Skip to content
This repository was archived by the owner on Jan 6, 2026. It is now read-only.

Commit d5e66f2

Browse files
author
Nikolas Haimerl
committed
merged with main
2 parents ec73596 + fbb8ef7 commit d5e66f2

29 files changed

+468
-255
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @juliangruber @pyropy @NikolasHaimerl

.github/workflows/deploy.yml

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ name: Deploy Observable Dashboard to Cloudflare Pages
22

33
on:
44
push:
5-
branches: [ main ]
5+
branches: [main]
66
schedule:
7-
- cron: "0 20 * * *"
7+
- cron: '0 20 * * *'
88

99
concurrency:
1010
group: ${{ github.workflow }}-${{ github.ref }}
@@ -19,28 +19,28 @@ jobs:
1919
environment: default
2020

2121
steps:
22-
- name: Checkout repository
23-
uses: actions/checkout@v4
24-
25-
- name: Install Node.js
26-
uses: actions/setup-node@v4
27-
with:
28-
node-version: 20
29-
cache: npm
30-
31-
- name: Install dependencies
32-
run: npm ci
33-
34-
- name: Build project
35-
run: npm run build # Assumes your project has a build script in package.json
36-
env:
37-
API_TOKEN: ${{ secrets.API_TOKEN }}
38-
39-
- name: Deploy to Cloudflare Pages
40-
uses: cloudflare/pages-action@v1
41-
with:
42-
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
43-
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
44-
projectName: spark-dashboard # Replace with your Cloudflare Pages project name
45-
directory: ./dist # Replace with your output directory after build
22+
- name: Checkout repository
23+
uses: actions/checkout@v4
24+
25+
- name: Install Node.js
26+
uses: actions/setup-node@v4
27+
with:
28+
node-version: 20
29+
cache: npm
30+
31+
- name: Install dependencies
32+
run: npm ci
33+
34+
- name: Build project
35+
run: npm run build # Assumes your project has a build script in package.json
36+
env:
37+
API_TOKEN: ${{ secrets.API_TOKEN }}
38+
39+
- name: Deploy to Cloudflare Pages
40+
uses: cloudflare/pages-action@v1
41+
with:
42+
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
43+
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
44+
projectName: spark-dashboard # Replace with your Cloudflare Pages project name
45+
directory: ./dist # Replace with your output directory after build
4646

.github/workflows/test.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Test Observable Dashboard
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
test:
9+
runs-on: ubuntu-latest
10+
permissions:
11+
contents: read
12+
environment: default
13+
14+
steps:
15+
- name: Check out repository
16+
uses: actions/checkout@v4
17+
18+
- name: Install Node.js
19+
uses: actions/setup-node@v4
20+
with:
21+
node-version: 20
22+
23+
- name: Install dependencies
24+
run: npm ci
25+
26+
- name: Test project
27+
run: npm test

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
src/.observablehq

.prettierrc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"singleQuote": true,
3+
"semi": false
4+
}

