Skip to content

Commit

Permalink
feat: rework court report generation
Browse files Browse the repository at this point in the history
Add generate docx modal with date pickers to filter dates of case
contacts to include in the generated report.

Modify current tests to open the modal before
attempting to click within it.

Allow range filtering of contacts in case report

wip

fix: code climate
  • Loading branch information
elasticspoon committed Apr 2, 2024
1 parent 7ded9ab commit e2af233
Show file tree
Hide file tree
Showing 17 changed files with 394 additions and 218 deletions.
6 changes: 6 additions & 0 deletions app/assets/stylesheets/base/variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@ $red: #dc3545;
$sidebar-inactive: #9AA4CA;
$sidebar-active: #365CF5;
$sidebar-dark: #1A2142;

:root {
--dark: #262d3f;
--gray: #5d657b;
--silver: #D9D9D9;
}
49 changes: 49 additions & 0 deletions app/assets/stylesheets/pages/casa_cases.scss
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,52 @@ body.casa_cases-show {
display: block;
}
}

#generate-docx-report-modal {
.dates-container {
display: flex;
}

.docx-report__modal-body {
display: flex;
flex-direction: column;
row-gap: 1rem;

}

.modal-footer {
[data-bs-dismiss="modal"] {
padding-block: 11px;
}
}
}

