Skip to content

Commit

Permalink
add graphql2chartjs to community tools (#1669)
Browse files Browse the repository at this point in the history
  • Loading branch information
wawhal authored and shahidhk committed Mar 14, 2019
0 parents commit 64c7315
Show file tree
Hide file tree
Showing 52 changed files with 15,370 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
lib
bundle
3 changes: 3 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
src
example
bundle
229 changes: 229 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
# graphql2chartjs - Instant realtime charts using GraphQL

`graphql2chartjs` reshapes your GraphQL data as per the [ChartJS](https://chartjs.org) API. This makes it easy to query a GraphQL API and render the output as a ChartJS chart.

For example, if you're using Postgres and [Hasura](https://hasura.io), this is what using `graphql2chartjs` looks like:

![graphql2chartjs](https://storage.googleapis.com/graphql-engine-cdn.hasura.io/img/graphql2chartjs-explained.png)



## Demos & sandbox
We've set up a GraphQL server with continuously changing data, so that you can try graphql2chartjs out easily.


|[View live charts](https://graphql2chartjs-examples.herokuapp.com) | [Edit in sandbox](https://codesandbox.io/s/p2wpj1o8pj) | [Open GraphiQL](https://g2c-examples-graphiql.herokuapp.com/) |
|---|---|---|

![realtime chart with live data](https://storage.googleapis.com/graphql-engine-cdn.hasura.io/assets/graphql2chartjs/live-chart.gif)

The demo above cover the following types of charts: [basic](https://graphql2chartjs-examples.herokuapp.com/#bar), [multiple datasets](https://graphql2chartjs-examples.herokuapp.com/#multi-bar), [mixed chart-types](https://graphql2chartjs-examples.herokuapp.com/#mixed), [realtime chart with live data](https://graphql2chartjs-examples.herokuapp.com/#live-chart), [realtime time-series](https://graphql2chartjs-examples.herokuapp.com/#timeseries-chart)

## Usage with Hasura
Hasura gives you an instant realtime GraphQL API on an existing Postgres database. You can create views to capture analytics and aggregations on your database and instantly turn them into charts.

Watch this video below to see a demo/tutorial of using Hasura with an existing Postgres database, creating views and building charts.

<div style="text-align:center">
<a href="https://www.youtube.com/watch?v=153iv1-qFuc&feature=youtu.be" target="_blank">
<img src="https://storage.googleapis.com/graphql-engine-cdn.hasura.io/assets/graphql2chartjs/g2c-youtube-embed.png" width="1000px" alt="youtube video demo">
</a>
</div>


## Example usage with react, apollo and react-chartjs-2

```javascript
import {Query} from 'react-apollo';
import gql from 'graphql-tag';
import graphql2chartjs from 'graphql2chartjs';
import {Bar} from 'react-chartjs-2';

const Chart = () => (
<Query
query={gql`
query {
Articles: articleStats {
label: title
data: num_likes
}
}`}
}>
{({data} => {
if (data) {
const g2c = new graphql2chartjs(data, 'bar');
return (<Bar data={g2c.data} />);
}
return null;
}
</Query>
);
```
## Mapping GraphQL queries to ChartJS charts
Different types of charts need different structures in their datasets.
For example a bar chart dataset needs labels and data associated for each label; the ChartJS API refers to this as `label` and `data`. Once you alias fields in your graphql query to `label` and `data`, and pass the response through `graphql2chartjs`, your dataset is ready to be used by bar chart in chartjs.
### Bar / Line / Doughnut / Pie / Radar / Polar Area / Area
Charts of this type need 2 data inputs, `label` and `data`.
```graphql
query {
ArticleLikes : articles {
label: title
data: likes
}
}
```
### Scatter / Bubble
Charts of this type need 2 data inputs: `data_x`, `data_y` (and `data_r` for bubble).
```graphql
query {
ArticleLikesVsComments : articles {
data_x: num_likes
data_y: num_comments
}
}
```
### Time series (line / bar)
Charts of this type need 2 data inputs, `data_x` or `data_t` and `data_y`. Note that there is no `label`.
```graphql
query {
StockPrices : stockprice {
data_t: created
data_y: price
}
}
```
## graphql2chartjs usage
graphql2chartjs works in 3 steps:
1. Initialise graphql2chartjs: `const g2c = new graphql2chartjs()`
2. Add data from your graphql response: `g2c.add(graphqlResponse.data, 'line')`
3. Set your chart data to the data properly of the graphql2chartjs instance: `g2c.data`
### Step 1: Initialiase with data: `new graphql2chartjs()`
#### Option 1: Initialise with data and chart type
**`graphql2chartjs(data, chartType)`**
```javascript
const g2c = new graphql2chartjs(data, 'bar');
```
- `data`: This is your GraphQL response. This data should have fields `label`, `data` etc. as per the GraphQL querying described above.
- `chartType`: This is a string that represents valid values of what your chart type is. Valid values include `'line'`, `'bar'`, `'radar'`, `'doughnut'`, `'pie'`, `'polarArea'`, `'bubble'`, `'scatter'`.
**Notes:**
- This is the simplest way of using `graphql2chartjs`
- If you have multiple datasets, all of the datasets will be rendered automatically as the same type of chart
- To customise the UI options of the rendered chart like colors or to create a mixed type chart (one dataset is rendered as a line chart, another as a bar chart) use the next initialisation method instead of this one.
#### Option 2: Initialise with data and a transform function
**`graphql2chartjs(data, transform)`**
The transformation function can add chartjs dataset props or even modify the record data:
```javascript
const g2c = new graphql2chartjs(data, (datasetName, dataPoint) => {
return {
chartType: 'bar',
backgroundColor: 'yellow'
};
});
```
- `transform(datasetName, dataPoint)`: This function defined by you can take the name of the dataset and the data record that comes from the GraphQL response and returns an object that can should have the `chartType` key and optionally other keys that specify other dataset properties.
- The object returned by this function should look like the following:
```javascript
{
chartType: 'line', // Or 'line', 'bar', 'radar', 'doughnut', 'pie', 'polarArea', 'bubble', 'scatter'
<other keys as per the dataset properties per chart. Refer to the link below>
}
```
- `chartType`: This should be a string value, one of: `'line'`, `'bar'`, `'radar'`, `'doughnut'`, `'pie'`, `'polarArea'`, `'bubble'`, `'scatter'`
- Other keys in this object should be dataset properties. These properties are slightly different for different chart types.
- Line chart: https://www.chartjs.org/docs/latest/charts/line.html#dataset-properties
- Bar chart: https://www.chartjs.org/docs/latest/charts/bar.html#dataset-properties
- Radar chart: https://www.chartjs.org/docs/latest/charts/radar.html#dataset-properties
- Doughnut & Pie: https://www.chartjs.org/docs/latest/charts/doughnut.html#dataset-properties
- Polar: https://www.chartjs.org/docs/latest/charts/polar.html#dataset-properties
- Bubble: https://www.chartjs.org/docs/latest/charts/bubble.html#dataset-properties
- Scatter: https://www.chartjs.org/docs/latest/charts/scatter.html#dataset-properties
### Step 2: Now create your cchart with data - `g2c.data`
`g2c.data` gives you access to the latest ChartJS data that can be passed to your chart.
1. Javascript
```javascript
var myChart = new Chart(ctx, { data: g2c.data });
```
2. react-chartjs-2
```javascript
<Bar data={g2c.data} />
```
### Step 3: (optional) Incrementally add data for your chart
**`g2c.add()`**
Once you've initialised a `graphql2chartjs` object, you can use the `add` function to add data for the first time or incrementally:
```javascript
await data = runQuery(..);

// Add for a chart type
g2c.add(data, 'line');

// Add with a transformation function to change UI props for the new data added or udpated
g2c.add(data, (datasetName, dataPoint) => {
chartType: 'line',
pointBackgroundColor: 'yellow'
});
```
## Installation
### Via npm
```
npm install --save graphql2chartjs
```
### Use in a script tag
```html
<script src="https://storage.googleapis.com/graphql-engine-cdn.hasura.io/tools/graphql2chartjs/index.js" type="application/javascript"></script>
```
## Reforming the data
### `reform()`
You can reform the existing data in your `graphql2chartjs` instance using the reform function that takes a reformer function as an argument. This reformer function is run over every datapoint in every dataset. For instance, to scale the x and y coordinates, you would do something like:
```
g2c.reform((datasetName, dataPoint) => {
// scale the x, y coordinates
return {
data_x: scalingFactor(dataPoint.data_x),
data_y: scalingFactor(dataPoint.data_y)
}
})
```
16 changes: 16 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const presets = [
[
"@babel/env",
{
targets: {
edge: "17",
firefox: "60",
chrome: "67",
safari: "11.1",
},
useBuiltIns: "usage",
},
],
];

module.exports = { presets };
15 changes: 15 additions & 0 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Example

This example app is live at https://graphql2chartjs-examples.herokuapp.com

## Client (React app)

The app directory has the React app that is already set up with a backend.

## Migrations (Hasura migrations)

The hasura directory contains the migrations for the Hasura GraphQL Engine backend that is setup at https://graphql2chartjs.hasura.app and has a GraphQL endpoint https://graphqlchartjs.hasura.app/v1alpha1/graphql

## Scripts

The scripts directory contains the scripts that are run to populate the backend with sample data.
2 changes: 2 additions & 0 deletions example/app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
build
6 changes: 6 additions & 0 deletions example/app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
To run this example:

```
npm install
npm start
```
39 changes: 39 additions & 0 deletions example/app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"name": "graphql2chartjs-examples",
"version": "0.1.0",
"private": true,
"dependencies": {
"apollo-boost": "^0.1.28",
"apollo-link-ws": "^1.0.14",
"bootstrap": "^4.3.1",
"chart.js": "^2.7.3",
"graphql": "^14.1.1",
"graphql2chartjs": "^0.2.1",
"react": "^16.8.3",
"react-apollo": "^2.4.1",
"react-bootstrap": "^1.0.0-beta.5",
"react-chartjs-2": "^2.7.4",
"react-dom": "^16.8.3",
"react-scripts": "2.1.5",
"react-syntax-highlighter": "^10.1.3",
"subscriptions-transport-ws": "^0.9.15"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"devDependencies": {
"@playlyfe/gql": "^2.6.1"
}
}
Binary file added example/app/public/favicon.ico
Binary file not shown.
48 changes: 48 additions & 0 deletions example/app/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="theme-color" content="#000000" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous"/>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css"
integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS"
crossorigin="anonymous"
/>
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>graphql2chartjs examples</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
15 changes: 15 additions & 0 deletions example/app/public/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
Loading

0 comments on commit 64c7315

Please sign in to comment.