diff --git a/ana.go b/ana.go index 6a4ed22..1106c70 100644 --- a/ana.go +++ b/ana.go @@ -30,7 +30,9 @@ func main() { r.Handle("/api/visits/count/day", api.Authorize(api.GetVisitsDayCountHandler)).Methods("GET") r.Handle("/api/visits/count/realtime", api.Authorize(api.GetVisitsRealtimeCount)).Methods("GET") r.Handle("/api/visits", api.Authorize(api.GetVisitsHandler)).Methods("GET") + r.Handle("/api/pageviews/count/day", api.Authorize(api.GetPageviewsDayCountHandler)).Methods("GET") r.Handle("/api/pageviews", api.Authorize(api.GetPageviewsHandler)).Methods("GET") + r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("./static/")))) r.Handle("/", http.FileServer(http.Dir("./views/"))) diff --git a/api/pageviews.go b/api/pageviews.go index bd885be..90debd5 100644 --- a/api/pageviews.go +++ b/api/pageviews.go @@ -36,3 +36,37 @@ var GetPageviewsHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.R w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(results) }) + + +// URL: /api/pageviews/count/day +var GetPageviewsDayCountHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + stmt, err := core.DB.Prepare(`SELECT + COUNT(*) AS count, DATE_FORMAT(timestamp, '%Y-%m-%d') AS date_group + FROM visits + GROUP BY date_group`) + checkError(err) + defer stmt.Close() + + rows, err := stmt.Query() + checkError(err) + + type Datapoint struct { + Count int + Label string + } + + results := make([]Datapoint, 0) + defer rows.Close() + for rows.Next() { + v := Datapoint{} + err = rows.Scan(&v.Count, &v.Label); + checkError(err) + results = append(results, v) + } + + err = rows.Err(); + checkError(err) + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(results) +}) diff --git a/api/visits.go b/api/visits.go index 18e73ab..e788b13 100644 --- a/api/visits.go +++ b/api/visits.go @@ -63,7 +63,7 @@ var GetVisitsRealtimeCount = http.HandlerFunc(func(w http.ResponseWriter, r *htt // URL: /api/visits/count/day var GetVisitsDayCountHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { stmt, err := core.DB.Prepare(`SELECT - COUNT(*) AS count, DATE_FORMAT(timestamp, '%Y-%m-%d') AS date_group + COUNT(DISTINCT(ip_address)) AS count, DATE_FORMAT(timestamp, '%Y-%m-%d') AS date_group FROM visits GROUP BY date_group`) checkError(err) diff --git a/assets/js/components/Graph.js b/assets/js/components/Graph.js index 48dbfd7..b8b81de 100644 --- a/assets/js/components/Graph.js +++ b/assets/js/components/Graph.js @@ -3,28 +3,39 @@ import { h, render, Component } from 'preact'; import Chart from 'chart.js' +Chart.defaults.global.tooltips.xPadding = 10; +Chart.defaults.global.tooltips.yPadding = 10; + class Graph extends Component { constructor(props) { super(props) this.state = { - data: [] + visitorData: [], + pageviewData: [] } this.fetchData = this.fetchData.bind(this); this.fetchData(); } - initChart() { - new Chart(this.ctx, { + refreshChart() { + this.chart = new Chart(this.ctx, { type: 'line', data: { - labels: this.state.data.map((d) => d.Label), - datasets: [{ + labels: this.state.visitorData.map((d) => d.Label), + datasets: [ + { label: '# of Visitors', - data: this.state.data.map((d) => d.Count), - backgroundColor: 'rgba(0, 155, 255, .2)' - }] + data: this.state.visitorData.map((d) => d.Count), + backgroundColor: 'rgba(0, 0, 255, .2)' + }, + { + label: '# of Pageviews', + data: this.state.pageviewData.map((d) => d.Count), + backgroundColor: 'rgba(0, 0, 125, .2)' + } + ] }, options: { scale: { @@ -37,13 +48,22 @@ class Graph extends Component { } fetchData() { - return fetch('/api/visits/count/day', { + // fetch visitor data + fetch('/api/visits/count/day', { credentials: 'include' - }) - .then((r) => r.json()) + }).then((r) => r.json()) .then((data) => { - this.setState({ data: data}) - this.initChart() + this.setState({ visitorData: data}) + this.refreshChart(); + }); + + // fetch pageview data + fetch('/api/pageviews/count/day', { + credentials: 'include' + }).then((r) => r.json()) + .then((data) => { + this.setState({ pageviewData: data}) + this.refreshChart(); }); }