Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 104 additions & 19 deletions app/components/app_timeline_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,37 @@ class AppTimelineComponent < ViewComponent::Base
<% @items.each do |item| %>
<% next if item.blank? %>

<li class="app-timeline__item <%= 'app-timeline__item--past' if item[:is_past_item] %>">
<% if item[:active] || item[:is_past_item] %>
<svg class="app-timeline__badge" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 28 28">
<circle cx="14" cy="14" r="13" fill="#005EB8"/>
</svg>
<% else %>
<svg class="app-timeline__badge app-timeline__badge--small" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14">
<circle cx="7" cy="7" r="6" fill="white" stroke="#AEB7BD" stroke-width="2"/>
</svg>
<% end %>

<div class="app-timeline__content">
<h3 class="app-timeline__header <%= 'nhsuk-u-font-weight-bold' if item[:active] %>">
<%= item[:heading_text].html_safe %>
<% if item[:type] == :section_header %>
<li>
<h3 class="nhsuk-u-margin-top-2">
<%= content_tag(:strong, item[:date]) %>
</h3>

<% if item[:description].present? %>
<p class="app-timeline__description"><%= item[:description].html_safe %></p>
</li>
<% else %>
<li class="app-timeline__item <%= 'app-timeline__item--past' if item[:is_past_item] %>">
<% if item[:active] || item[:is_past_item] %>
<svg class="app-timeline__badge" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 28 28">
<circle cx="14" cy="14" r="13" fill="#005EB8"/>
</svg>
<% else %>
<svg class="app-timeline__badge app-timeline__badge--small" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14">
<circle cx="7" cy="7" r="6" fill="white" stroke="#AEB7BD" stroke-width="2"/>
</svg>
<% end %>
</div>
</li>

<div class="app-timeline__content">
<h3 class="app-timeline__header <%= 'nhsuk-u-font-weight-bold' if item[:active] %>">
<%= format_heading(item).html_safe %>
</h3>

<% if item[:description].present? || item[:details].present? %>
<div class="app-timeline__description">
<%= format_description(item).html_safe %>
</div>
<% end %>
</div>
</li>
<% end %>
<% end %>
</ul>
ERB
Expand All @@ -38,4 +48,79 @@ def initialize(items)
def render?
@items.present?
end

private

EVENT_COLOUR_MAPPING = {
"CohortImport" => "blue",
"ClassImport" => "purple",
"PatientSession" => "green",
"Consent" => "yellow",
"Triage" => "red",
"VaccinationRecord" => "grey",
"SchoolMove" => "orange",
"SchoolMoveLogEntry" => "pink"
}.freeze

def format_heading(item)
if item[:type] && item[:created_at]
time = format_time(item[:created_at])
event_tag =
govuk_tag(
text: item[:event_type],
colour: tag_colour(item[:event_type])
)
"#{event_tag} at #{time}"
elsif item[:heading_text]
item[:heading_text]
end
end

def format_description(item)
if item[:details].present?
formatted_details = format_event_details(item[:details])
id_info =
item[:id] ? "<p class=\"timeline__byline\">id: #{item[:id]}</p>" : ""
"#{id_info}#{formatted_details}"
elsif item[:description].present?
item[:description]
end
end

def format_time(date_time)
date_time.strftime("%H:%M:%S")
end

def format_event_details(details)
return "" if details.blank?

if details.is_a?(Hash)
formatted =
details.map do |key, value|
if value.is_a?(Hash)
nested =
value.map do |sub_key, sub_value|
nested_value =
sub_value.is_a?(String) ? sub_value : sub_value.inspect
"<div style='margin-left: 1em;'><strong>#{sub_key}:</strong> #{nested_value}</div>"
end
"<div><strong>#{key}:</strong>#{nested.join}</div>"
else
"<div><strong>#{key}:</strong> #{value}</div>"
end
end
formatted.join
else
details.to_s
end
end

def tag_colour(type)
return "light-blue" if type.end_with?("-Audit")
EVENT_COLOUR_MAPPING.fetch(type, "grey")
end

