Skip to content

Commit 711701b

Browse files
authored
examples: Words of Open Source (#4058)
* examples: Words of Open Source * Migrate to cube-example-wrapper
1 parent b5cc5b5 commit 711701b

File tree

13 files changed

+4477
-0
lines changed

13 files changed

+4477
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module.exports = {
2+
orchestratorOptions: {
3+
queryCacheOptions: {
4+
queueOptions: {
5+
concurrency: 20
6+
}
7+
}
8+
}
9+
};
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
CUBE_API=https://emerald-llama.gcp-us-central1.cubecloudapp.dev/cubejs-api/v1
2+
CUBE_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjEwMDAwMDAwMDAsImV4cCI6NTAwMDAwMDAwMH0.OHZOpOBVKr-sCwn8sbZ5UFsqI3uCs6e4omT7P6WVMFw
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.parcel-cache
2+
dist
3+
node_modules
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"siteId": "11f75d70-722b-4fa7-930e-613486360bc9"
3+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"devDependencies": {
3+
"parcel": "^2.2.1"
4+
},
5+
"dependencies": {
6+
"@cubejs-client/core": "^0.29.23",
7+
"@cubejs-client/react": "^0.29.24",
8+
"cube-example-wrapper": "^1.0.20",
9+
"date-fns": "^2.28.0",
10+
"react": "^17.0.2",
11+
"react-dom": "^17.0.2",
12+
"recharts": "^2.1.8"
13+
},
14+
"license": "MIT"
15+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { useState, useEffect } from 'react'
2+
import { AreaChart, Area, XAxis, ResponsiveContainer } from 'recharts';
3+
import { fetchData } from './api'
4+
import * as classes from './App.module.css'
5+
6+
export function App() {
7+
const [ word, setWord ] = useState("FOSDEM")
8+
const [ data, setData ] = useState([])
9+
10+
useEffect(() => {
11+
fetchData(word).then(data => setData(data))
12+
}, [ word ])
13+
14+
return (
15+
<>
16+
<div className={classes.root}>
17+
<div className={classes.inputWrapper}>
18+
<input
19+
defaultValue={word}
20+
onKeyDown={e => e.key === 'Enter' && e.target.value && setWord(e.target.value)}
21+
className={classes.input}
22+
/>
23+
<div className={classes.enterSymbol}></div>
24+
</div>
25+
26+
<div className={classes.chartWrapper}>
27+
<ResponsiveContainer width="100%" height="100%">
28+
<AreaChart
29+
data={data}
30+
margin={{ top: 3, right: 20, left: 20 }}
31+
>
32+
<XAxis
33+
dataKey="name"
34+
axisLine={false}
35+
interval={0}
36+
tickSize={0}
37+
tickMargin={15}
38+
/>
39+
<Area
40+
type="basis"
41+
dataKey="data"
42+
stroke="#c93324"
43+
fill="#eddedd"
44+
strokeWidth={3}
45+
/>
46+
</AreaChart>
47+
</ResponsiveContainer>
48+
</div>
49+
</div>
50+
</>
51+
)
52+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
.root {
2+
font-family: -apple-system, sans-serif;
3+
box-sizing: border-box;
4+
margin: auto;
5+
padding: 0px 25px 50px;
6+
text-align: center;
7+
width: 90%;
8+
}
9+
10+
.inputWrapper {
11+
display: grid;
12+
grid-template-columns: 1fr min-content;
13+
margin: 0 auto;
14+
width: 40%;
15+
min-width: 300px;
16+
}
17+
18+
.input {
19+
border: 2px solid #ccc;
20+
color: #333;
21+
font-size: 20px;
22+
padding: 7px 10px;
23+
outline: none;
24+
}
25+
26+
.enterSymbol {
27+
font-size: 20px;
28+
position: relative;
29+
top: 30%;
30+
left: 30%;
31+
}
32+
33+
.chartWrapper {
34+
height: 400px;
35+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import cubejs from '@cubejs-client/core'
2+
import { format } from 'date-fns'
3+
4+
const cubejsApi = cubejs(
5+
process.env.CUBE_TOKEN,
6+
{ apiUrl: process.env.CUBE_API }
7+
)
8+
9+
function createQuery(word) {
10+
return ({
11+
measures: [ "Words.count" ],
12+
timeDimensions: [{
13+
dimension: "Words.timestamp",
14+
granularity: "month"
15+
}],
16+
filters: !word ? [] : [{
17+
member: "Words.word",
18+
operator: "equals",
19+
values: [ word.toLowerCase() ]
20+
}]
21+
})
22+
}
23+
24+
function formatDate(date) {
25+
let month = format(date, 'MMM')
26+
let year = format(date, 'yyyy')
27+
return month == 'Jan' ? year : ''
28+
}
29+
30+
function mapData(data, maxValues) {
31+
return maxValues.map(row => {
32+
let count = data.find(e => e["Words.timestamp"] === row["Words.timestamp"])
33+
34+
return ({
35+
name: formatDate(new Date(row["Words.timestamp"])),
36+
data: !count ? 0 : parseInt(count["Words.count"]) / parseInt(row["Words.count"])
37+
})
38+
})
39+
}
40+
41+
let maxValues = undefined
42+
43+
function fetchMaxValue() {
44+
return new Promise((resolve, reject) => {
45+
if (maxValues) {
46+
resolve(maxValues)
47+
return
48+
}
49+
50+
cubejsApi
51+
.load(createQuery())
52+
.then(resultSet => {
53+
maxValues = resultSet.rawData()
54+
resolve(maxValues)
55+
})
56+
.catch(reject)
57+
})
58+
}
59+
60+
export function fetchData(word) {
61+
return cubejsApi
62+
.load(createQuery(word))
63+
.then(resultSet => {
64+
return fetchMaxValue()
65+
.then(maxValues => {
66+
return mapData(resultSet.rawData(), maxValues)
67+
})
68+
})
69+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<title>Words of Open Source</title>
6+
</head>
7+
<body>
8+
<div id="app"></div>
9+
<script type="module" src="index.js"></script>
10+
</body>
11+
</html>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import createExampleWrapper from "cube-example-wrapper";
2+
3+
createExampleWrapper({
4+
title: "Words of Open Source",
5+
text: `
6+
<p>Ratio of the number of commits containing a certain word to the total number of commits.</p>
7+
<p>Based on the public dataset of <a href="https://console.cloud.google.com/marketplace/product/github/github-repos">GitHub Activity Data</a> and powered by <a href="https://cube.dev">Cube</a>.</p>
8+
`,
9+
});
10+
11+
import ReactDOM from "react-dom";
12+
import { App } from "./App";
13+
14+
const app = document.getElementById("app");
15+
ReactDOM.render(<App />, app);

0 commit comments

Comments
 (0)