docassemble.AssemblyLine 4.3.0__tar.gz → 4.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {docassemble_assemblyline-4.3.0/docassemble.AssemblyLine.egg-info → docassemble_assemblyline-4.5.0}/PKG-INFO +2 -2
- docassemble_assemblyline-4.5.0/docassemble/AssemblyLine/__init__.py +1 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/al_courts.py +1 -3
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/al_document.py +115 -9
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/al_general.py +10 -9
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/custom_jinja_filters.py +50 -5
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/al_code.yml +67 -30
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/al_document.yml +62 -39
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/al_language.yml +4 -4
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/al_question_test.yml +7 -7
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/al_reminders.yml +51 -19
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/al_saved_sessions.yml +22 -15
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/al_saved_sessions_store.yml +5 -1
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/al_settings.yml +20 -14
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/al_visual.yml +59 -27
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/assembly_line.yml +2 -2
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/demo_search_sessions.yml +11 -5
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/feedback.yml +1 -2
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/interview_list.yml +59 -45
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/ql_baseline.yml +83 -47
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/ql_catchall.yml +1 -1
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/ql_namechange.yml +1 -1
- docassemble_assemblyline-4.5.0/docassemble/AssemblyLine/data/questions/reserved_words.yml +94 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/test_alcourts.yml +5 -5
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/test_aldocument.yml +7 -7
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/test_aldocument_background_assembly.yml +1 -1
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/test_preferred_name.yml +7 -7
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/test_question_library.yml +12 -9
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/sources/ar-words.yml +1 -1
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/sources/es-words.yml +3 -3
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/sources/fr-words.yml +3 -3
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/sources/ne-words.yml +3 -3
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/sessions.py +2 -6
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/test_al_general.py +14 -1
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0/docassemble.AssemblyLine.egg-info}/PKG-INFO +2 -2
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble.AssemblyLine.egg-info/requires.txt +1 -1
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/pyproject.toml +2 -2
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/setup.py +2 -2
- docassemble_assemblyline-4.3.0/docassemble/AssemblyLine/__init__.py +0 -1
- docassemble_assemblyline-4.3.0/docassemble/AssemblyLine/data/questions/reserved_words.yml +0 -92
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/LICENSE +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/MANIFEST.in +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/README.md +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/al_package.yml +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/al_package_unstyled.yml +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/al_terms_of_use.yml +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/assembly_line_unstyled.yml +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/test_al_table_document.yml +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/test_aladdendum.yml +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/test_alexhibit.yml +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/test_alexhibit_maxsize.yml +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/test_bundle_parity.yml +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/test_catchall.yml +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/test_familiar_disambiguation.yml +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/test_if_final.yml +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/test_preferred_formats.yml +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/questions/test_signature.yml +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/sources/README.md +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/sources/languages.yml +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/sources/test_aldocument.feature +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/sources/test_alexhibit_docx_1.docx +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/sources/test_alexhibit_jpg_1.jpg +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/sources/test_alexhibit_pdf_1.pdf +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/sources/test_alexhibit_png_1.png +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/sources/test_question_library.feature +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/sources/translation_es.xlsx +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/sources/translation_ht.xlsx +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/sources/translation_pt.xlsx +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/static/README.md +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/static/al_audio.css +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/static/al_audio.js +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/static/aldocument.css +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/static/aldocument.js +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/static/interview_list.css +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/static/limit_upload_size.js +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/static/lt1-pullout-10-getting-organized.pdf +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/static/ma_logo.png +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/static/placeholder.png +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/static/seal.jpg +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/static/styles.css +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/templates/README.md +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/templates/al_basic_addendum.docx +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/templates/exhibit_cover_sheet.docx +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/templates/exhibit_table_of_contents.docx +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/templates/general_cover_sheet.docx +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/templates/sample_word_template.docx +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/templates/test_aldocument_docx_1.docx +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/templates/test_aldocument_pdf_1.pdf +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/templates/test_catchall.docx +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/data/templates/test_if_final.docx +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/language.py +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/py.typed +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/requirements.txt +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/sign.py +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/test_al_document.py +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble/AssemblyLine/test_language.py +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble.AssemblyLine.egg-info/SOURCES.txt +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble.AssemblyLine.egg-info/dependency_links.txt +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble.AssemblyLine.egg-info/not-zip-safe +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/docassemble.AssemblyLine.egg-info/top_level.txt +0 -0
- {docassemble_assemblyline-4.3.0 → docassemble_assemblyline-4.5.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: docassemble.AssemblyLine
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.5.0
|
|
4
4
|
Summary: Quickly go from a paper court form to a runnable, guided, step-by-step web application powered by Docassemble. Swap out branding and pre-built questions to meet your needs.
|
|
5
5
|
Home-page: https://courtformsonline.org
|
|
6
6
|
Author: Suffolk Legal Innovation and Technology Lab
|
|
@@ -9,7 +9,7 @@ License-Expression: MIT
|
|
|
9
9
|
Project-URL: Homepage, https://courtformsonline.org
|
|
10
10
|
Description-Content-Type: text/markdown
|
|
11
11
|
License-File: LICENSE
|
|
12
|
-
Requires-Dist: docassemble.ALToolbox>=0.
|
|
12
|
+
Requires-Dist: docassemble.ALToolbox>=0.16.0
|
|
13
13
|
Requires-Dist: docassemble.GitHubFeedbackForm>=0.4.1.1
|
|
14
14
|
Dynamic: author
|
|
15
15
|
Dynamic: home-page
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '4.5.0'
|
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
Package for a very simple / MVP list of courts that is mostly signature compatible w/ MACourts for now
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
from typing import Any, Callable, Dict, List, Mapping, Optional, Union, Set, Tuple
|
|
5
|
+
from typing import Any, Callable, Dict, List, Optional, Union, Set, Tuple
|
|
7
6
|
import pandas as pd
|
|
8
7
|
import docassemble.base.functions
|
|
9
8
|
from docassemble.base.util import (
|
|
10
9
|
path_and_mimetype,
|
|
11
|
-
Address,
|
|
12
10
|
LatitudeLongitude,
|
|
13
11
|
DAObject,
|
|
14
12
|
log,
|
|
@@ -35,7 +35,6 @@ from docassemble.base.pdfa import pdf_to_pdfa
|
|
|
35
35
|
from textwrap import wrap
|
|
36
36
|
from math import floor
|
|
37
37
|
import subprocess
|
|
38
|
-
from collections import ChainMap
|
|
39
38
|
import pikepdf
|
|
40
39
|
from typing import Tuple
|
|
41
40
|
import secrets
|
|
@@ -1582,6 +1581,7 @@ class ALDocumentBundle(DAList):
|
|
|
1582
1581
|
self.auto_gather = False
|
|
1583
1582
|
if "gathered" not in kwargs:
|
|
1584
1583
|
self.gathered = True
|
|
1584
|
+
self._set_default_attributes()
|
|
1585
1585
|
self.initializeAttribute("cache", DALazyAttribute)
|
|
1586
1586
|
self.always_enabled = hasattr(self, "enabled") and self.enabled
|
|
1587
1587
|
# Pre-cache some DALazyTemplates we set up to aid translation that won't
|
|
@@ -1590,6 +1590,24 @@ class ALDocumentBundle(DAList):
|
|
|
1590
1590
|
# When the key is "preview", append it to the file name
|
|
1591
1591
|
self.suffix_to_append = "preview"
|
|
1592
1592
|
|
|
1593
|
+
def _set_default_attributes(self) -> None:
|
|
1594
|
+
if not hasattr(self, "add_page_numbers"):
|
|
1595
|
+
self.add_page_numbers = False
|
|
1596
|
+
if not hasattr(self, "page_number_prefix"):
|
|
1597
|
+
self.page_number_prefix = ""
|
|
1598
|
+
if not hasattr(self, "page_number_start"):
|
|
1599
|
+
self.page_number_start = 1
|
|
1600
|
+
if not hasattr(self, "page_number_digits"):
|
|
1601
|
+
self.page_number_digits = 5
|
|
1602
|
+
if not hasattr(self, "page_number_area"):
|
|
1603
|
+
self.page_number_area = None
|
|
1604
|
+
if not hasattr(self, "page_number_font_size"):
|
|
1605
|
+
self.page_number_font_size = 10
|
|
1606
|
+
if not hasattr(self, "page_number_offset_horizontal"):
|
|
1607
|
+
self.page_number_offset_horizontal = 15
|
|
1608
|
+
if not hasattr(self, "page_number_offset_vertical"):
|
|
1609
|
+
self.page_number_offset_vertical = 15
|
|
1610
|
+
|
|
1593
1611
|
def as_pdf(
|
|
1594
1612
|
self,
|
|
1595
1613
|
key: str = "final",
|
|
@@ -1649,6 +1667,17 @@ class ALDocumentBundle(DAList):
|
|
|
1649
1667
|
filename=f"{base_name(self.filename)}{append_suffix}.pdf",
|
|
1650
1668
|
pdfa=pdfa,
|
|
1651
1669
|
)
|
|
1670
|
+
if hasattr(self, "add_page_numbers") and self.add_page_numbers:
|
|
1671
|
+
self._set_default_attributes()
|
|
1672
|
+
pdf.bates_number(
|
|
1673
|
+
prefix=self.page_number_prefix,
|
|
1674
|
+
start=self.page_number_start,
|
|
1675
|
+
digits=self.page_number_digits,
|
|
1676
|
+
area=self.page_number_area,
|
|
1677
|
+
font_size=self.page_number_font_size,
|
|
1678
|
+
offset_horizontal=self.page_number_offset_horizontal,
|
|
1679
|
+
offset_vertical=self.page_number_offset_vertical,
|
|
1680
|
+
)
|
|
1652
1681
|
pdf.title = self.title
|
|
1653
1682
|
setattr(self.cache, safe_key, pdf)
|
|
1654
1683
|
|
|
@@ -2386,6 +2415,7 @@ class ALDocumentBundle(DAList):
|
|
|
2386
2415
|
label: str = "Send",
|
|
2387
2416
|
icon: str = "envelope",
|
|
2388
2417
|
preferred_formats: Optional[Union[str, List[str]]] = None,
|
|
2418
|
+
email_legend_class: str = "h4",
|
|
2389
2419
|
) -> str:
|
|
2390
2420
|
"""
|
|
2391
2421
|
Generate HTML for an input box and button that allows someone to send the bundle
|
|
@@ -2405,6 +2435,8 @@ class ALDocumentBundle(DAList):
|
|
|
2405
2435
|
icon (str, optional): The Fontawesome icon for the button. Defaults
|
|
2406
2436
|
to "envelope".
|
|
2407
2437
|
preferred_formats (Optional[Union[str,List[str]]], optional): A list of allowed formats for the document. Defaults to "pdf" if not specified.
|
|
2438
|
+
email_legend_class (str, optional): CSS class applied to the email
|
|
2439
|
+
section legend. Defaults to "h4".
|
|
2408
2440
|
|
|
2409
2441
|
Returns:
|
|
2410
2442
|
str: The generated HTML string for the input box and button.
|
|
@@ -2444,7 +2476,7 @@ class ALDocumentBundle(DAList):
|
|
|
2444
2476
|
# Container of whole email section with header
|
|
2445
2477
|
return_str = f"""
|
|
2446
2478
|
<fieldset class="al_send_bundle al_send_section_alone {html_safe_str(self.instanceName)}" id="al_send_bundle_{name}" name="al_send_bundle_{name}">
|
|
2447
|
-
<legend class="
|
|
2479
|
+
<legend class="{email_legend_class} al_doc_email_header">{str(self.get_email_copy)}</legend>
|
|
2448
2480
|
"""
|
|
2449
2481
|
# "Editable" checkbox
|
|
2450
2482
|
if (
|
|
@@ -2736,9 +2768,14 @@ class ALExhibit(DAObject):
|
|
|
2736
2768
|
self,
|
|
2737
2769
|
*,
|
|
2738
2770
|
refresh: bool = False,
|
|
2739
|
-
prefix: str = "",
|
|
2740
2771
|
pdfa: bool = False,
|
|
2741
2772
|
add_page_numbers: bool = True,
|
|
2773
|
+
page_number_prefix: str = "",
|
|
2774
|
+
page_number_digits: int = 5,
|
|
2775
|
+
page_number_area=None,
|
|
2776
|
+
page_number_font_size: float = 10,
|
|
2777
|
+
page_number_offset_horizontal: float = 15,
|
|
2778
|
+
page_number_offset_vertical: float = 15,
|
|
2742
2779
|
add_cover_page: bool = True,
|
|
2743
2780
|
filename: Optional[str] = None,
|
|
2744
2781
|
append_matching_suffix: bool = True,
|
|
@@ -2750,9 +2787,14 @@ class ALExhibit(DAObject):
|
|
|
2750
2787
|
|
|
2751
2788
|
Args:
|
|
2752
2789
|
refresh (bool): If True, forces the exhibit to refresh before generating the PDF. (unused, provided for signature compatibility)
|
|
2753
|
-
prefix (str): Prefix for Bates numbering if 'add_page_numbers' is True.
|
|
2754
2790
|
pdfa (bool): If True, the generated PDF will be in PDF/A format.
|
|
2755
2791
|
add_page_numbers (bool): If True, apply Bates numbering starting from 'self.start_page'.
|
|
2792
|
+
page_number_prefix (str): If add_page_numbers is True, this gets added to the beginning on the bates number each page (e.g. `EX-`).
|
|
2793
|
+
page_number_digits (int): How many digits (i.e. leading 0s) that the bates number will have
|
|
2794
|
+
page_number_area (str): Where on the page the bates number will go ("TOP_LEFT", "TOP_RIGHT", "BOTTOM_LEFT", "BOTTOM_RIGHT" (default))
|
|
2795
|
+
page_number_font_size (float): How big the bates page number will be in points (default is 10).
|
|
2796
|
+
page_number_offset_horizontal (float): The number of pixels that the bates page number is offset from the left / right of the page.
|
|
2797
|
+
page_number_offset_vertical (float): The number of pixels that the bates page number is offset from the top / bottom of the page.
|
|
2756
2798
|
add_cover_page (bool): If True, prepend the exhibit with a cover page.
|
|
2757
2799
|
filename (Optional[str]): Custom filename for the generated PDF. Default is "exhibits.pdf".
|
|
2758
2800
|
append_matching_suffix (bool): If True, appends a suffix to the filename based on certain matching criteria.
|
|
@@ -2780,7 +2822,15 @@ class ALExhibit(DAObject):
|
|
|
2780
2822
|
)
|
|
2781
2823
|
|
|
2782
2824
|
if add_page_numbers:
|
|
2783
|
-
concatenated_pages.bates_number(
|
|
2825
|
+
concatenated_pages.bates_number(
|
|
2826
|
+
start=self.start_page,
|
|
2827
|
+
prefix=page_number_prefix,
|
|
2828
|
+
digits=page_number_digits,
|
|
2829
|
+
area=page_number_area,
|
|
2830
|
+
font_size=page_number_font_size,
|
|
2831
|
+
offset_horizontal=page_number_offset_horizontal,
|
|
2832
|
+
offset_vertical=page_number_offset_vertical,
|
|
2833
|
+
)
|
|
2784
2834
|
|
|
2785
2835
|
setattr(self._cache, safe_key, concatenated_pages)
|
|
2786
2836
|
return getattr(self._cache, safe_key)
|
|
@@ -2914,6 +2964,12 @@ class ALExhibitList(DAList):
|
|
|
2914
2964
|
filename="file.pdf",
|
|
2915
2965
|
pdfa: bool = False,
|
|
2916
2966
|
add_page_numbers: bool = False,
|
|
2967
|
+
page_number_prefix: str = "",
|
|
2968
|
+
page_number_digits: int = 5,
|
|
2969
|
+
page_number_area=None,
|
|
2970
|
+
page_number_font_size: float = 10,
|
|
2971
|
+
page_number_offset_horizontal: float = 15,
|
|
2972
|
+
page_number_offset_vertical: float = 15,
|
|
2917
2973
|
toc_pages: int = 0,
|
|
2918
2974
|
append_matching_suffix: bool = True,
|
|
2919
2975
|
) -> DAFile:
|
|
@@ -2924,6 +2980,12 @@ class ALExhibitList(DAList):
|
|
|
2924
2980
|
filename (str): Desired filename for the generated PDF.
|
|
2925
2981
|
pdfa (bool): If True, generates the PDF in PDF/A format.
|
|
2926
2982
|
add_page_numbers (bool): If True, adds page numbers to the generated PDF.
|
|
2983
|
+
page_number_prefix (str): What the bates number added to each page should start with (e.g. `EX-`).
|
|
2984
|
+
page_number_digits (int): How many digits (i.e. leading 0s) that the bates number will have
|
|
2985
|
+
page_number_area (str): Where on the page the bates number will go ("TOP_LEFT", "TOP_RIGHT", "BOTTOM_LEFT", "BOTTOM_RIGHT" (default))
|
|
2986
|
+
page_number_font_size (float): How big the bates page number will be in points (default is 10).
|
|
2987
|
+
page_number_offset_horizontal (float): The number of pixels that the bates page number is offset from the left / right of the page.
|
|
2988
|
+
page_number_offset_vertical (float): The number of pixels that the bates page number is offset from the top / bottom of the page.
|
|
2927
2989
|
toc_pages (int): Expected number of pages in the table of contents.
|
|
2928
2990
|
append_matching_suffix (bool): If True, appends matching suffix to the filename.
|
|
2929
2991
|
|
|
@@ -2935,12 +2997,19 @@ class ALExhibitList(DAList):
|
|
|
2935
2997
|
exhibit.cover_page
|
|
2936
2998
|
if self.include_table_of_contents and toc_pages != 1:
|
|
2937
2999
|
self._update_page_numbers(toc_guess_pages=toc_pages)
|
|
3000
|
+
if not page_number_prefix and self.bates_prefix:
|
|
3001
|
+
page_number_prefix = self.bates_prefix
|
|
2938
3002
|
return pdf_concatenate(
|
|
2939
3003
|
[
|
|
2940
3004
|
exhibit.as_pdf(
|
|
2941
3005
|
add_cover_page=self.include_exhibit_cover_pages,
|
|
2942
3006
|
add_page_numbers=add_page_numbers,
|
|
2943
|
-
|
|
3007
|
+
page_number_prefix=page_number_prefix,
|
|
3008
|
+
page_number_digits=page_number_digits,
|
|
3009
|
+
page_number_area=page_number_area,
|
|
3010
|
+
page_number_font_size=page_number_font_size,
|
|
3011
|
+
page_number_offset_horizontal=page_number_offset_horizontal,
|
|
3012
|
+
page_number_offset_vertical=page_number_offset_vertical,
|
|
2944
3013
|
)
|
|
2945
3014
|
for exhibit in self
|
|
2946
3015
|
],
|
|
@@ -3073,12 +3142,19 @@ class ALExhibitDocument(ALDocument):
|
|
|
3073
3142
|
has_addendum: bool
|
|
3074
3143
|
auto_labeler: Callable
|
|
3075
3144
|
auto_ocr: bool
|
|
3145
|
+
# Deprecated
|
|
3076
3146
|
bates_prefix: str
|
|
3077
3147
|
maximum_size: int
|
|
3078
3148
|
maximum_size_per_doc: int
|
|
3079
3149
|
suffix_to_append: str
|
|
3080
3150
|
exhibits: ALExhibitList
|
|
3081
3151
|
table_of_contents: DAFile
|
|
3152
|
+
page_number_prefix: str
|
|
3153
|
+
page_number_digits: int
|
|
3154
|
+
page_number_area: str | None
|
|
3155
|
+
page_number_font_size: float
|
|
3156
|
+
page_number_offset_horizontal: float
|
|
3157
|
+
page_number_offset_vertical: float
|
|
3082
3158
|
|
|
3083
3159
|
def init(self, *pargs, **kwargs) -> None:
|
|
3084
3160
|
"""Standard DAObject init method.
|
|
@@ -3093,8 +3169,6 @@ class ALExhibitDocument(ALDocument):
|
|
|
3093
3169
|
self.exhibits.auto_labeler = self.auto_labeler
|
|
3094
3170
|
if hasattr(self, "auto_ocr"):
|
|
3095
3171
|
self.exhibits.auto_ocr = self.auto_ocr
|
|
3096
|
-
if hasattr(self, "bates_prefix"):
|
|
3097
|
-
self.exhibits.bates_prefix = self.bates_prefix
|
|
3098
3172
|
if hasattr(self, "include_exhibit_cover_pages"):
|
|
3099
3173
|
self.exhibits.include_exhibit_cover_pages = self.include_exhibit_cover_pages
|
|
3100
3174
|
else:
|
|
@@ -3112,13 +3186,30 @@ class ALExhibitDocument(ALDocument):
|
|
|
3112
3186
|
else:
|
|
3113
3187
|
self.include_table_of_contents = True
|
|
3114
3188
|
self.exhibits.include_table_of_contents = True
|
|
3189
|
+
if hasattr(self, "bates_prefix"):
|
|
3190
|
+
self.exhibits.bates_prefix = self.bates_prefix
|
|
3115
3191
|
if not hasattr(self, "add_page_numbers"):
|
|
3116
3192
|
self.add_page_numbers = False
|
|
3193
|
+
self._set_default_attributes()
|
|
3117
3194
|
self.has_addendum = False
|
|
3118
3195
|
if not hasattr(self, "suffix_to_append"):
|
|
3119
3196
|
# When the key is "preview", append it to the file name
|
|
3120
3197
|
self.suffix_to_append = "preview"
|
|
3121
3198
|
|
|
3199
|
+
def _set_default_attributes(self) -> None:
|
|
3200
|
+
if not hasattr(self, "page_number_prefix"):
|
|
3201
|
+
self.page_number_prefix = ""
|
|
3202
|
+
if not hasattr(self, "page_number_digits"):
|
|
3203
|
+
self.page_number_digits = 5
|
|
3204
|
+
if not hasattr(self, "page_number_area"):
|
|
3205
|
+
self.page_number_area = None
|
|
3206
|
+
if not hasattr(self, "page_number_font_size"):
|
|
3207
|
+
self.page_number_font_size = 10
|
|
3208
|
+
if not hasattr(self, "page_number_offset_horizontal"):
|
|
3209
|
+
self.page_number_offset_horizontal = 15
|
|
3210
|
+
if not hasattr(self, "page_number_offset_vertical"):
|
|
3211
|
+
self.page_number_offset_vertical = 15
|
|
3212
|
+
|
|
3122
3213
|
def has_overflow(self) -> bool:
|
|
3123
3214
|
"""
|
|
3124
3215
|
Check if there is any overflow in the document.
|
|
@@ -3193,12 +3284,21 @@ class ALExhibitDocument(ALDocument):
|
|
|
3193
3284
|
filename = base_name(self.filename) + ".pdf"
|
|
3194
3285
|
|
|
3195
3286
|
if len(self.exhibits):
|
|
3287
|
+
self._set_default_attributes()
|
|
3196
3288
|
if self.include_table_of_contents:
|
|
3197
3289
|
toc_pages = self.table_of_contents.num_pages()
|
|
3198
3290
|
return pdf_concatenate(
|
|
3199
3291
|
self.table_of_contents,
|
|
3200
3292
|
self.exhibits.as_pdf(
|
|
3201
|
-
add_page_numbers=self.add_page_numbers,
|
|
3293
|
+
add_page_numbers=self.add_page_numbers,
|
|
3294
|
+
page_number_prefix=self.page_number_prefix,
|
|
3295
|
+
page_number_digits=self.page_number_digits,
|
|
3296
|
+
page_number_area=self.page_number_area,
|
|
3297
|
+
page_number_font_size=self.page_number_font_size,
|
|
3298
|
+
page_number_offset_horizontal=self.page_number_offset_horizontal,
|
|
3299
|
+
page_number_offset_vertical=self.page_number_offset_vertical,
|
|
3300
|
+
toc_pages=toc_pages,
|
|
3301
|
+
pdfa=pdfa,
|
|
3202
3302
|
),
|
|
3203
3303
|
filename=filename,
|
|
3204
3304
|
pdfa=pdfa,
|
|
@@ -3206,6 +3306,12 @@ class ALExhibitDocument(ALDocument):
|
|
|
3206
3306
|
else:
|
|
3207
3307
|
return self.exhibits.as_pdf(
|
|
3208
3308
|
add_page_numbers=self.add_page_numbers,
|
|
3309
|
+
page_number_prefix=self.page_number_prefix,
|
|
3310
|
+
page_number_digits=self.page_number_digits,
|
|
3311
|
+
page_number_area=self.page_number_area,
|
|
3312
|
+
page_number_font_size=self.page_number_font_size,
|
|
3313
|
+
page_number_offset_horizontal=self.page_number_offset_horizontal,
|
|
3314
|
+
page_number_offset_vertical=self.page_number_offset_vertical,
|
|
3209
3315
|
filename=filename,
|
|
3210
3316
|
pdfa=pdfa,
|
|
3211
3317
|
)
|
|
@@ -30,13 +30,11 @@ from docassemble.base.util import (
|
|
|
30
30
|
their,
|
|
31
31
|
url_action,
|
|
32
32
|
validation_error,
|
|
33
|
-
value,
|
|
34
33
|
word,
|
|
35
34
|
your,
|
|
36
35
|
log,
|
|
37
36
|
value,
|
|
38
37
|
)
|
|
39
|
-
from docassemble.ALToolbox.misc import fa_icon
|
|
40
38
|
import docassemble.base.functions
|
|
41
39
|
import random
|
|
42
40
|
import re
|
|
@@ -325,7 +323,7 @@ class ALAddress(Address):
|
|
|
325
323
|
if not bare and (
|
|
326
324
|
unit_lower.isnumeric()
|
|
327
325
|
or (
|
|
328
|
-
|
|
326
|
+
" " not in self.unit
|
|
329
327
|
and not any(
|
|
330
328
|
x in unit_lower
|
|
331
329
|
for x in [
|
|
@@ -1660,10 +1658,13 @@ class ALIndividual(Individual):
|
|
|
1660
1658
|
Used to assist with checkbox filling in PDFs with "skip undefined"
|
|
1661
1659
|
turned on.
|
|
1662
1660
|
"""
|
|
1663
|
-
return not
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1661
|
+
return self.gender not in [
|
|
1662
|
+
"prefer-not-to-say",
|
|
1663
|
+
"male",
|
|
1664
|
+
"female",
|
|
1665
|
+
"unknown",
|
|
1666
|
+
"nonbinary",
|
|
1667
|
+
]
|
|
1667
1668
|
|
|
1668
1669
|
def contact_fields(self) -> None:
|
|
1669
1670
|
"""
|
|
@@ -1913,7 +1914,7 @@ class ALIndividual(Individual):
|
|
|
1913
1914
|
if len(pronouns_to_use) > 0:
|
|
1914
1915
|
output = "/".join(pronouns_to_use)
|
|
1915
1916
|
else:
|
|
1916
|
-
output = default
|
|
1917
|
+
output = f"{default}'s {target}"
|
|
1917
1918
|
elif hasattr(self, "person_type") and self.person_type in [
|
|
1918
1919
|
"business",
|
|
1919
1920
|
"organization",
|
|
@@ -1927,7 +1928,7 @@ class ALIndividual(Individual):
|
|
|
1927
1928
|
else:
|
|
1928
1929
|
output = their(target, **kwargs)
|
|
1929
1930
|
else:
|
|
1930
|
-
output = default
|
|
1931
|
+
output = f"{default}'s {target}"
|
|
1931
1932
|
|
|
1932
1933
|
if "capitalize" in kwargs and kwargs["capitalize"]:
|
|
1933
1934
|
return capitalize(output)
|
|
@@ -5,9 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
# See: https://docassemble.org/docs/documents.html#register_jinja_filter
|
|
7
7
|
|
|
8
|
-
import re
|
|
9
8
|
from typing import Any, Dict, List, Optional, Union
|
|
10
|
-
from docassemble.base.util import register_jinja_filter, DACatchAll
|
|
9
|
+
from docassemble.base.util import register_jinja_filter, DACatchAll
|
|
11
10
|
from jinja2 import Undefined, pass_context
|
|
12
11
|
from jinja2.runtime import Context as Jinja2Context
|
|
13
12
|
|
|
@@ -18,6 +17,7 @@ __all__ = [
|
|
|
18
17
|
"catchall_question",
|
|
19
18
|
"catchall_subquestion",
|
|
20
19
|
"catchall_fields_code",
|
|
20
|
+
"catchall_complete",
|
|
21
21
|
]
|
|
22
22
|
|
|
23
23
|
|
|
@@ -29,6 +29,7 @@ def catchall_options(value: Any, *raw_items: Any) -> DACatchAll:
|
|
|
29
29
|
|
|
30
30
|
The items can be in various formats:
|
|
31
31
|
|
|
32
|
+
- String: `"code_is_the_label"`
|
|
32
33
|
- String: `"code: label"`
|
|
33
34
|
- Dictionary: `{"code": "label"}`
|
|
34
35
|
- Tuple: `("code", "label")`
|
|
@@ -66,14 +67,14 @@ def catchall_options(value: Any, *raw_items: Any) -> DACatchAll:
|
|
|
66
67
|
DACatchAll: The modified DACatchAll object with the assigned options.
|
|
67
68
|
"""
|
|
68
69
|
if isinstance(value, DACatchAll):
|
|
69
|
-
pairs = []
|
|
70
|
+
pairs: list[str | tuple[str, str]] = []
|
|
70
71
|
for item in raw_items:
|
|
71
72
|
if isinstance(item, str):
|
|
72
73
|
if ":" in item:
|
|
73
74
|
code, label = item.split(":", 1)
|
|
75
|
+
pairs.append((code.strip(), label.strip()))
|
|
74
76
|
else:
|
|
75
|
-
|
|
76
|
-
pairs.append((code.strip(), label.strip()))
|
|
77
|
+
pairs.append(item.strip())
|
|
77
78
|
elif isinstance(item, dict):
|
|
78
79
|
for code, label in item.items():
|
|
79
80
|
pairs.append((code.strip(), label.strip()))
|
|
@@ -203,6 +204,49 @@ def catchall_subquestion(value: Any, subquestion: str) -> DACatchAll:
|
|
|
203
204
|
return value
|
|
204
205
|
|
|
205
206
|
|
|
207
|
+
def catchall_complete(
|
|
208
|
+
value: DACatchAll,
|
|
209
|
+
question: str = "",
|
|
210
|
+
subquestion: str = "",
|
|
211
|
+
label: str = "",
|
|
212
|
+
datatype: str = "",
|
|
213
|
+
options: Any = "",
|
|
214
|
+
) -> DACatchAll:
|
|
215
|
+
"""
|
|
216
|
+
Jinja2 filter to allow you to define multiple attributes of a DACatchAll field inside a DOCX template.
|
|
217
|
+
|
|
218
|
+
Each argument after `value` corresponds to the similarly named `catchall_` function.
|
|
219
|
+
|
|
220
|
+
Example usage in a DOCX template:
|
|
221
|
+
```
|
|
222
|
+
{{ my_catchall_field | catchall_complete(question="What additional information do you need?", subquestion="Be specific", label="no label") }}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
value (DACatchAll): The DACatchAll object to which the attributes will be assigned.
|
|
227
|
+
question (str, optional): The question text to set on the DACatchAll object.
|
|
228
|
+
subquestion (str, optional): The subquestion text to set on the DACatchAll object.
|
|
229
|
+
label (str, optional): The label to set on the DACatchAll object.
|
|
230
|
+
datatype (str, optional): The datatype to set on the DACatchAll object.
|
|
231
|
+
options (Any, optional): The options to set on the DACatchAll object.
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
DACatchAll: The modified DACatchAll object with the assigned attributes.
|
|
235
|
+
"""
|
|
236
|
+
if isinstance(value, DACatchAll):
|
|
237
|
+
if question:
|
|
238
|
+
catchall_question(value, question)
|
|
239
|
+
if subquestion:
|
|
240
|
+
catchall_subquestion(value, subquestion)
|
|
241
|
+
if label:
|
|
242
|
+
catchall_label(value, label)
|
|
243
|
+
if datatype:
|
|
244
|
+
catchall_datatype(value, datatype)
|
|
245
|
+
if options:
|
|
246
|
+
catchall_options(value, options)
|
|
247
|
+
return value
|
|
248
|
+
|
|
249
|
+
|
|
206
250
|
def _undefined_label(ud: Undefined) -> Union[str, None]:
|
|
207
251
|
"""
|
|
208
252
|
Extract the variable name from a Jinja2 Undefined object for use as a placeholder label.
|
|
@@ -314,6 +358,7 @@ register_jinja_filter("catchall_label", catchall_label)
|
|
|
314
358
|
register_jinja_filter("catchall_datatype", catchall_datatype)
|
|
315
359
|
register_jinja_filter("catchall_question", catchall_question)
|
|
316
360
|
register_jinja_filter("catchall_subquestion", catchall_subquestion)
|
|
361
|
+
register_jinja_filter("catchall_complete", catchall_complete)
|
|
317
362
|
register_jinja_filter("if_final", if_final)
|
|
318
363
|
|
|
319
364
|
|
|
@@ -22,14 +22,14 @@ code: |
|
|
|
22
22
|
form_delivery_complete = True
|
|
23
23
|
---
|
|
24
24
|
code: |
|
|
25
|
-
court_email = court_emails.get(trial_court.name,None)
|
|
25
|
+
court_email = court_emails.get(trial_court.name, None)
|
|
26
26
|
if not court_email:
|
|
27
27
|
found_email = False
|
|
28
28
|
else:
|
|
29
29
|
found_email = True
|
|
30
30
|
---
|
|
31
31
|
code: |
|
|
32
|
-
bcc_failsafe = court_emails.get(
|
|
32
|
+
bcc_failsafe = court_emails.get("Failsafe Address", None)
|
|
33
33
|
---
|
|
34
34
|
comment: |
|
|
35
35
|
You are encouraged to overwrite these emails during testing!
|
|
@@ -51,22 +51,50 @@ code: |
|
|
|
51
51
|
else:
|
|
52
52
|
email_to_use = dev_email_to_use
|
|
53
53
|
bcc_email = dev_bcc_email
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
# temporary for testing
|
|
56
56
|
# email_to_use = "massaccess@suffolk.edu"
|
|
57
57
|
|
|
58
|
-
if task_not_yet_performed(
|
|
58
|
+
if task_not_yet_performed("send email"):
|
|
59
59
|
log(f"Court email is {court_email}, sending email to {email_to_use}")
|
|
60
60
|
email_success = False
|
|
61
61
|
if should_cc_user:
|
|
62
|
-
log(
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
log(
|
|
63
|
+
"Sending email to "
|
|
64
|
+
+ email_to_use
|
|
65
|
+
+ " and ccing "
|
|
66
|
+
+ cc_email
|
|
67
|
+
+ " for "
|
|
68
|
+
+ str(users)
|
|
69
|
+
+ " bcc to "
|
|
70
|
+
+ bcc_email
|
|
71
|
+
)
|
|
72
|
+
email_success = send_email(
|
|
73
|
+
to=email_to_use,
|
|
74
|
+
template=email_to_court_template,
|
|
75
|
+
task="send email",
|
|
76
|
+
cc=cc_email,
|
|
77
|
+
bcc=bcc_email,
|
|
78
|
+
attachments=al_final_form_to_file.as_pdf_list(key="final"),
|
|
79
|
+
)
|
|
65
80
|
else:
|
|
66
|
-
log(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
81
|
+
log(
|
|
82
|
+
"Sending email to "
|
|
83
|
+
+ email_to_use
|
|
84
|
+
+ " and no cc "
|
|
85
|
+
+ " for "
|
|
86
|
+
+ str(users)
|
|
87
|
+
+ " bcc to "
|
|
88
|
+
+ bcc_email
|
|
89
|
+
)
|
|
90
|
+
email_success = send_email(
|
|
91
|
+
to=email_to_use,
|
|
92
|
+
template=email_to_court_template,
|
|
93
|
+
task="send email",
|
|
94
|
+
attachments=al_final_form_to_file.as_pdf_list(key="final"),
|
|
95
|
+
bcc=bcc_email,
|
|
96
|
+
)
|
|
97
|
+
mark_task_as_performed("send email")
|
|
70
98
|
sent_email_to_court = True
|
|
71
99
|
---
|
|
72
100
|
##############################################################
|
|
@@ -90,7 +118,7 @@ code: |
|
|
|
90
118
|
# Gets the number of pages, plus the first cover page
|
|
91
119
|
# TODO(brycew): figure out a better way to estimate the number of pages,
|
|
92
120
|
# including addendum, without generating a full file
|
|
93
|
-
al_num_package_pages = al_court_bundle.as_pdf(key=
|
|
121
|
+
al_num_package_pages = al_court_bundle.as_pdf(key="preview").num_pages() + 1
|
|
94
122
|
---
|
|
95
123
|
code: |
|
|
96
124
|
# You can define this in the interview's code block.
|
|
@@ -101,7 +129,7 @@ code: |
|
|
|
101
129
|
# This is a fallback package title to avoid errors on new forms
|
|
102
130
|
# It defines package_title as the metadata title.
|
|
103
131
|
# You may want a better form title for most interviews
|
|
104
|
-
package_title = all_variables(special=
|
|
132
|
+
package_title = all_variables(special="metadata").get("title", "").rstrip()
|
|
105
133
|
---
|
|
106
134
|
attachment:
|
|
107
135
|
variable name: al_cover_page[i]
|
|
@@ -126,27 +154,36 @@ code: |
|
|
|
126
154
|
elif signature_choice == "typed_signature":
|
|
127
155
|
for signature in signature_fields:
|
|
128
156
|
# Signature fields are strings like "users[0].signature". If the string ends in .signature, remove that and replace with .typed_signature, only at the end of the string
|
|
129
|
-
if signature.endswith(
|
|
130
|
-
typed_signature = signature[:-9] +
|
|
157
|
+
if signature.endswith("signature"):
|
|
158
|
+
typed_signature = signature[:-9] + "typed_signature"
|
|
131
159
|
define(signature, DAFile(signature, filename="signature.png"))
|
|
132
160
|
value(signature).initialize()
|
|
133
|
-
create_signature(
|
|
161
|
+
create_signature(
|
|
162
|
+
value(typed_signature),
|
|
163
|
+
value(signature).path(),
|
|
164
|
+
signature_prefix=al_typed_signature_prefix,
|
|
165
|
+
font_name=al_typed_signature_font,
|
|
166
|
+
)
|
|
134
167
|
else:
|
|
135
|
-
log(
|
|
136
|
-
|
|
168
|
+
log(
|
|
169
|
+
"Signature field "
|
|
170
|
+
+ signature
|
|
171
|
+
+ " does not end with .signature, not creating typed signature"
|
|
172
|
+
)
|
|
173
|
+
elif signature_choice in ["this device", "this_device"]:
|
|
137
174
|
for signature in signature_fields:
|
|
138
|
-
value(signature)
|
|
175
|
+
value(signature)
|
|
139
176
|
# Check for Branch 2 or 3
|
|
140
|
-
elif signature_choice ==
|
|
177
|
+
elif signature_choice == "phone":
|
|
141
178
|
saw_signature_qrcode
|
|
142
179
|
# User will click next. link_cell will only be defined if they chose the texting option
|
|
143
|
-
if showifdef("link_cell") and task_not_yet_performed(
|
|
180
|
+
if showifdef("link_cell") and task_not_yet_performed("send signature link"):
|
|
144
181
|
# They used the text option
|
|
145
|
-
send_sms(task=
|
|
182
|
+
send_sms(task="send signature link", to=link_cell, template=interview_link)
|
|
146
183
|
signature_wait_screen
|
|
147
184
|
for signature in signature_fields:
|
|
148
185
|
value(signature)
|
|
149
|
-
else:
|
|
186
|
+
else: # Branch 3: They used the QR Code. No special screen, just continue
|
|
150
187
|
for signature in signature_fields:
|
|
151
188
|
value(signature)
|
|
152
189
|
# Show the follow-up if they sent the link to their phone by QR or by SMS
|
|
@@ -157,14 +194,14 @@ code: |
|
|
|
157
194
|
code: |
|
|
158
195
|
# Sometimes we have values that can be set from interview_metadata.
|
|
159
196
|
# They don't always work, but interview author can override.
|
|
160
|
-
|
|
197
|
+
|
|
161
198
|
# Some interviews have multiple interview_metadata keys. Look in the 1st one
|
|
162
|
-
first_form_key = next(iter(interview_metadata),
|
|
163
|
-
if isinstance(interview_metadata.get(first_form_key,{}), dict):
|
|
164
|
-
first_form = interview_metadata.get(first_form_key,{})
|
|
199
|
+
first_form_key = next(iter(interview_metadata), "")
|
|
200
|
+
if isinstance(interview_metadata.get(first_form_key, {}), dict):
|
|
201
|
+
first_form = interview_metadata.get(first_form_key, {})
|
|
165
202
|
else:
|
|
166
203
|
first_form = {}
|
|
167
|
-
del
|
|
204
|
+
del first_form_key
|
|
168
205
|
---
|
|
169
206
|
depends on:
|
|
170
207
|
- user_ask_role
|
|
@@ -175,12 +212,12 @@ code: |
|
|
|
175
212
|
# define user_role to be either "defendant" or "plaintiff",
|
|
176
213
|
# either by checking interview_metadata or asking the user.
|
|
177
214
|
# The only valid values for user_role are "plaintiff" and "defendant".
|
|
178
|
-
|
|
215
|
+
|
|
179
216
|
# We will check for the "typical_role" key.
|
|
180
217
|
# Some older wizarded code doesn't define `typical_role`, so fall back
|
|
181
218
|
# to "unknown" if the key is not present.
|
|
182
219
|
# first_form is the first entry in interview_metadata
|
|
183
|
-
if not first_form.get("typical_role",
|
|
220
|
+
if not first_form.get("typical_role", "unknown") == "unknown":
|
|
184
221
|
user_role = first_form.get("typical_role")
|
|
185
222
|
else:
|
|
186
223
|
# If the user role was set to "unknown" at the time wizard run
|