def govuk_tag(text:, colour:)
helpers.govuk_tag(text: text, colour: colour)
end
end
181 changes: 181 additions & 0 deletions app/components/app_timeline_filter_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
<%= render AppCardComponent.new(filters: true) do |card| %>
<% card.with_heading { "Customise timeline" } %>
<%= form_with url: @url,
method: :get,
data: { module: "autosubmit",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we've removed Stimulus from Mavis, probably since this was originally written (see b66c0f4). Not a show-stopper, but it would be nice to see if we can get this functionality back, although I suspect NHSUK won't support it directly so we'll have to bring Stimulus back.

turbo: "true",
turbo_action: "replace" },
builder: GOVUKDesignSystemFormBuilder::FormBuilder do |f| %>
<%= f.govuk_fieldset legend: { text: "Events to display:", size: "s" } do %>
<% event_options.keys.each do |value| %>
<%= f.govuk_check_boxes_fieldset :event_names, legend: { hidden: true } do %>
<%= f.govuk_check_box :event_names,
value,
label: { text: value.to_s.humanize },
checked: value.to_s.in?(params[:event_names] || event_options.keys.map(&:to_s)),
"data-autosubmit-target": "field",
"data-action": "autosubmit#submit",
"data-turbo-permanent": "true" %>

<% available_fields = timeline_fields[value.to_sym] || [] %>
<% if available_fields.any? && value.to_s.in?(params[:event_names]) %>
<div class="nhsuk-checkboxes__conditional nhsuk-u-margin-bottom-2">
<% available_fields.each do |field| %>
<%= f.govuk_check_box "detail_config[#{value}]",
field,
small: true,
label: { text: field },
checked: field.to_s.in?(params.dig("detail_config", value) || []),
"data-autosubmit-target": "field",
"data-action": "autosubmit#submit",
"data-turbo-permanent": "true" %>
<% end %>
</div>
<% end %>
<% end %>
<% end %>

<%= f.govuk_check_boxes_fieldset :audit_config, legend: { hidden: true } do %>
<%= f.govuk_check_box :event_names, "audits",
label: { text: "Audits" },
checked: "audits".in?(params[:event_names]),
"data-autosubmit-target": "field",
"data-action": "autosubmit#submit",
"data-turbo-permanent": "true" %>
<% if "audits".in?(params[:event_names]) %>
<div class="nhsuk-checkboxes__conditional nhsuk-u-margin-bottom-2">
<%= f.govuk_check_box "audit_config[include_associated_audits]", true, false,
multiple: false,
label: { text: "include associated audits" },
checked: params.dig(:audit_config, :include_associated_audits) == "true",
"data-autosubmit-target": "field",
"data-action": "autosubmit#submit",
"data-turbo-permanent": "true" %>

<%= f.govuk_check_box "audit_config[include_filtered_audit_changes]", true, false,
multiple: false,
label: { text: "include filtered audit changes" },
checked: params.dig(:audit_config, :include_filtered_audit_changes) == "true",
"data-autosubmit-target": "field",
"data-action": "autosubmit#submit",
"data-turbo-permanent": "true" %>
</div>
<% end %>
<% end %>

<%= f.govuk_check_box :event_names, "org_cohort_imports",
label: { text: "Cohort Imports for Team #{@teams.join(",")} excluding patient" },
checked: "org_cohort_imports".in?(params[:event_names]),
"data-autosubmit-target": "field",
"data-action": "autosubmit#submit",
"data-turbo-permanent": "true" %>

<% (@additional_class_imports).each do |location_id, import_ids| %>
<%= f.govuk_check_box :event_names, "add_class_imports_#{location_id}",
label: { text: "Class Imports for Location-#{location_id} excluding Patient" },
checked: "add_class_imports_#{location_id}".in?(params[:event_names]),
"data-autosubmit-target": "field",
"data-action": "autosubmit#submit",
"data-turbo-permanent": "true" %>
<% end %>


<%= f.govuk_radio_buttons_fieldset :compare_option, legend: { text: "Compare with another patient:", size: "s" } do %>
<%= f.govuk_radio_button :compare_option,
nil,
label: { text: "Do not compare" },
checked: params[:compare_option].blank?,
"data-autosubmit-target": "field",
"data-action": "autosubmit#submit",
"data-turbo-permanent": "true" %>

