-
Notifications
You must be signed in to change notification settings - Fork 141
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 16 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 | ||||
---|---|---|---|---|---|---|
|
@@ -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}); | ||||||
|
@@ -15,7 +14,6 @@ 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"; | ||||||
``` | ||||||
|
||||||
|
@@ -59,7 +57,7 @@ function getCompareValue(data, metric) { | |||||
function lineChart(data, {width, height, metric}) { | ||||||
return Plot.plot({ | ||||||
width, | ||||||
height: 97, | ||||||
height: 94, | ||||||
axis: null, | ||||||
insetTop: 10, | ||||||
insetLeft: -15, | ||||||
|
@@ -78,11 +76,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 +274,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> | ||||||
<span class="small">${((v) => html`<span class="${v > 0 ? "green" : v < 0 ? "red" : ""}">${bigNumber(v)} ${v > 0 ? "↗︎" : v < 0 ? "↘︎" : ""}`)(getCompareValue(summary, 'active28d'))}</span> | ||||||
${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> | ||||||
<span class="small">${((v) => html`<span class="${v > 0 ? "green" : v < 0 ? "red" : ""}">${percent(v)} ${v > 0 ? "↗︎" : v < 0 ? "↘︎" : ""}`)(getCompareValue(summary, 'engagementRate'))}</span> | ||||||
Fil marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
${resize((width) => lineChart(summary, {width, metric: 'engagementRate'}))} | ||||||
Fil marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
</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> | ||||||
<span class="small">${((v) => html`<span class="${v > 0 ? "green" : v < 0 ? "red" : ""}">${percent(v)} ${v > 0 ? "↗︎" : v < 0 ? "↘︎" : ""}`)(getCompareValue(summary, 'wauPerMau'))}</span> | ||||||
Fil marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
${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> | ||||||
<span class="small">${((v) => html`<span class="${v > 0 ? "green" : v < 0 ? "red" : ""}">${bigNumber(v)} ${v > 0 ? "↗︎" : v < 0 ? "↘︎" : ""}`)(getCompareValue(summary, 'engagedSessions'))}</span> | ||||||
Fil marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
${resize((width) => areaChart(summary, {width, metric: 'engagedSessions'}))} | ||||||
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.
Suggested change
|
||||||
</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.
Fil marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -6,7 +6,6 @@ theme: dashboard | |||||||
# Plot | ||||||||
|
||||||||
```js | ||||||||
import {BigNumber} from "./components/bigNumber.js"; | ||||||||
import {DailyPlot, today, start} from "./components/dailyPlot.js"; | ||||||||
``` | ||||||||
|
||||||||
|
@@ -21,6 +20,9 @@ const stars = FileAttachment("data/plot-github-stars.csv").csv({typed: true}); | |||||||
const lastMonth = d3.utcDay.offset(today, -28); | ||||||||
const lastWeek = d3.utcDay.offset(today, -7); | ||||||||
const x = {domain: [start, today]}; | ||||||||
function trend(value, format) { | ||||||||
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.
Suggested change
This sort of function should have a default format, or better, allow the format to be optionally specified as a function (and promote to a function when a string). If I wanted it to be reusable, I’d probably also take an options object instead of |
||||||||
return html`<span class="${value > 0 ? "green" : value < 0 ? "red" : "muted"}">${d3.format(format)(value)} ${value > 0 ? "↗︎" : value < 0 ? "↘︎" : ""}`; | ||||||||
} | ||||||||
``` | ||||||||
|
||||||||
```js | ||||||||
|
@@ -43,17 +45,29 @@ const burndown = issues | |||||||
``` | ||||||||
|
||||||||
<div class="grid grid-cols-4" style="grid-auto-rows: 86px;"> | ||||||||
<div class=card>${BigNumber(versions.at(-1).version, { | ||||||||
title: "Current release", | ||||||||
href: `https://github.com/observablehq/plot/releases/tag/v${versions.at(-1).version}`, | ||||||||
trend: d3.utcDay.count(versions.at(-1).date, Date.now()), | ||||||||
trendFormat: d => `${d === 0 ? "today" : d===1 ? "yesterday" : `${d} days ago`}`, | ||||||||
trendColor: "#888", | ||||||||
trendArrow: null | ||||||||
})}</div> | ||||||||
<div class=card>${BigNumber(stars.length, {title: "GitHub stars", trend: stars.filter((d) => d.starred_at >= lastWeek).length, trendFormat: "+", trendTitle: "Since last week"})}</div> | ||||||||
<div class=card>${BigNumber(downloads[0].value, {title: "Daily npm downloads", trend: downloads[7].value ? (downloads[0].value - downloads[7].value) / downloads[7].value : undefined, trendTitle: "Compared to last week"})}</div> | ||||||||
<div class=card>${BigNumber(d3.sum(downloads, (d) => d.value), {title: "Total npm downloads"})}</div> | ||||||||
<div class="card"> | ||||||||
<h2>Current release</h2> | ||||||||
<span class="big">${versions.at(-1).version}</span> | ||||||||
<a href="https://github.com/observablehq/plot/releases" style="color: inherit;"> | ||||||||
${((days) => days === 0 ? "today" : days === 1 ? "yesterday" : `${days} days ago`)(d3. utcDay.count(versions.at(-1).date, Date.now()))} | ||||||||
Fil marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
</a> | ||||||||
</div> | ||||||||
<div class="card"> | ||||||||
<h2>GitHub stars</h2> | ||||||||
<span class="big">${d3.format(",")(stars.length)}</span> | ||||||||
<span class="green">${d3.format("+")(d3.sum(stars, (d) => d.starred_at >= lastWeek))} ↗︎</ span> | ||||||||
Fil marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
</div> | ||||||||
<div class="card"> | ||||||||
<h2>Daily npm downloads</h2> | ||||||||
<span class="big">${d3.format(",")(downloads[0].value)}</span> | ||||||||
${trend(downloads[7].value | ||||||||
? (downloads[0].value - downloads[7].value) / downloads[7].value | ||||||||
: undefined, d3.format("+.1%"))} | ||||||||
</div> | ||||||||
<div class="card"> | ||||||||
<h2>Total npm downloads</h2> | ||||||||
<span class="big">${d3.format(",")(d3.sum(downloads, (d) => d.value))} | ||||||||
Fil marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
</div> | ||||||||
</div> | ||||||||
|
||||||||
<div class="card grid grid-cols-1" style="grid-auto-rows: calc(260px + 2rem);"> | ||||||||
|
@@ -100,10 +114,22 @@ const burndown = issues | |||||||
</div> | ||||||||
|
||||||||
<div class="grid grid-cols-4" style="grid-auto-rows: 86px;"> | ||||||||
<div class=card>${BigNumber(issues.filter((d) => !d.pull_request && d.state === "open").length, {title: "Open issues", href: "https://github.com/observablehq/plot/issues"})}</div> | ||||||||
<div class=card>${BigNumber(issues.filter((d) => !d.pull_request && d.open >= lastMonth).length, {title: "Opened issues, 28d"})}</div> | ||||||||
<div class=card>${BigNumber(issues.filter((d) => !d.pull_request && d.close >= lastMonth).length, {title: "Closed issues, 28d"})}</div> | ||||||||
<div class=card>${BigNumber(issues.filter((d) => d.pull_request && d.state === "open" && !d.draft).length, {title: "Open PRs", href: "https://github.com/observablehq/plot/pulls?q=is%3Apr+is%3Aopen+draft%3Afalse"})}</div> | ||||||||
<div class="card"> | ||||||||
<h2>Open issues</h2> | ||||||||
<a href="https://github.com/observablehq/plot/issues" class="big" style="color: inherit;">${d3.format(",")(d3.sum(issues, (d) => !d.pull_request && d.state === "open"))}</a> | ||||||||
</div> | ||||||||
<div class="card"> | ||||||||
<h2>Opened issues, 28d</h2> | ||||||||
<span class="big">${d3.format(",")(d3.sum(issues, (d) => !d.pull_request && d.open >= lastMonth))}</span> | ||||||||
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 a big fan of the |
||||||||
</div> | ||||||||
<div class="card"> | ||||||||
<h2>Closed issues, 28d</h2> | ||||||||
<span class="big">${d3.format(",")(d3.sum(issues, (d) => !d.pull_request && d.close >= lastMonth))}</span> | ||||||||
</div> | ||||||||
<div class="card"> | ||||||||
<h2>Open PRs</h2> | ||||||||
<a class="big" href="https://github.com/observablehq/plot/pulls?q=is%3Apr+is%3Aopen+draft%3Afalse" style="color: inherit;">${d3.format(",")(d3.sum(issues, (d) => d.pull_request && d.state === "open" && !d.draft))}</a> | ||||||||
</div> | ||||||||
</div> | ||||||||
|
||||||||
<div class="grid grid-cols-2" style="grid-auto-rows: 276px;"> | ||||||||
|
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.
I think this has too much complexity to be practical. We need to find a way to encapsulate this.
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.
I've put the logic in a function of (value, format).
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.
I don’t see the change here. It looks like you did this for the Plot example but not the Google Analytics one. 😓
Also, I don’t think this really solves the problem I raised because someone still has to find the
trend
function you wrote — we need to think about how to incorporate a practical solution “in the box” (in the standard library or default CSS).(And also I want inline expressions for attributes #32 or even better server-side rendering #234…)