.generate-report-button {
display: flex;
flex-direction: row;
width: 100%;
border: solid 1px var(--silver);
padding: 1.2rem;
column-gap: 1.2rem;

&:hover {
border-color: black;
}

svg {
min-inline-size: 40px;
width: 40px;
height: auto;
}

div {
text-align: left;
h3 {
margin-block-end: .25rem;

}
p {

}
}
}
Empty file.
5 changes: 5 additions & 0 deletions app/assets/stylesheets/shared/typography.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// TODO check in css so tests can run without internet
@use "../base/variables.scss" as globals;
@import url(https://fonts.googleapis.com/css?family=Montserrat:400,700);

body {
Expand All @@ -13,12 +14,16 @@ option {
font-family: Inter;
font-size: 16px;
font-weight: 500;
line-height: 19px;
color: var(--dark);
}

.content-2 {
font-family: Inter;
font-size: 14px;
font-weight: 500;
line-height: 22px;
color: var(--gray)
}

.content-3 {
Expand Down
2 changes: 1 addition & 1 deletion app/components/modal/footer_component.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="modal-footer <%= @class %>">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">Close</button>
<%= content %>
</div>
15 changes: 11 additions & 4 deletions app/controllers/case_court_reports_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ def show

def generate
authorize CaseCourtReport
casa_case = CasaCase.find_by(case_params)
casa_case = CasaCase.find_by(case_number: case_params[:case_number])

respond_to do |format|
format.json do
if casa_case
report_data = generate_report_to_string(casa_case, params[:time_zone])
report_data = generate_report_to_string(casa_case, date_range_params)
save_report(report_data, casa_case)

render json: {link: case_court_report_path(casa_case.case_number, format: "docx"), status: :ok}
Expand All @@ -53,6 +54,10 @@ def generate

private

def date_range_params
params.permit(:time_zone, case_court_report: %i[start_date end_date])
end

def case_params
params.require(:case_court_report).permit(:case_number)
end
Expand All @@ -69,15 +74,17 @@ def assigned_cases
end
end

def generate_report_to_string(casa_case, time_zone)
def generate_report_to_string(casa_case, time_range)
return unless casa_case

casa_case.casa_org.open_org_court_report_template do |template_docx_file|
args = {
volunteer_id: current_user.volunteer? ? current_user.id : casa_case.assigned_volunteers.first&.id,
case_id: casa_case.id,
path_to_template: template_docx_file.to_path,
time_zone: time_zone
time_zone: time_range[:time_zone],
start_date: time_range[:case_court_report][:start_date],
end_date: time_range[:case_court_report][:end_date]
}
context = CaseCourtReportContext.new(args).context
court_report = CaseCourtReport.new(path_to_template: template_docx_file.to_path, context: context)
Expand Down
6 changes: 6 additions & 0 deletions app/javascript/src/casa_case.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,24 @@ function copyOrdersFromCaseAction (id, caseNumber) {
}

function showBtn (el) {
if (!el) return
el.classList.remove('d-none')
}

function hideBtn (el) {
if (!el) return
el.classList.add('d-none')
}

function disableBtn (el) {
if (!el) return
el.disabled = true
el.classList.add('disabled')
el.setAttribute('aria-disabled', true)
}

function enableBtn (el) {
if (!el) return
el.disabled = false
el.classList.remove('disabled')
el.removeAttribute('aria-disabled')
Expand Down Expand Up @@ -101,6 +105,7 @@ function handleGenerateReport (e) {
body: JSON.stringify(formData)
}
showBtn(spinner)
hideBtn($('#btnGenerateReport .lni-download')[0])
window.fetch(url, options)
.then(response => {
return response.json()
Expand All @@ -113,6 +118,7 @@ function handleGenerateReport (e) {
return
}
hideBtn(spinner)
showBtn($('#btnGenerateReport .lni-download')[0])
enableBtn(generateBtn)
window.open(data.link, '_blank')
})
Expand Down
31 changes: 21 additions & 10 deletions app/models/case_court_report_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require "date"

class CaseCourtReportContext
attr_reader :report_path, :template
attr_reader :report_path, :template, :date_range

def initialize(args = {})
@casa_case = CasaCase.friendly.find(args[:case_id])
Expand All @@ -12,6 +12,7 @@ def initialize(args = {})
@path_to_template = args[:path_to_template]
@court_date = args[:court_date] || @casa_case.next_court_date
@case_court_orders = args[:case_court_orders] || @casa_case.case_court_orders
@date_range = calculate_date_range(args)
end

def context
Expand All @@ -35,8 +36,7 @@ def context
# - :dates [Array<String>]
# - :dates_by_medium_type [Array<String>]
def case_contacts
cccts = CaseContactContactType.includes(:case_contact, :contact_type).where("case_contacts.casa_case_id": @casa_case.id)
interviewees = filter_out_old_case_contacts(cccts)
interviewees = filtered_interviewees
return [] unless interviewees.size.positive?

CaseContactsContactDates.new(interviewees).contact_dates_details
Expand All @@ -56,13 +56,11 @@ def case_orders(orders)
end
end

def filter_out_old_case_contacts(interviewees)
most_recent_court_date = @casa_case.most_recent_past_court_date&.date
if most_recent_court_date
interviewees.where("occurred_at >= ?", most_recent_court_date)
else
interviewees
end
def filtered_interviewees
# this query is slow
CaseContactContactType.includes(:case_contact, :contact_type)
.where("case_contacts.casa_case_id": @casa_case.id)
.where("case_contacts.occurred_at": @date_range)
end

def case_details
Expand All @@ -89,4 +87,17 @@ def org_address(path_to_template)
is_default_template = path_to_template.end_with?("default_report_template.docx")
@volunteer.casa_org.address if @volunteer && is_default_template
end

private

def calculate_date_range(args)
zone = args[:time_zone] ? ActiveSupport::TimeZone.new(args[:time_zone]) : Time.zone

start_date = @casa_case.most_recent_past_court_date&.date&.in_time_zone(zone)
start_date = zone.parse(args[:start_date]) if args[:start_date]&.present?

end_date = args[:end_date]&.present? ? zone.parse(args[:end_date]) : nil

start_date..end_date
end
end
16 changes: 11 additions & 5 deletions app/views/casa_cases/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,17 @@
<% end %>
<%= form_with url: generate_case_court_reports_path, local: false, class: "d-inline" do |form| %>
<%= form.hidden_field :case_number, value: @casa_case.case_number %>
<%= button_tag "Generate Report", type: :submit,
data: {button_name: "Generate Report"},
id: "btnGenerateReport",
class: "main-btn success-btn btn-hover btn-sm pull-right mb-2" %>
<i id="spinner" class='fas fa-spin d-none pull-right'></i>
<%= button_tag type: :submit,
data: {
button_name: "Generate Report"
},
id: "btnGenerateReport",
class: "main-btn btn-hover btn-sm success-btn pull-right mb-2",
onclick: "setTimeZone()" do %>
<i class="lni lni-download mr-10"></i>
<i id="spinner" class='fas fa-spin d-none mr-10'></i>
Generate Report
<% end %>
<% end %>
<% if @casa_case.casa_org.show_fund_request %>
<%= link_to("New Fund Request", new_casa_case_fund_request_path(@casa_case),
Expand Down
75 changes: 75 additions & 0 deletions app/views/case_court_reports/_generate_docx.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<%= form_with url: generate_case_court_reports_path, local: false do |form| %>
<% id = "generate-docx-report-modal" %>
<%= render(Modal::OpenButtonComponent.new(target: id, klass: "generate-report-button")) do %>
<svg viewBox="0 0 40 50" fill="none" xmlns="http://www.w3.org/2000/svg">
<title>Word Document Logo</title>
<path d="M25 0H5C3.67392 0 2.40215 0.526784 1.46447 1.46447C0.526784 2.40215 0 3.67392 0 5V45C0 46.3261 0.526784 47.5979 1.46447 48.5355C2.40215 49.4732 3.67392 50 5 50H35C36.3261 50 37.5979 49.4732 38.5355 48.5355C39.4732 47.5979 40 46.3261 40 45V15L25 0ZM28 45H24.5L20 28L15.5 45H12L6.5 22.5H10.25L13.75 39.5L18.25 22.5H21.5L26 39.5L29.5 22.5H33.25L28 45ZM22.5 17.5V3.75L36.25 17.5H22.5Z" fill="#4A6CF7" />
</svg>
<div>
<h3 class="content-1">Download Court Report as .docx</h3>
<p class="content-2">
The Court Report is pre-filled with information for your case. You can select among currently active cases assigned to you. The document is in Microsoft Word format (.docx).
</p>
</div>
<% end %>
<%= render(Modal::GroupComponent.new(id: id)) do |component| %>
<% component.with_header(text: "Download Court Report as a .docx", id: id, klass: "content-1") %>
<% component.with_body do %>
<div class="docx-report__modal-body">
<p class="content-3 md-10">
To download a court report, choose an active case and specify the date range.
</p>
<div class="input-style-1" id="case_select_body">
<%= form.label :case_selection, "Case" %>
<% select_options = @assigned_cases.map { |casa_case| casa_case.decorate.court_report_select_option } %>

<% show_search = !current_user.volunteer? %>

<% select_case_prompt = show_search ? "Search by volunteer name or case number" : "Select case number" %>
<% select2_class = show_search ? " select2" : "" %>
<%= select_tag :case_number,
options_for_select(select_options),
prompt: select_case_prompt,
include_blank: false,
id: "case-selection",
class: "custom-select#{select2_class}",
data: { dropdown_parent: "##{id}" } %>

<%= form.hidden_field :time_zone, id: "user-time-zone" %>
</div>
<div class="dates-container">
<div class="field form-group mb-20">
<h6><label class="form-label" for="start_date">Starting From</label></h6>
<%= form.text_field :start_date,
value: Time.zone.now.strftime(::DateHelper::RUBY_MONTH_DAY_YEAR_FORMAT),
data: { provide: "datepicker",
date_format: ::DateHelper::JQUERY_MONTH_DAY_YEAR_FORMAT },
class: "form-control" %>
</div>

<div class="field form-group mb-20">
<h6><label class="form-label" for="end_date">Ending At</label></h6>
<%= form.text_field :end_date,
value: Time.zone.now.strftime(::DateHelper::RUBY_MONTH_DAY_YEAR_FORMAT),
data: { provide: "datepicker",
date_format: ::DateHelper::JQUERY_MONTH_DAY_YEAR_FORMAT },
class: "form-control" %>
</div>
</div>
</div>
<% end %>
<% component.with_footer do %>
<%= button_tag type: :submit,
data: {
button_name: "Generate Report"
},
id: "btnGenerateReport",
class: "main-btn primary-btn btn-hover btn-sm",
onclick: "setTimeZone()" do %>
<i class="lni lni-download mr-10"></i>
<i id="spinner" class='fas fa-spin d-none mr-10'></i>
Generate Report
<% end %>
<% end %>
<% end %>
<% end %>
40 changes: 3 additions & 37 deletions app/views/case_court_reports/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="row align-items-center">
<div class="col-md-6">
<div class="title mb-30">
<h1>Report Categories</h1>
<h1>Generate Reports</h1>
</div>
</div>
</div>
Expand All @@ -11,42 +11,8 @@
<div class="row">
<div class="col-lg-12">
<div class="card-style mb-30">
<h6 class="mb-10">Generate Court Report</h6>
<p class="text-sm mb-25">
The Court Report is pre-filled with information for your case. You can select among currently active cases assigned to you. The document is in Microsoft Word format (.docx).
</p>
<%= form_with url: generate_case_court_reports_path, local: false do |form| %>
<div class="input-style-1">
<%= form.label :case_selection, "Case Number:" %>
<% select_options = @assigned_cases.map { |casa_case| casa_case.decorate.court_report_select_option } %>

<% show_search = !current_user.volunteer? %>

<% select_case_prompt = show_search ? "Search by volunteer name or case number" : "Select case number" %>
<% select2_class = show_search ? "select2" : "" %>

<%= select_tag :case_number,
options_for_select(select_options),
prompt: select_case_prompt,
include_blank: false,
id: "case-selection",
class: "custom-select #{select2_class}" %>

<%= form.hidden_field :time_zone, id: "user-time-zone" %>
</div>
<div class="input-style-1">
<%= button_tag type: :submit,
data: {
button_name: "Generate Report"
},
id: "btnGenerateReport",
class: "main-btn primary-btn btn-hover btn-sm",
onclick: "setTimeZone()" do %>
<i class="lni lni-download mr-10"></i> Generate Report
<% end %>
<i id="spinner" class='fas fa-spin d-none'></i>
</div>
<% end %>
<h6 class="mb-10">Court Reports</h6>
<%= render "case_court_reports/generate_docx" %>
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit e2af233

Please sign in to comment.