1- import { Chart , BarController , BarElement , CategoryScale , LinearScale , Colors , Tooltip } from "chart.js"
1+ import { Chart , BarController , PieController , BarElement , ArcElement , CategoryScale , LinearScale , Colors , Tooltip , Legend } from "chart.js"
2+ import { ChoroplethController , ProjectionScale , ColorScale , GeoFeature , topojson } from 'chartjs-chart-geo' ;
3+ import countries50m from "world-atlas/countries-50m.json" with { type : "json" } ;
24
35// Bundle optimization
4- Chart . register ( BarController , BarElement , CategoryScale , LinearScale , Colors , Tooltip )
6+ Chart . register ( BarController , PieController , ChoroplethController , BarElement , ArcElement , CategoryScale , LinearScale , ProjectionScale , ColorScale , GeoFeature , Colors , Tooltip , Legend )
57
68// Current charts
7- let pagesChart = null
8- let referrersChart = null
9+ let charts = [ ]
910
1011async function displayData ( site , time ) {
1112 // Destroy the old charts
12- if ( pagesChart !== null ) pagesChart . destroy ( )
13- if ( referrersChart !== null ) referrersChart . destroy ( )
13+ for ( let chart of charts ) {
14+ chart . destroy ( )
15+ }
16+ charts = [ ]
1417
1518 // Calculate the from time
1619 const from = ( Date . now ( ) / 1000 ) - time
1720
1821 // Fetch the numbers
1922 const pages = await fetch ( `/api/sites/${ site } /pages?from=${ from } ` ) . then ( x => x . json ( ) )
2023 const referrers = await fetch ( `/api/sites/${ site } /referrers?from=${ from } ` ) . then ( x => x . json ( ) )
24+ const browsers = await fetch ( `/api/sites/${ site } /browsers?from=${ from } ` ) . then ( x => x . json ( ) )
25+ const systems = await fetch ( `/api/sites/${ site } /operating-systems?from=${ from } ` ) . then ( x => x . json ( ) )
26+ const devices = await fetch ( `/api/sites/${ site } /device-types?from=${ from } ` ) . then ( x => x . json ( ) )
27+ const countries = await fetch ( `/api/sites/${ site } /countries?from=${ from } ` ) . then ( x => x . json ( ) )
2128
2229 // Display the charts
23- pagesChart = displayLineChart ( "pages" , pages . map ( x => [ x . path , x . count ] ) )
24- referrersChart = displayLineChart ( "referrers" , referrers . map ( x => [ x . referrer , x . count ] ) )
30+ const region = new Intl . DisplayNames ( [ 'en' ] , { type : 'region' } )
31+ charts . push ( displayLineChart ( "pages" , pages . map ( x => [ x . path , x . count ] ) ) )
32+ charts . push ( displayLineChart ( "referrers" , referrers . map ( x => [ x . referrer , x . count ] ) ) )
33+ charts . push ( displayPieChart ( "browsers" , browsers . map ( x => [ x . browser , x . count ] ) ) )
34+ charts . push ( displayPieChart ( "systems" , systems . map ( x => [ x . operating_system , x . count ] ) ) )
35+ charts . push ( displayPieChart ( "devices" , devices . map ( x => [ x . device_type , x . count ] ) ) )
36+ charts . push ( displayCountryChart ( "countries" , Object . fromEntries ( countries . map ( x => [ region . of ( x . country ) , x . count ] ) ) ) ) ;
2537}
2638
27- function displayLineChart ( id , values ) {
28- const options = {
29- indexAxis : "y"
30- }
31-
39+ function displayChartInternal ( type , options , id , values ) {
3240 // Map the data
3341 const data = {
3442 labels : values . map ( x => x [ 0 ] ) ,
@@ -42,14 +50,60 @@ function displayLineChart(id, values) {
4250
4351 // Display the chart
4452 const chart = new Chart ( document . getElementById ( id ) , {
45- type : "bar" ,
53+ type : type ,
4654 data,
4755 options
4856 } )
4957
5058 return chart
5159}
5260
61+ function displayCountryChart ( id , values ) {
62+ const countries = topojson . feature ( countries50m , countries50m . objects . countries ) . features ;
63+
64+ const chart = new Chart ( document . getElementById ( id ) . getContext ( "2d" ) , {
65+ type : 'choropleth' ,
66+ data : {
67+ labels : countries . map ( ( d ) => d . properties . name ) ,
68+ datasets : [ {
69+ label : 'Countries' ,
70+ data : countries . map ( ( d ) => {
71+ const country = d . properties . name ;
72+ return ( { feature : d , value : values [ country ] ? values [ country ] : 0 } )
73+ } ) ,
74+ } ]
75+ } ,
76+ options : {
77+ scales : {
78+ projection : {
79+ axis : 'x' ,
80+ projection : 'equalEarth'
81+ }
82+ }
83+ }
84+ } ) ;
85+
86+ return chart ;
87+ }
88+
89+ function displayLineChart ( id , values ) {
90+ const options = {
91+ indexAxis : "y"
92+ }
93+ return displayChartInternal ( "bar" , options , id , values )
94+ }
95+
96+ function displayPieChart ( id , values ) {
97+ const options = {
98+ plugins : {
99+ legend : {
100+ position : 'top'
101+ }
102+ }
103+ }
104+ return displayChartInternal ( "pie" , options , id , values )
105+ }
106+
53107function startDisplayData ( ) {
54108 // Get the site and time
55109 const site = document . getElementById ( "site-select" ) . value
0 commit comments