-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rudimentary reporting framework for custom reports
- Loading branch information
Showing
14 changed files
with
451 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
Trestle.admin(:reports) do | ||
menu do | ||
item :reports, icon: "fas fa-file-alt" | ||
end | ||
|
||
controller do | ||
def index | ||
@reports = Report::AVAILABLE_REPORTS | ||
end | ||
|
||
def show | ||
@report = Report::AVAILABLE_REPORTS.find { |x| params[:name] == x.name } | ||
end | ||
|
||
def generate_report | ||
@report = Report::AVAILABLE_REPORTS.find { |x| params[:name] == x.name } | ||
report_params = params.permit(@report.inputs.keys).to_h | ||
report_instance = @report.new(report_params.symbolize_keys) | ||
report_instance.perform unless report_instance.errors.any? | ||
|
||
if report_instance.errors.any? | ||
flash[:error] = report_instance.errors.join("\n") | ||
render :show | ||
else | ||
if params[:format] == "download" | ||
stream_table(report_instance) | ||
else | ||
@data = report_instance.data | ||
@headers = report_instance.headers | ||
render :result | ||
end | ||
end | ||
end | ||
|
||
private | ||
def stream_table(report) | ||
require 'csv' | ||
headers.delete("Content-Length") | ||
headers["Cache-Control"] = "no-cache" | ||
headers["Content-Type"] = "text/csv" | ||
headers["Content-Disposition"] = "attachment; filename=\"#{report.class.name}-#{Date.today}.tsv\"" | ||
headers["X-Accel-Buffering"] = "no" | ||
response.status = 200 | ||
|
||
self.response_body = Enumerator.new do |stream| | ||
stream << CSV.generate_line(report.headers, col_sep: "\t") | ||
report.data.each do |row| | ||
stream << CSV.generate_line(row, col_sep: "\t") | ||
end | ||
end | ||
end | ||
end | ||
|
||
routes do | ||
get '/:name', action: :show | ||
post '/:name', action: :generate_report | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
Trestle.admin(:utilities) do | ||
menu do | ||
item :utilities, icon: "fas fa-cogs" | ||
end | ||
|
||
controller do | ||
def index | ||
@utilities = ActionWrapper::AVAILABLE_ACTIONS | ||
end | ||
|
||
def show | ||
@util = ActionWrapper::AVAILABLE_ACTIONS.find { |x| params[:name] == x.name } | ||
end | ||
|
||
def perform_action | ||
@util = ActionWrapper::AVAILABLE_ACTIONS.find { |x| params[:name] == x.name } | ||
util_params = params.permit(@util.inputs.keys).to_h | ||
action = @util.new | ||
res = action.perform(util_params.symbolize_keys) | ||
|
||
if res.errors.any? | ||
flash[:error] = res.errors.join("\n") | ||
else | ||
flash[:message] = "#{@util.name} Succeeded" | ||
end | ||
|
||
render :show | ||
end | ||
end | ||
|
||
routes do | ||
get '/:name', action: :show | ||
post '/:name', action: :perform_action | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
class ClingenCounts < Report | ||
attr_reader :start_date, :end_date, :all_org_ids | ||
CLINGEN_ORG_ID = 2 | ||
|
||
def self.name | ||
"ClinGen Contributions" | ||
end | ||
|
||
def self.description | ||
"Count contributions from ClinGen member orgs over a specified timespan." | ||
end | ||
|
||
def self.inputs | ||
{ | ||
start_date: :date, | ||
end_date: :date, | ||
include_suborgs: :boolean | ||
} | ||
end | ||
|
||
def setup(start_date:, end_date:, include_suborgs:) | ||
@start_date = Date.parse(start_date) | ||
@end_date = Date.parse(end_date) | ||
|
||
clingen_org = Organization.find(CLINGEN_ORG_ID) | ||
if include_suborgs | ||
sub_groups = clingen_org.groups | ||
@all_org_ids = [clingen_org.id] + sub_groups.map(&:id) | ||
else | ||
@all_org_ids = clingen_org.id | ||
end | ||
end | ||
|
||
def headers | ||
["Contribution Type", "Count"] | ||
end | ||
|
||
def execute | ||
data << ["Assertions Submitted", SubmitAssertionActivity.where(organization_id: all_org_ids, created_at: (start_date..end_date)).count] | ||
data << ["Evidence Submitted", SubmitEvidenceItemActivity.where(organization_id: all_org_ids, created_at: (start_date..end_date)).count] | ||
data << ["Comments Made", CommentActivity.where(organization_id: all_org_ids, created_at: (start_date..end_date)).count] | ||
data << ["Revisions Suggested", Event.where(organization_id: all_org_ids, action: 'revision suggested', created_at: (start_date..end_date)).count] | ||
data << ["Proposed Revisions Accepted", calculate_contribution('revision suggested', 'revision suggested')] | ||
data << ["Submitted Evidence Accepted", calculate_contribution('accepted', 'submitted')] | ||
data << ["Submitted Assertions Accepted", calculate_contribution('assertion accepted', 'assertion submitted')] | ||
end | ||
|
||
private | ||
def calculate_contribution(submission_event_name, accept_event_name) | ||
contributed_by_clingen = 0 | ||
Event.where(action: accept_event_name, created_at: (start_date..end_date)).find_each do |e| | ||
if Event.where(action: submission_event_name, organization_id: all_org_ids, subject: e.subject).exists? | ||
contributed_by_clingen += 1 | ||
end | ||
end | ||
contributed_by_clingen | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
class Report | ||
AVAILABLE_REPORTS = [ | ||
ClingenCounts | ||
] | ||
|
||
def initialize(params) | ||
setup(**params) | ||
rescue => e | ||
errors << e.message | ||
end | ||
|
||
attr_reader :data, :headers, :errors | ||
|
||
def self.name | ||
raise NotImplementedError.new("Specify in subclass") | ||
end | ||
|
||
def self.description | ||
raise NotImplementedError.new("Specify in subclass") | ||
end | ||
|
||
# Can users download this as a TSV | ||
def self.downloadable? | ||
true | ||
end | ||
|
||
# Can users view this directly in the admin UI | ||
def self.viewable? | ||
true | ||
end | ||
|
||
def self.inputs | ||
#format input_name: :type | ||
#supported types :text, :date, :boolean, :int | ||
{} | ||
end | ||
|
||
# Column headers for the report | ||
def headers | ||
raise NotImplementedError.new("Specify in subclass") | ||
end | ||
|
||
# Data rows. #execute should append rows to this list | ||
def data | ||
@data ||= [] | ||
end | ||
|
||
# Append any errors here | ||
def errors | ||
@errors ||= [] | ||
end | ||
|
||
def perform | ||
execute | ||
rescue => e | ||
errors << e.message | ||
end | ||
|
||
# Called from constructor. | ||
# Will receive named arguments from the form inputs | ||
# specified by self.inputs | ||
def setup | ||
raise NotImplementedError.new("Specify in subclass") | ||
end | ||
|
||
# Invoke the report logic. Must set data, headers, or errors | ||
def execute | ||
raise NotImplementedError.new("Specify in subclass") | ||
end | ||
end |
Oops, something went wrong.