diff --git a/asteroid.lisp b/asteroid.lisp index bc0f0ff..8b26fac 100644 --- a/asteroid.lisp +++ b/asteroid.lisp @@ -1403,10 +1403,11 @@ ("avg_session_minutes" . ,(sixth row)))) stats)))))) -(define-api asteroid/stats/geo (&optional (days "7")) () - "Get geographic distribution of listeners (admin only)" +(define-api asteroid/stats/geo (&optional (days "7") (sort-by "minutes")) () + "Get geographic distribution of listeners (admin only). + SORT-BY can be 'minutes' (default) or 'listeners'." (require-role :admin) - (let ((stats (get-geo-stats (parse-integer days :junk-allowed t)))) + (let ((stats (get-geo-stats (parse-integer days :junk-allowed t) sort-by))) (api-output `(("status" . "success") ("geo" . ,(mapcar (lambda (row) `(("country_code" . ,(first row)) diff --git a/listener-stats.lisp b/listener-stats.lisp index 8b185f9..2530a27 100644 --- a/listener-stats.lisp +++ b/listener-stats.lisp @@ -369,17 +369,21 @@ (log:error "Failed to get daily stats: ~a" e) nil))) -(defun get-geo-stats (&optional (days 7)) - "Get geographic distribution for the last N days" +(defun get-geo-stats (&optional (days 7) (order-by "minutes")) + "Get geographic distribution for the last N days. + ORDER-BY can be 'minutes' (default) or 'listeners'." (handler-case (with-db - (postmodern:query - (format nil "SELECT country_code, SUM(listener_count) as total_listeners, SUM(listen_minutes) as total_minutes + (let ((order-column (if (string= order-by "listeners") + "total_listeners" + "total_minutes"))) + (postmodern:query + (format nil "SELECT country_code, SUM(listener_count) as total_listeners, SUM(listen_minutes) as total_minutes FROM listener_geo_stats WHERE date > NOW() - INTERVAL '~a days' GROUP BY country_code - ORDER BY total_minutes DESC - LIMIT 20" days))) + ORDER BY ~a DESC + LIMIT 20" days order-column)))) (error (e) (log:error "Failed to get geo stats: ~a" e) nil))) diff --git a/parenscript/admin.lisp b/parenscript/admin.lisp index ff8f01c..02086e4 100644 --- a/parenscript/admin.lisp +++ b/parenscript/admin.lisp @@ -970,8 +970,10 @@ ;; Refresh geo stats from API (defun refresh-geo-stats () - (ps:chain - (fetch "/api/asteroid/stats/geo?days=7") + (let* ((sort-select (ps:chain document (get-element-by-id "geo-sort-by"))) + (sort-by (if sort-select (ps:@ sort-select value) "minutes"))) + (ps:chain + (fetch (+ "/api/asteroid/stats/geo?days=7&sort-by=" sort-by)) (then (lambda (response) (ps:chain response (json)))) (then (lambda (result) (let ((data (or (ps:@ result data) result)) @@ -1009,7 +1011,7 @@ (let ((tbody (ps:chain document (get-element-by-id "geo-stats-body")))) (when tbody (setf (ps:@ tbody inner-h-t-m-l) - "