README.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This is an [Observable Framework](https://observablehq.com/framework) app runnin
44

55
## Development
66

7-
To start the local preview server, run:
7+
To start the local preview server, run:
88

99
```
1010
npm run dev
@@ -47,11 +47,11 @@ A typical Framework project looks like this:
4747

4848
## Command reference
4949

50-
| Command | Description |
51-
| ----------------- | -------------------------------------------------------- |
52-
| `npm install` | Install or reinstall dependencies |
53-
| `npm run dev` | Start local preview server |
54-
| `npm run build` | Build your static site, generating `./dist` |
55-
| `npm run deploy` | Deploy your app to Observable |
56-
| `npm run clean` | Clear the local data loader cache |
57-
| `npm run observable` | Run commands like `observable help` |
50+
| Command | Description |
51+
| -------------------- | ------------------------------------------- |
52+
| `npm install` | Install or reinstall dependencies |
53+
| `npm run dev` | Start local preview server |
54+
| `npm run build` | Build your static site, generating `./dist` |
55+
| `npm run deploy` | Deploy your app to Observable |
56+
| `npm run clean` | Clear the local data loader cache |
57+
| `npm run observable` | Run commands like `observable help` |

observablehq.config.js

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
import { jsonFetcher } from "./src/data/json-fetcher.js";
2-
import { getDateXDaysAgo } from "./src/utils/date-utils.js";
1+
import { jsonFetcher } from './src/data/json-fetcher.js'
2+
import { getDateXDaysAgo } from './src/utils/date-utils.js'
33

4-
const start = '2024-04-07';
5-
const end = getDateXDaysAgo(1);
4+
const start = '2024-04-07'
5+
const end = getDateXDaysAgo(1)
66

7-
const result = await jsonFetcher(`https://stats.filspark.com/miners/retrieval-success-rate/summary?from=${start}&to=${end}`)
8-
const providerPaths = result.map(provider => `/provider/${provider.miner_id}`);
7+
const result = await jsonFetcher(
8+
`https://stats.filspark.com/miners/retrieval-success-rate/summary?from=${start}&to=${end}`,
9+
)
10+
const providerPaths = result.map((provider) => `/provider/${provider.miner_id}`)
911

1012
// See https://observablehq.com/framework/config for documentation.
1113
export default {
1214
// The app’s title; used in the sidebar and webpage titles.
13-
title: "spark-dash",
15+
title: 'Spark Dashboard',
1416

1517
// The pages and sections in the sidebar. If you don’t specify this option,
1618
// all pages will be listed in alphabetical order. Listing pages explicitly
@@ -29,10 +31,10 @@ export default {
2931
head: '<link rel="icon" href="media/spark-with-bbox.png" type="image/png" sizes="32x32"><script defer data-domain="dashboard.filspark.com" src="https://plausible.io/js/script.js"></script>',
3032

3133
// The path to the source root.
32-
root: "src",
34+
root: 'src',
3335

3436
// Some additional configuration options and their defaults:
35-
// theme: "default", // try "light", "dark", "slate", etc.
37+
theme: 'dark', // try "light", "dark", "slate", etc.
3638
// header: "", // what to show in the header (HTML)
3739
// footer: "Built with Observable.", // what to show in the footer (HTML)
3840
sidebar: false, // whether to show the sidebar
@@ -44,4 +46,4 @@ export default {
4446
// typographer: false, // smart quotes and other typographic improvements
4547
// cleanUrls: true, // drop .html from URLs
4648
dynamicPaths: providerPaths,
47-
};
49+
}

package-lock.json

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"build": "observable build",
77
"dev": "observable preview",
88
"deploy": "observable deploy",
9-
"observable": "observable"
9+
"observable": "observable",
10+
"test": "prettier --check ."
1011
},
1112
"dependencies": {
1213
"@observablehq/framework": "^1.12.0",
@@ -16,6 +17,7 @@
1617
"p-retry": "^6.2.1"
1718
},
1819
"devDependencies": {
20+
"prettier": "^3.4.2",
1921
"rimraf": "^5.0.5"
2022
},
2123
"engines": {

src/components/histogram.js

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,58 @@
11
import * as Plot from 'npm:@observablehq/plot'
22
import * as d3 from 'd3'
33

4-
export function Histogram (events, { width, title, thresholds }) {
5-
const data = events.flatMap(d => {
6-
let res = Array.from([ { type: 'HTTP or Graphsync', value: d.success_rate * 100 }]);
4+
export function Histogram(events, { width, title, thresholds }) {
5+
const data = events.flatMap((d) => {
6+
const res = Array.from([
7+
{ type: 'HTTP or Graphsync', value: d.success_rate * 100 },
8+
])
79
// We only want to count the http success rate if it is not null
810
// When querying the summary per miner, an http of null means that the miner has never been tested using http
9-
// A value of 0 means that the miner has been tested at some point in time but has never been successful.
11+
// A value of 0 means that the miner has been tested at some point in time but has never been successful.
1012
if (d.success_rate_http != null) {
11-
res.push({ type: 'HTTP only', value: d.success_rate_http * 100 })
13+
res.push({ type: 'HTTP only', value: d.success_rate_http * 100 })
1214
}
1315
return res
14-
}
15-
)
16+
})
1617

17-
// We want to create a number of evenly spaced bins (thresholds) in which we can collect each success rate value into
18-
const binnedData = Array.from(new Set(data.map(item => item.type))).flatMap(type => {
19-
const groupData = data.filter(d => d.type === type)
20-
const bins = d3
21-
.bin()
22-
// The rates are percentage values, so the domain of the bins will be 0 to 100
23-
.domain([0, 100])
24-
.thresholds(thresholds)(groupData.map(d => d.value))
18+
// We want to create a number of evenly spaced bins (thresholds) in which we can collect each success rate value into
19+
const binnedData = Array.from(new Set(data.map((item) => item.type))).flatMap(
20+
(type) => {
21+
const groupData = data.filter((d) => d.type === type)
22+
const bins = d3
23+
.bin()
24+
// The rates are percentage values, so the domain of the bins will be 0 to 100
25+
.domain([0, 100])
26+
.thresholds(thresholds)(groupData.map((d) => d.value))
2527

26-
return bins.map(bin => ({
27-
type,
28-
threshold: `${bin.x0}${bin.x1}`,
29-
count: bin.length
30-
}))
31-
})
28+
return bins.map((bin) => ({
29+
type,
30+
threshold: `${bin.x0}${bin.x1}`,
31+
count: bin.length,
32+
}))
33+
},
34+
)
3235

3336
return Plot.plot({
3437
marks: [
35-
Plot.barY(
36-
binnedData,
37-
{
38-
fx: 'threshold',
39-
y: 'count',
40-
x: 'type',
41-
fill: 'type'
42-
}
43-
)
38+
Plot.barY(binnedData, {
39+
fx: 'threshold',
40+
y: 'count',
41+
x: 'type',
42+
fill: 'type',
43+
}),
4444
],
4545
y: { grid: true },
4646
x: {
4747
axis: null,
48-
padding: 0.1
48+
padding: 0.1,
4949
},
5050
color: {
5151
legend: true,
52-
label: 'Type'
52+
label: 'Type',
5353
},
5454
width,
5555
title,
56-
facet: { label: 'Rate Ranges in %' }
56+
facet: { label: 'Rate Ranges in %' },
5757
})
5858
}

0 commit comments

Comments
 (0)