<% if class_imports.present? %>
<%= f.govuk_radio_button :compare_option,
"class_import",
label: { text: "From a Class Import" },
checked: params[:compare_option] == "class_import",
"data-autosubmit-target": "field",
"data-action": "autosubmit#submit",
"data-turbo-permanent": "true" do %>
<% class_imports.each do |import| %>
<%= f.govuk_radio_button :compare_option_class_import,
import,
label: { text: "ClassImport-#{import}" },
checked: params[:compare_option_class_import].to_s == import.to_s,
"data-autosubmit-target": "field",
"data-action": "autosubmit#submit",
"data-turbo-permanent": "true" %>
<% end %>
<% end %>
<% end %>

<% if cohort_imports.present? %>
<%= f.govuk_radio_button :compare_option,
"cohort_import",
label: { text: "From a Cohort Import" },
checked: params[:compare_option] == "cohort_import",
"data-autosubmit-target": "field",
"data-action": "autosubmit#submit",
"data-turbo-permanent": "true" do %>
<% cohort_imports.each do |import| %>
<%= f.govuk_radio_button :compare_option_cohort_import,
import,
label: { text: "CohortImport-#{import}" },
checked: params[:compare_option_cohort_import].to_s == import.to_s,
"data-autosubmit-target": "field",
"data-action": "autosubmit#submit",
"data-turbo-permanent": "true" %>
<% end %>
<% end %>
<% end %>

<% if sessions.present? %>
<%= f.govuk_radio_button :compare_option,
"session",
label: { text: "In a Session" },
checked: params[:compare_option] == "session" do %>
<% sessions.each do |session| %>
<%= f.govuk_radio_button :compare_option_session,
session,
label: { text: "Session-#{session}" },
checked: params[:compare_option_session].to_s == session.to_s && params[:compare_option] == "session",
"data-autosubmit-target": "field",
"data-action": "autosubmit#submit",
"data-turbo-permanent": "true" %>
<% end %>
<% end %>
<% end %>

<%= f.govuk_radio_button :compare_option,
"manual_entry",
label: { text: "With a specific Patient ID" },
checked: params[:compare_option] == "manual_entry" do %>
<%= f.govuk_number_field :manual_patient_id,
label: { hidden: true },
width: 10,
"data-autosubmit-target": "field",
"data-action": "autosubmit#submit",
"data-turbo-permanent": "true" %>
<% end %>
<% end %>

<div class="nhsuk-u-margin-bottom-4">
<%= f.govuk_check_box :show_pii, true,
label: { text: "Show PII" },
checked: @show_pii,
"data-autosubmit-target": "field",
"data-action": "autosubmit#submit",
"data-turbo-permanent": "true" %>
</div>

<%= helpers.govuk_button_link_to "Reset filters",
@reset_url,
class: "govuk-button govuk-button--secondary nhsuk-u-display-block app-button--small",
secondary: true,
"data-autosubmit-target": "reset",
"data-action": "autosubmit#submit",
"data-turbo-permanent": "true" %>
<%= f.govuk_submit "Filter" %>
<% end %>
<% end %>
<% end %>
40 changes: 40 additions & 0 deletions app/components/app_timeline_filter_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

class AppTimelineFilterComponent < ViewComponent::Base
def initialize(
url:,
patient:,
teams:,
event_options:,
timeline_fields:,
additional_class_imports:,
class_imports:,
cohort_imports:,
sessions:,
reset_url:,
show_pii:
)
@url = url
@patient = patient
@teams = teams.map(&:id)
@event_options = event_options
@timeline_fields = timeline_fields
@additional_class_imports = additional_class_imports
@class_imports = class_imports
@cohort_imports = cohort_imports
@sessions = sessions
@reset_url = reset_url
@show_pii = show_pii
end

attr_reader :url,
:patient,
:event_options,
:timeline_fields,
:additional_class_imports,
:class_imports,
:cohort_imports,
:sessions,
:reset_url,
:show_pii
end
Loading