Skip to content

Commit a4cbcdc

Browse files
committed
interactive demo via @wq/analyst
1 parent d00992c commit a4cbcdc

File tree

18 files changed

+279
-14
lines changed

18 files changed

+279
-14
lines changed

.github/workflows/pages.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,16 @@ jobs:
3333
run: |
3434
curl -L -s https://unpkg.com/wq > docs/js/wq.js
3535
curl -L -s https://unpkg.com/@wq/markdown@latest > docs/js/markdown.js
36+
curl -L -s https://unpkg.com/@wq/analyst@next > docs/js/analyst.js
37+
curl -L -s https://unpkg.com/@wq/chart@next > docs/js/chart.js
3638
sed -i "s/^import\(.*\)https:\/\/unpkg.com\/wq/import\1.\/wq.js/" docs/js/*.js
3739
sed -i "s/^import\(.*\)https:\/\/unpkg.com\/@wq\/markdown@next/import\1.\/markdown.js/" docs/js/*.js
40+
sed -i "s/^import\(.*\)https:\/\/unpkg.com\/@wq\/analyst/import\1.\/analyst.js/" docs/js/*.js
41+
sed -i "s/^import\(.*\)https:\/\/unpkg.com\/@wq\/chart/import\1.\/chart.js/" docs/js/*.js
42+
- name: Export Django site
43+
run: |
44+
python -m pip install django djangorestframework pandas openpyxl matplotlib
45+
python -m unittest tests.generate_docs
3846
- name: Build with Jekyll
3947
uses: actions/jekyll-build-pages@v1
4048
with:

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@
55
build
66
dist
77
node_modules
8+
docs/static
9+
docs/timeseries.*
10+
docs/weather.*

docs/_layouts/default.html

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@
1313
margin-right: auto;
1414
max-width: 100%;
1515
}
16+
.MuiAppBar-colorPrimary img {
17+
border-radius: 4px;
18+
padding-left: 4px;
19+
padding-right: 4px;
20+
margin-left: -18px !important;
21+
margin-top: 4px;
22+
margin-bottom: 4px;
23+
background-color: rgba(0, 0, 0, 0.6);
24+
}
1625
</style>
1726
<script async src="https://www.googletagmanager.com/gtag/js?id=G-LTN8HFGJT2"></script>
1827
<script>

docs/index.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,32 @@ wq_config:
1212

1313
#### [Django REST Framework] + [pandas] = A Model-driven Visualization API
1414

15-
**Django REST Pandas** (DRP) provides a simple way to generate and serve [pandas] DataFrames via the [Django REST Framework]. The resulting API can serve up CSV (and a number of [other formats][formats] for consumption by a client-side visualization tool like [d3.js].
15+
**Django REST Pandas** (DRP) provides a simple way to generate and serve [pandas] DataFrames via the [Django REST Framework]. The resulting API can serve up CSV (and a number of [other formats][formats] for consumption by a client-side visualization tool like [@wq/analyst]:
16+
17+
```js
18+
// @wq/analyst
19+
{
20+
"title": "Live Demo",
21+
"url": "/weather.csv",
22+
"initial_rows": 10,
23+
"initial_order": {
24+
"date": "desc"
25+
},
26+
"formats": {
27+
"csv": "CSV",
28+
"xlsx": "Excel",
29+
"json": "JSON",
30+
"html": "HTML"
31+
}
32+
}
33+
```
1634

1735
[**Django REST Pandas on GitHub**](https://github.com/wq/django-rest-pandas)
1836

1937
[pandas]: https://pandas.pydata.org/
2038
[Django REST Framework]: https://www.django-rest-framework.org/
2139
[formats]: ./renderers/index.md
22-
[d3.js]: ./@wq/chart.md
40+
[@wq/analyst]: ./@wq/analyst.md
2341

2442
## News
2543

docs/js/$index.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,21 @@ layout: null
33
---
44

55
import wq, { modules } from 'https://unpkg.com/wq';
6-
import markdown, { renderers } from 'https://unpkg.com/@wq/markdown@next';
6+
import markdown, { components } from 'https://unpkg.com/@wq/markdown@next';
7+
import analyst from 'https://unpkg.com/@wq/analyst';
8+
9+
import Demo from './demo.js';
710

811
const React = modules['react'];
912
const { Typography, Link } = modules['@wq/material'];
1013

11-
wq.use(markdown);
14+
components.code = Demo;
15+
16+
wq.use([markdown, analyst]);
1217

1318
const config = {
1419
site_title: 'Django REST Pandas',
20+
logo: '/images/icons/django-rest-pandas.svg',
1521
store: {
1622
service: '',
1723
defaults: {
@@ -52,6 +58,7 @@ function pageConf(page) {
5258
icon: page.wq_config.icon_data ? page.wq_config.name : null,
5359
markdown: page.content,
5460
list: true,
61+
form: [],
5562
cache: 'all',
5663
can_change: false,
5764
can_add: false,

docs/js/demo.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { modules } from "https://unpkg.com/wq";
2+
import { components } from "https://unpkg.com/@wq/markdown";
3+
import { Analyst } from "https://unpkg.com/@wq/analyst";
4+
5+
const React = modules.react;
6+
const Code = components.code;
7+
8+
export default function CodeDetect(props) {
9+
const { children: value } = props;
10+
if (value.includes("// @wq/analyst")) {
11+
const config = parseConfig(value);
12+
if (config) {
13+
return React.createElement(Analyst, config);
14+
} else {
15+
return React.createElement(Code, {
16+
children: "// Error parsing @wq/analyst config\n\n" + value,
17+
});
18+
}
19+
} else {
20+
return React.createElement(Code, props);
21+
}
22+
}
23+
24+
function parseConfig(value) {
25+
value = value.replace("// @wq/analyst", "").trim();
26+
try {
27+
return JSON.parse(value);
28+
} catch {
29+
return null;
30+
}
31+
}

tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@
77
setup_test_environment()
88
django.setup()
99
call_command("makemigrations", "testapp", interactive=False)
10+
call_command("makemigrations", "weather", interactive=False)
1011
call_command("migrate", interactive=False)

tests/files/multitimeseries.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@
33
<html lang="en-us" dir="ltr">
44
<head>
55
<title>Multi Time Series</title>
6-
<link rel="stylesheet" href="admin/css/base.css">
6+
<link rel="stylesheet" href="/static/admin/css/base.css">
77

8-
<link rel="stylesheet" href="admin/css/dark_mode.css">
9-
<script src="admin/js/theme.js" defer></script>
8+
<link rel="stylesheet" href="/static/admin/css/dark_mode.css">
9+
<script src="/static/admin/js/theme.js" defer></script>
1010

1111

1212

13-
<link rel="stylesheet" type="text/css" href="admin/css/forms.css">
13+
<link rel="stylesheet" type="text/css" href="/static/admin/css/forms.css">
1414

1515

1616

1717

1818
<meta name="viewport" content="width=device-width, initial-scale=1.0">
19-
<link rel="stylesheet" href="admin/css/responsive.css">
19+
<link rel="stylesheet" href="/static/admin/css/responsive.css">
2020

2121

2222
<meta name="robots" content="NONE,NOARCHIVE">

tests/files/timeseries.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@
33
<html lang="en-us" dir="ltr">
44
<head>
55
<title>Time Series Custom</title>
6-
<link rel="stylesheet" href="admin/css/base.css">
6+
<link rel="stylesheet" href="/static/admin/css/base.css">
77

8-
<link rel="stylesheet" href="admin/css/dark_mode.css">
9-
<script src="admin/js/theme.js" defer></script>
8+
<link rel="stylesheet" href="/static/admin/css/dark_mode.css">
9+
<script src="/static/admin/js/theme.js" defer></script>
1010

1111

1212

13-
<link rel="stylesheet" type="text/css" href="admin/css/forms.css">
13+
<link rel="stylesheet" type="text/css" href="/static/admin/css/forms.css">
1414

1515

1616

1717

1818
<meta name="viewport" content="width=device-width, initial-scale=1.0">
19-
<link rel="stylesheet" href="admin/css/responsive.css">
19+
<link rel="stylesheet" href="/static/admin/css/responsive.css">
2020

2121

2222
<meta name="robots" content="NONE,NOARCHIVE">

tests/generate_docs.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import unittest
2+
from rest_framework.test import APITestCase
3+
from tests.testapp.models import TimeSeries
4+
from tests.weather.models import Station
5+
from django.core.management import call_command
6+
import pathlib
7+
8+
9+
DOCS = pathlib.Path("docs")
10+
11+
STATIONS = {
12+
"MSP": "USW00014922",
13+
"ATL": "USW00013874",
14+
"LAX": "USW00023174",
15+
}
16+
17+
class DocsTestCase(APITestCase):
18+
def setUp(self):
19+
data = (
20+
("2014-01-01", 0.5),
21+
("2014-01-02", 0.4),
22+
("2014-01-03", 0.6),
23+
("2014-01-04", 0.2),
24+
("2014-01-05", 0.1),
25+
)
26+
for date, value in data:
27+
TimeSeries.objects.create(date=date, value=value)
28+
29+
for name, code in STATIONS.items():
30+
station = Station.objects.create(name=name, code=code)
31+
station.load_weather()
32+
33+
def test_docs(self):
34+
call_command('collectstatic', interactive=False)
35+
for url in (
36+
"timeseries.html",
37+
"timeseries.csv",
38+
"timeseries.json",
39+
"timeseries.xlsx",
40+
"timeseries.png",
41+
"timeseries.svg",
42+
"weather.html",
43+
"weather.csv",
44+
"weather.json",
45+
"weather.xlsx",
46+
"weather.png",
47+
"weather.svg",
48+
):
49+
response = self.client.get(f"/{url}")
50+
path = DOCS / url
51+
path.parent.mkdir(parents=True, exist_ok=True)
52+
path.write_bytes(response.content)

0 commit comments

Comments
 (0)