diff --git a/scripts/generate-checklist-pdf.py b/scripts/generate-checklist-pdf.py new file mode 100644 index 000000000..db71f8ef7 --- /dev/null +++ b/scripts/generate-checklist-pdf.py @@ -0,0 +1,136 @@ +""" +Generate the RecordSponge Expungement Checklist PDF. + +Requirements: pip install reportlab + +Output: src/frontend/public/docs/expungement-checklist.pdf + +Run from the project root: + python scripts/generate-checklist-pdf.py +""" + +import os +from reportlab.lib.pagesizes import letter +from reportlab.lib.units import inch +from reportlab.lib.colors import HexColor, black, white +from reportlab.platypus import ( + SimpleDocTemplate, Paragraph, Spacer, HRFlowable, Flowable +) +from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +OUTPUT_PATH = os.path.join(SCRIPT_DIR, "..", "src", "frontend", "public", "docs", "expungement-checklist.pdf") + + +class CheckboxStep(Flowable): + """A checkbox followed by step text, vertically aligned.""" + + def __init__(self, text, style, checkbox_size=11): + super().__init__() + self.text = text + self.style = style + self.checkbox_size = checkbox_size + self._para = Paragraph(text, style) + + def wrap(self, availWidth, availHeight): + text_width = availWidth - self.checkbox_size - 10 + self._para_w, self._para_h = self._para.wrap(text_width, availHeight) + self.width = availWidth + self.height = self._para_h + 4 + return self.width, self.height + + def draw(self): + para_y = self.height - self._para_h + self._para.drawOn(self.canv, self.checkbox_size + 10, para_y) + + cb_y = self.height - self._para_h + (self._para_h - self.checkbox_size) / 2 - 1 + + self.canv.setStrokeColor(black) + self.canv.setFillColor(white) + self.canv.setLineWidth(0.8) + self.canv.rect(0, max(0, cb_y), self.checkbox_size, self.checkbox_size, fill=1, stroke=1) + + +def generate(): + os.makedirs(os.path.dirname(OUTPUT_PATH), exist_ok=True) + + doc = SimpleDocTemplate( + OUTPUT_PATH, + pagesize=letter, + topMargin=0.75 * inch, + bottomMargin=0.75 * inch, + leftMargin=0.75 * inch, + rightMargin=0.75 * inch, + ) + + styles = getSampleStyleSheet() + blue = HexColor("#357edd") + dark = HexColor("#333333") + gray = HexColor("#555555") + + title_style = ParagraphStyle("ChecklistTitle", parent=styles["Title"], fontSize=20, textColor=dark, spaceAfter=6) + subtitle_style = ParagraphStyle("Subtitle", parent=styles["Normal"], fontSize=11, textColor=gray, spaceAfter=4) + step_style = ParagraphStyle("StepStyle", parent=styles["Normal"], fontSize=12, textColor=dark, fontName="Helvetica-Bold", spaceBefore=0, spaceAfter=4, leading=14) + sub_style = ParagraphStyle("SubStyle", parent=styles["Normal"], fontSize=11, textColor=gray, leftIndent=28, spaceBefore=2, spaceAfter=2) + note_style = ParagraphStyle("NoteStyle", parent=styles["Normal"], fontSize=11, textColor=gray, spaceBefore=0, spaceAfter=4, borderWidth=1, borderColor=HexColor("#cccccc"), borderPadding=8) + + link_str = 'color="#357edd"' + story = [] + + story.append(Paragraph("RecordSponge Expungement Checklist", title_style)) + story.append(Paragraph("A step-by-step guide to the expungement process", subtitle_style)) + story.append(HRFlowable(width="100%", thickness=1, color=blue, spaceAfter=12)) + + steps = [ + { + "title": "Log in to OECI", + "subs": [ + "You will need an OECI account to search for criminal records.", + f'Purchase a subscription at courts.oregon.gov.', + ], + }, + { + "title": "Search records", + "subs": [ + "Ensure that Assumptions are met", + "Search by name and date of birth", + ], + }, + { + "title": "Complete paperwork for expungement", + "subs": [ + "This includes paperwork to modify financial obligations if applicable", + ], + }, + { + "title": "Obtain fingerprints", + "subs": [ + "Mail to Oregon State Police", + ], + }, + { + "title": "File paperwork in appropriate courts", + "subs": [], + }, + ] + + for i, step in enumerate(steps, 1): + story.append(Spacer(1, 10)) + story.append(CheckboxStep(f'Step {i}: {step["title"]}', step_style)) + for sub in step["subs"]: + story.append(Paragraph(f"\u2022 {sub}", sub_style)) + + story.append(Spacer(1, 24)) + story.append(Paragraph( + f'Note: If new to RecordSponge, confirm results with Michael Zhang at ' + f'michael@qiu-qiulaw.com.

' + f'For further details, visit recordsponge.com/manual.', + note_style, + )) + + doc.build(story) + print(f"PDF generated: {os.path.abspath(OUTPUT_PATH)}") + + +if __name__ == "__main__": + generate() diff --git a/src/frontend/public/docs/expungement-checklist.pdf b/src/frontend/public/docs/expungement-checklist.pdf new file mode 100644 index 000000000..fd1695435 Binary files /dev/null and b/src/frontend/public/docs/expungement-checklist.pdf differ diff --git a/src/frontend/public/img/aliases.webp b/src/frontend/public/img/aliases.webp new file mode 100644 index 000000000..795b4be17 Binary files /dev/null and b/src/frontend/public/img/aliases.webp differ diff --git a/src/frontend/public/img/expanded-view-generate-paperwork.webp b/src/frontend/public/img/expanded-view-generate-paperwork.webp new file mode 100644 index 000000000..2d4e60196 Binary files /dev/null and b/src/frontend/public/img/expanded-view-generate-paperwork.webp differ diff --git a/src/frontend/public/img/expanded-view.webp b/src/frontend/public/img/expanded-view.webp new file mode 100644 index 000000000..8224e5fb1 Binary files /dev/null and b/src/frontend/public/img/expanded-view.webp differ diff --git a/src/frontend/public/img/full-results.webp b/src/frontend/public/img/full-results.webp new file mode 100644 index 000000000..00e686d97 Binary files /dev/null and b/src/frontend/public/img/full-results.webp differ diff --git a/src/frontend/public/img/generate-expungement-forms.webp b/src/frontend/public/img/generate-expungement-forms.webp new file mode 100644 index 000000000..b4ea3b286 Binary files /dev/null and b/src/frontend/public/img/generate-expungement-forms.webp differ diff --git a/src/frontend/public/img/search-form.webp b/src/frontend/public/img/search-form.webp new file mode 100644 index 000000000..45ad3e6fb Binary files /dev/null and b/src/frontend/public/img/search-form.webp differ diff --git a/src/frontend/public/img/search-results.webp b/src/frontend/public/img/search-results.webp new file mode 100644 index 000000000..79ac7dd16 Binary files /dev/null and b/src/frontend/public/img/search-results.webp differ diff --git a/src/frontend/public/img/simple-search.webp b/src/frontend/public/img/simple-search.webp new file mode 100644 index 000000000..0f6abf2e1 Binary files /dev/null and b/src/frontend/public/img/simple-search.webp differ diff --git a/src/frontend/public/img/smart-search.webp b/src/frontend/public/img/smart-search.webp new file mode 100644 index 000000000..483cab38c Binary files /dev/null and b/src/frontend/public/img/smart-search.webp differ diff --git a/src/frontend/public/img/wildcard-search.webp b/src/frontend/public/img/wildcard-search.webp new file mode 100644 index 000000000..08a2cd1b1 Binary files /dev/null and b/src/frontend/public/img/wildcard-search.webp differ diff --git a/src/frontend/src/components/App/App.test.tsx b/src/frontend/src/components/App/App.test.tsx index b67989ffe..ec8086dd5 100644 --- a/src/frontend/src/components/App/App.test.tsx +++ b/src/frontend/src/components/App/App.test.tsx @@ -39,7 +39,7 @@ describe("App routing", () => { ["/", "winner"], ["/oeci", "ecourt"], ["/demo-record-search", "app demo"], - ["/manual", "introduction"], + ["/manual", "RecordSponge"], ["/rules", "type eligibility rules"], ["/faq", "myth"], ["/appendix", "forms to file"], diff --git a/src/frontend/src/components/Appendix/index.tsx b/src/frontend/src/components/Appendix/index.tsx index 227d11420..7474fa66b 100644 --- a/src/frontend/src/components/Appendix/index.tsx +++ b/src/frontend/src/components/Appendix/index.tsx @@ -22,7 +22,7 @@ class Landing extends React.Component { counties listed here, and will use the Stock Form for those not listed. You can also fill out the forms manually if preferred.{" "} - + Learn more in the Manual . diff --git a/src/frontend/src/components/FillForms/index.tsx b/src/frontend/src/components/FillForms/index.tsx index 2f43b14c5..0650221dd 100644 --- a/src/frontend/src/components/FillForms/index.tsx +++ b/src/frontend/src/components/FillForms/index.tsx @@ -136,7 +136,7 @@ export default function FillFormsIndex() { available, it will be provided in the form. If it is not present in OECI, some of the information may or may not be required in the application; please consult the{" "} - + Manual . @@ -162,7 +162,7 @@ export default function FillFormsIndex() {

Please read the complete instructions in the{" "} - + Manual {" "} for filing the required forms for expungement. After downloading diff --git a/src/frontend/src/components/Footer/index.tsx b/src/frontend/src/components/Footer/index.tsx index 73d37b124..1ebc81bf7 100644 --- a/src/frontend/src/components/Footer/index.tsx +++ b/src/frontend/src/components/Footer/index.tsx @@ -4,7 +4,7 @@ import { Link } from "react-router-dom"; export default class Footer extends React.Component { public render() { return ( -