Reputation: 3635
I'm generating PDF report in my Rails app and uses gem "prawn" but having trouble handling the descriptions data because it contains html tags e.g. < b >, < ul >, < li >, < img >, < table > and more...
# frozen_string_literal: true
require 'prawn'
require 'prawn/table'
module User
module Reports
class GeneratePdf
include ActionView::Helpers::NumberHelper
include ActionView::Helpers::DateHelper
include Seo::ApplicationHelper
BORDER_COLOR = 'dddddd'.freeze
TABLE_HEADER_COLOR = 'f2f0f0'.freeze
WHITE_COLOR = 'ffffff'.freeze
TABLE_HEADERS = [[I18n.t("seo.reports.type_of_fix"), I18n.t("seo.reports.description"), I18n.t("seo.reports.fixed_at")]].freeze
A4_SIZE = [595.276, 841.890]
attr_reader :shop
def initialize(shop)
@shop = shop
@pdf = Prawn::Document.new(page_size: A4_SIZE)
@document_width = @pdf.bounds.width
end
def perform
report_summary_section
reports_table
@pdf.render
end
private
def formatted_reports_data
reports = Report.all
reports.map do |report|
fix_type = if report.issue_type.include?('_created')
pretty_report_issue_type(report.issue_type, report.get_description_count)
else
pretty_report_issue_type(report.issue_type)
end
description = pretty_report_description(report.issue_type, report.description) # this is where the HTML tags came from
fixed_at = "#{distance_of_time_in_words_to_now(report.fixed_at)} ago" if report.fixed_at
[fix_type, description, fixed_at]
end
end
def report_summary_section
@pdf.text I18n.t("seo.dashboard.reports.title"), size: 16, style: :bold
@pdf.move_down 5
@pdf.text @shop.domain, size: 12, color: 'a6a6a6', inline_format: true
@pdf.move_down 10
summary_data = [
[
"#{I18n.t("seo.dashboard.reports.total_fixes")}\n<b>#{number_with_delimiter(@shop.reports_count) || 0}</b>",
"#{I18n.t("seo.dashboard.reports.title_tags_fixed")}\n<b>#{number_with_delimiter(@shop.report_title_count) || 0}</b>",
"#{I18n.t("seo.dashboard.reports.meta_tags_fixed")}\n<b>#{number_with_delimiter(@shop.report_desc_count) || 0}</b>"
],
[
"#{I18n.t("seo.dashboard.reports.alt_texts_fixed")}\n<b>#{number_with_delimiter(@shop.report_alt_count) || 0}</b>",
"#{I18n.t("seo.dashboard.reports.links_fixed")}\n<b>#{number_with_delimiter(@shop.report_links_count) || 0}</b>",
"#{I18n.t("seo.dashboard.reports.bulk_updates")}\n<b>#{number_with_delimiter(@shop.report_bulk_count) || 0}</b>"
]
]
column_width = @document_width / 3.0
summary_options = {
cell_style: {
size: 12,
inline_format: true,
padding: [15, 10],
borders: [:top, :bottom, :left, :right],
border_width: 1,
border_color: BORDER_COLOR,
align: :center,
valign: :center
},
column_widths: [column_width] * 3
}
@pdf.table(summary_data, summary_options) do |table|
table.cells.each do |cell|
cell.content = cell.content.sub('<b>', '<font size="18"><b>').sub('</b>', '</b></font>')
end
end
end
def reports_table
@pdf.move_down 20
report_data_options = {
width: @document_width,
row_colors: [WHITE_COLOR],
cell_style: {
border_width: 1,
borders: [:bottom],
border_color: BORDER_COLOR,
size: 10,
inline_format: true
}
}
@pdf.table(TABLE_HEADERS + formatted_reports_data, report_data_options) do |table|
table.row(0).font_style = :bold
table.row(0).background_color = TABLE_HEADER_COLOR
table.row(0).size = 9
table.cells.each do |cell|
cell.content = cell.content # I plan to catch here, i can sanitize but I need to render the <html> codes as it is in PDF
end
end
end
end
end
end
Upvotes: 0
Views: 54