Merge pull request #21 from wagesj45/codex/add-datatables-chart-type-and-update-definitions

Add DataTables table chart type
This commit is contained in:
Jordan Wages 2025-07-18 22:34:32 -05:00 committed by GitHub
commit f0653f972f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 45 additions and 14 deletions

View file

@ -39,6 +39,12 @@ This document outlines general practices and expectations for AI agents assistin
* Use latest CDN version for embedded dashboards * Use latest CDN version for embedded dashboards
* Charts should be rendered from pre-generated JSON blobs in `/json/` * Charts should be rendered from pre-generated JSON blobs in `/json/`
### Tables: DataTables
* Use DataTables via CDN for reports with `chart: table`
* Requires jQuery from a CDN
* Table data comes from the same `/json/` files as charts
### Styling: Bulma CSS ### Styling: Bulma CSS
* Use via CDN or vendored minified copy (to keep reports fully static) * Use via CDN or vendored minified copy (to keep reports fully static)

View file

@ -1,6 +1,6 @@
- name: hits - name: hits
label: Hits label: Hits
chart: bar chart: line
query: | query: |
SELECT {bucket} AS bucket, SELECT {bucket} AS bucket,
COUNT(*) AS value COUNT(*) AS value
@ -20,7 +20,7 @@
- name: cache_status_breakdown - name: cache_status_breakdown
label: Cache Status label: Cache Status
chart: bar chart: polarArea
query: | query: |
SELECT cache_status AS bucket, SELECT cache_status AS bucket,
COUNT(*) AS value COUNT(*) AS value
@ -30,7 +30,7 @@
- name: domain_traffic - name: domain_traffic
label: Top Domains label: Top Domains
chart: bar chart: table
query: | query: |
SELECT host AS bucket, SELECT host AS bucket,
COUNT(*) AS value COUNT(*) AS value
@ -50,7 +50,7 @@
- name: top_paths - name: top_paths
label: Top Paths label: Top Paths
chart: bar chart: table
query: | query: |
SELECT path AS bucket, SELECT path AS bucket,
COUNT(*) AS value COUNT(*) AS value
@ -65,7 +65,7 @@
- name: user_agents - name: user_agents
label: User Agents label: User Agents
chart: bar chart: table
query: | query: |
SELECT user_agent AS bucket, SELECT user_agent AS bucket,
COUNT(*) AS value COUNT(*) AS value
@ -76,7 +76,7 @@
- name: referrers - name: referrers
label: Referrers label: Referrers
chart: bar chart: table
query: | query: |
SELECT referer AS bucket, SELECT referer AS bucket,
COUNT(*) AS value COUNT(*) AS value
@ -87,7 +87,7 @@
- name: status_distribution - name: status_distribution
label: HTTP Statuses label: HTTP Statuses
chart: bar chart: stackedBar
query: | query: |
SELECT CASE SELECT CASE
WHEN status BETWEEN 200 AND 299 THEN '2xx' WHEN status BETWEEN 200 AND 299 THEN '2xx'

View file

@ -4,7 +4,10 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>{{ interval.title() }} Report</title> <title>{{ interval.title() }} Report</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.0/dist/jquery.min.js"></script>
<script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
</head> </head>
<body class="section"> <body class="section">
<div class="container"> <div class="container">
@ -12,7 +15,11 @@
{% for report in reports %} {% for report in reports %}
<div class="box"> <div class="box">
<h2 class="subtitle">{{ report.label }}</h2> <h2 class="subtitle">{{ report.label }}</h2>
{% if report.chart == 'table' %}
<table id="table-{{ report.name }}" class="table is-striped"></table>
{% else %}
<canvas id="chart-{{ report.name }}"></canvas> <canvas id="chart-{{ report.name }}"></canvas>
{% endif %}
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
@ -22,10 +29,32 @@
fetch(rep.json) fetch(rep.json)
.then(r => r.json()) .then(r => r.json())
.then(data => { .then(data => {
if (rep.chart === 'table') {
const rows = data.map(x => [x.bucket, x.value]);
new DataTable('#table-' + rep.name, {
data: rows,
columns: [
{ title: 'Bucket' },
{ title: 'Value' }
]
});
return;
}
const labels = data.map(x => x.bucket); const labels = data.map(x => x.bucket);
const values = data.map(x => x.value); const values = data.map(x => x.value);
const chartType = rep.chart === 'stackedBar' ? 'bar' : rep.chart;
const options = {
scales: {
y: { beginAtZero: true }
}
};
if (rep.chart === 'stackedBar') {
options.scales.x = { stacked: true };
options.scales.y.stacked = true;
}
new Chart(document.getElementById('chart-' + rep.name), { new Chart(document.getElementById('chart-' + rep.name), {
type: rep.chart, type: chartType,
data: { data: {
labels: labels, labels: labels,
datasets: [{ datasets: [{
@ -34,14 +63,10 @@
backgroundColor: 'rgba(54, 162, 235, 0.5)', backgroundColor: 'rgba(54, 162, 235, 0.5)',
borderColor: 'rgba(54, 162, 235, 1)', borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1, borderWidth: 1,
fill: rep.chart !== 'bar', fill: rep.chart !== 'bar' && rep.chart !== 'stackedBar',
}] }]
}, },
options: { options: options
scales: {
y: { beginAtZero: true }
}
}
}); });
}); });
}); });