From 9b105264fdb52d8acee9b84b75b9f013e5805240 Mon Sep 17 00:00:00 2001 From: HelenWDTK <120410992+HelenWDTK@users.noreply.github.com> Date: Wed, 5 Apr 2023 05:21:55 +0100 Subject: [PATCH] Update admin general timeline Allow the timeline filters by time and event types at the same time. Improves parameters by using a single `start_date` param rather than separate ones for day/hour/week/... Refactors the loading of events to use `ActiveRecord` query where possible and where isn't possible use the query builder and call `#to_sql` in order to get query sanitization. --- app/controllers/admin_general_controller.rb | 78 ++++++------------- app/helpers/admin_general_timeline_helper.rb | 36 +++++++++ app/views/admin_general/timeline.html.erb | 25 +++--- .../admin_general_controller_spec.rb | 27 +++++-- 4 files changed, 88 insertions(+), 78 deletions(-) create mode 100644 app/helpers/admin_general_timeline_helper.rb diff --git a/app/controllers/admin_general_controller.rb b/app/controllers/admin_general_controller.rb index c51fd03c05..8d125e732c 100644 --- a/app/controllers/admin_general_controller.rb +++ b/app/controllers/admin_general_controller.rb @@ -5,6 +5,7 @@ # Email: hello@mysociety.org; WWW: http://www.mysociety.org/ class AdminGeneralController < AdminController + include AdminGeneralTimelineHelper def index # Tasks to do @@ -170,46 +171,11 @@ def debug private - def get_date_back_to_utc - date_back_to = if params[:hour] - Time.zone.now - 1.hour - elsif params[:day] - Time.zone.now - 1.day - elsif params[:week] - Time.zone.now - 1.week - elsif params[:month] - Time.zone.now - 1.month - elsif params[:all] - Time.zone.now - 1000.years - else - Time.zone.now - 2.days - end - date_back_to.getutc - end - - def get_event_type - if params[:event_type] == 'authority_change' - 'Authority changes' - elsif params[:event_type] == 'info_request_event' - 'Request events' - else - "Events" - end - end - def get_events_title - title = if params[:hour] - "#{get_event_type} in last hour" - elsif params[:day] - "#{get_event_type} in last day" - elsif params[:week] - "#{get_event_type} in last week" - elsif params[:month] - "#{get_event_type} in last month" - elsif params[:all] - "#{get_event_type}, all time" + if current_time_filter == 'All time' + "#{current_event_type}, all time" else - "#{get_event_type} in last two days" + "#{current_event_type} in the last #{current_time_filter.downcase}" end end @@ -219,26 +185,26 @@ def get_timestamps # Note that the relevant date for InfoRequestEvents is creation, but # for PublicBodyVersions is update throughout connection = InfoRequestEvent.connection - authority_change_clause = "SELECT id, 'PublicBodyVersion', - updated_at AS timestamp - FROM #{PublicBody.versioned_class.table_name} - WHERE updated_at > '#{get_date_back_to_utc}'" - - info_request_event_clause = "SELECT id, 'InfoRequestEvent', - created_at AS timestamp - FROM info_request_events - WHERE created_at > '#{get_date_back_to_utc}'" - - timestamps = if params[:event_type] == 'authority_change' - connection.select_rows("#{authority_change_clause} - ORDER by timestamp desc") - elsif params[:event_type] == 'info_request_event' - connection.select_rows("#{info_request_event_clause} - ORDER by timestamp desc") + + authority_change_scope = PublicBody.versioned_class. + select("id, 'PublicBodyVersion', updated_at AS timestamp"). + where(updated_at: start_date...). + order(timestamp: :desc) + + info_request_event_scope = InfoRequestEvent. + select("id, 'InfoRequestEvent', created_at AS timestamp"). + where(created_at: start_date...). + order(timestamp: :desc) + + case params[:event_type] + when 'authority_change' + connection.select_rows(authority_change_scope.to_sql) + when 'info_request_event' + connection.select_rows(info_request_event_scope.to_sql) else - connection.select_rows("#{info_request_event_clause} + connection.select_rows("#{info_request_event_scope.unscope(:order).to_sql} UNION - #{authority_change_clause} + #{authority_change_scope.unscope(:order).to_sql} ORDER by timestamp desc") end end diff --git a/app/helpers/admin_general_timeline_helper.rb b/app/helpers/admin_general_timeline_helper.rb new file mode 100644 index 0000000000..c6fa3d70ef --- /dev/null +++ b/app/helpers/admin_general_timeline_helper.rb @@ -0,0 +1,36 @@ +## +# Helpers for rendering timeline filter buttons. Also used in the controller for +# generating the queries to load events. +# +module AdminGeneralTimelineHelper + def start_date + params[:start_date]&.to_datetime || 2.days.ago + end + + def time_filters + { + 'Hour' => 1.hour.ago, + 'Day' => 1.day.ago, + '2 days' => 2.days.ago, + 'Week' => 1.week.ago, + 'Month' => 1.month.ago, + 'All time' => Time.utc(1970, 1, 1) + } + end + + def current_time_filter + time_filters.min_by { |_, time| (time - start_date).abs }.first + end + + def event_types + { + authority_change: 'Authority changes', + info_request_event: 'Request events', + all: 'All events' + } + end + + def current_event_type + event_types[params[:event_type]&.to_sym] || event_types[:all] + end +end diff --git a/app/views/admin_general/timeline.html.erb b/app/views/admin_general/timeline.html.erb index 1983799f42..26bf5a5399 100644 --- a/app/views/admin_general/timeline.html.erb +++ b/app/views/admin_general/timeline.html.erb @@ -1,23 +1,18 @@ <% @title = "Timeline" %>