docassemble.AssemblyLine 2.26.0__tar.gz → 2.27.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.
Files changed (87) hide show
  1. {docassemble.AssemblyLine-2.26.0/docassemble.AssemblyLine.egg-info → docassemble.AssemblyLine-2.27.0}/PKG-INFO +2 -2
  2. docassemble.AssemblyLine-2.27.0/docassemble/AssemblyLine/__init__.py +1 -0
  3. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/al_courts.py +9 -3
  4. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/al_document.py +16 -2
  5. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/al_general.py +23 -23
  6. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/al_visual.yml +22 -6
  7. docassemble.AssemblyLine-2.27.0/docassemble/AssemblyLine/data/questions/interview_list.yml +428 -0
  8. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/ql_baseline.yml +9 -18
  9. docassemble.AssemblyLine-2.27.0/docassemble/AssemblyLine/data/questions/test_aladdendum.yml +70 -0
  10. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/static/al_audio.js +11 -4
  11. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/sessions.py +40 -0
  12. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/test_al_general.py +26 -0
  13. docassemble.AssemblyLine-2.27.0/docassemble/__init__.py +2 -0
  14. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0/docassemble.AssemblyLine.egg-info}/PKG-INFO +2 -2
  15. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble.AssemblyLine.egg-info/SOURCES.txt +1 -0
  16. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble.AssemblyLine.egg-info/requires.txt +1 -1
  17. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/setup.py +2 -2
  18. docassemble.AssemblyLine-2.26.0/docassemble/AssemblyLine/__init__.py +0 -1
  19. docassemble.AssemblyLine-2.26.0/docassemble/AssemblyLine/data/questions/interview_list.yml +0 -242
  20. docassemble.AssemblyLine-2.26.0/docassemble/__init__.py +0 -5
  21. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/LICENSE +0 -0
  22. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/MANIFEST.in +0 -0
  23. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/README.md +0 -0
  24. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/al_code.yml +0 -0
  25. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/al_document.yml +0 -0
  26. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/al_language.yml +0 -0
  27. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/al_package.yml +0 -0
  28. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/al_package_unstyled.yml +0 -0
  29. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/al_question_test.yml +0 -0
  30. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/al_reminders.yml +0 -0
  31. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/al_saved_sessions.yml +0 -0
  32. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/al_saved_sessions_store.yml +0 -0
  33. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/al_settings.yml +0 -0
  34. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/al_terms_of_use.yml +0 -0
  35. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/assembly_line.yml +0 -0
  36. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/assembly_line_unstyled.yml +0 -0
  37. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/feedback.yml +0 -0
  38. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/ql_catchall.yml +0 -0
  39. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/reserved_words.yml +0 -0
  40. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/test_al_table_document.yml +0 -0
  41. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/test_alcourts.yml +0 -0
  42. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/test_aldocument.yml +0 -0
  43. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/test_alexhibit.yml +0 -0
  44. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/test_alexhibit_maxsize.yml +0 -0
  45. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/questions/test_question_library.yml +0 -0
  46. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/sources/README.md +0 -0
  47. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/sources/es-words.yml +0 -0
  48. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/sources/languages.yml +0 -0
  49. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/sources/test_aldocument.feature +0 -0
  50. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/sources/test_alexhibit_docx_1.docx +0 -0
  51. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/sources/test_alexhibit_jpg_1.jpg +0 -0
  52. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/sources/test_alexhibit_pdf_1.pdf +0 -0
  53. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/sources/test_alexhibit_png_1.png +0 -0
  54. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/sources/test_question_library.feature +0 -0
  55. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/sources/translation_es.xlsx +0 -0
  56. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/sources/translation_ht.xlsx +0 -0
  57. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/sources/translation_pt.xlsx +0 -0
  58. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/static/README.md +0 -0
  59. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/static/al_audio.css +0 -0
  60. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/static/aldocument.css +0 -0
  61. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/static/aldocument.js +0 -0
  62. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/static/interview_list.css +0 -0
  63. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/static/limit_upload_size.js +0 -0
  64. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/static/lt1-pullout-10-getting-organized.pdf +0 -0
  65. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/static/ma_logo.png +0 -0
  66. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/static/placeholder.png +0 -0
  67. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/static/seal.jpg +0 -0
  68. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/static/styles.css +0 -0
  69. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/templates/README.md +0 -0
  70. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/templates/al_basic_addendum.docx +0 -0
  71. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/templates/exhibit_cover_sheet.docx +0 -0
  72. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/templates/exhibit_table_of_contents.docx +0 -0
  73. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/templates/general_cover_sheet.docx +0 -0
  74. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/templates/sample_word_template.docx +0 -0
  75. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/templates/test_aldocument_docx_1.docx +0 -0
  76. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/data/templates/test_aldocument_pdf_1.pdf +0 -0
  77. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/language.py +0 -0
  78. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/py.typed +0 -0
  79. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/requirements.txt +0 -0
  80. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/test_al_document.py +0 -0
  81. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble/AssemblyLine/test_language.py +0 -0
  82. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble.AssemblyLine.egg-info/dependency_links.txt +0 -0
  83. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble.AssemblyLine.egg-info/namespace_packages.txt +0 -0
  84. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble.AssemblyLine.egg-info/not-zip-safe +0 -0
  85. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/docassemble.AssemblyLine.egg-info/top_level.txt +0 -0
  86. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/pyproject.toml +0 -0
  87. {docassemble.AssemblyLine-2.26.0 → docassemble.AssemblyLine-2.27.0}/setup.cfg +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: docassemble.AssemblyLine
3
- Version: 2.26.0
3
+ Version: 2.27.0
4
4
  Home-page: https://courtformsonline.org
5
5
  Author: Suffolk Legal Innovation and Technology Lab
6
6
  Author-email: qsteenhuis@suffolk.edu
7
7
  License: The MIT License (MIT)
8
8
  Description-Content-Type: text/markdown
9
9
  License-File: LICENSE
10
- Requires-Dist: docassemble.ALToolbox>=0.8.1
10
+ Requires-Dist: docassemble.ALToolbox>=0.8.3
11
11
  Requires-Dist: docassemble.GithubFeedbackForm>=0.2.1
12
12
 
13
13
  # Suffolk LIT Lab Document Assembly Line
@@ -0,0 +1 @@
1
+ __version__ = '2.27.0'
@@ -4,6 +4,7 @@ Package for a very simple / MVP list of courts that is mostly signature compatib
4
4
  import os
5
5
  from typing import Any, Dict, List, Optional, Union, Set
6
6
  import pandas as pd
7
+ import docassemble.base.functions
7
8
  from docassemble.base.util import (
8
9
  path_and_mimetype,
9
10
  Address,
@@ -205,6 +206,7 @@ class ALCourtLoader(DAObject):
205
206
 
206
207
  def init(self, *pargs, **kwargs):
207
208
  super().init(*pargs, **kwargs)
209
+ self.package = docassemble.base.functions.this_thread.current_question.package
208
210
  if not hasattr(self, "filename"):
209
211
  self.filename = (
210
212
  self.file_name
@@ -416,11 +418,15 @@ class ALCourtLoader(DAObject):
416
418
  """
417
419
  if not hasattr(self, "filename") and hasattr(self, "file_name"):
418
420
  self.filename = self.file_name
419
- if "/" in self.filename:
420
- to_load = path_and_mimetype(self.filename)[0]
421
+ if ":" not in self.filename and hasattr(self, "package"):
422
+ load_path = self.package + ":"
423
+ if "/" not in str(self.filename):
424
+ load_path += "data/sources/"
425
+ load_path += str(self.filename)
421
426
  else:
422
- to_load = path_and_mimetype(os.path.join("data/sources", self.filename))[0]
427
+ load_path = str(self.filename)
423
428
 
429
+ to_load = path_and_mimetype(load_path)[0]
424
430
  if self.filename.lower().endswith(".xlsx"):
425
431
  df = pd.read_excel(to_load)
426
432
  elif self.filename.lower().endswith(".csv"):
@@ -3,6 +3,8 @@ import os
3
3
  import mimetypes
4
4
  from typing import Any, Dict, List, Union, Callable, Optional
5
5
  from docassemble.base.util import (
6
+ Address,
7
+ LatitudeLongitude,
6
8
  log,
7
9
  DADict,
8
10
  DAList,
@@ -116,14 +118,22 @@ def safeattr(object: Any, key: str) -> str:
116
118
 
117
119
  Returns:
118
120
  str: The retrieved value or an empty string if not found or if an error occurred.
121
+
122
+ Note:
123
+ The `location` attribute of an Address object or any LatitudeLongitude attribute of a DAObject is always skipped.
119
124
  """
120
125
  try:
121
126
  if isinstance(object, dict) or isinstance(object, DADict):
122
127
  return str(object.get(key, ""))
123
128
  elif isinstance(object, DAObject):
124
129
  # `location` is not an attribute people usually want shown in the table of people's attributes
125
- if key == "location":
130
+ if key == "location" and isinstance(object, Address):
126
131
  return ""
132
+ elif key == "location" and isinstance(object, DAObject):
133
+ if hasattr(object, "location") and isinstance(
134
+ object.location, LatitudeLongitude
135
+ ):
136
+ return ""
127
137
  return str(getattr(object, key))
128
138
  else:
129
139
  return ""
@@ -512,6 +522,9 @@ class ALAddendumField(DAObject):
512
522
 
513
523
  Returns:
514
524
  Optional[list]: A list of columns or None if no meaningful columns can be determined.
525
+
526
+ Note:
527
+ The "location" attribute of an Address object is always skipped in the column list.
515
528
  """
516
529
  if not skip_attributes:
517
530
  skip_attributes = {"complete"}
@@ -2078,7 +2091,8 @@ class ALDocumentBundle(DAList):
2078
2091
  show_editable_checkbox (bool, optional): Flag indicating if the checkbox
2079
2092
  for deciding the inclusion of an editable (Word) copy should be displayed.
2080
2093
  Defaults to True.
2081
- template_name (str, optional): The name of the template to be used. Defaults to an empty string.
2094
+ template_name (str, optional): Name of the template variable that is used to fill
2095
+ the email contents. By default, the `x.send_email_template` template will be used.
2082
2096
 
2083
2097
  Returns:
2084
2098
  str: The generated HTML string for the input box and button.
@@ -24,6 +24,7 @@ from docassemble.base.util import (
24
24
  name_suffix,
25
25
  phone_number_formatted,
26
26
  phone_number_is_valid,
27
+ showifdef,
27
28
  state_name,
28
29
  states_list,
29
30
  subdivision_type,
@@ -150,6 +151,10 @@ class ALAddress(Address):
150
151
  # differs from the server's country.
151
152
  if country_code and country_code != get_country() and not show_country:
152
153
  self.country = country_code
154
+ # Priority order for country: already answered country, passed in country_code, then get_country
155
+ prev_selected_country = showifdef(self.attr_name("country"), None, prior=True)
156
+ if prev_selected_country:
157
+ country_code = prev_selected_country
153
158
  if not country_code:
154
159
  country_code = get_country()
155
160
  if allow_no_address:
@@ -193,7 +198,7 @@ class ALAddress(Address):
193
198
 
194
199
  fields.append({"label": str(self.city_label), "field": self.attr_name("city")})
195
200
 
196
- if country_code:
201
+ if country_code and not show_country:
197
202
  fields.append(
198
203
  {
199
204
  "label": str(self.state_label),
@@ -202,15 +207,15 @@ class ALAddress(Address):
202
207
  "default": default_state if default_state else "",
203
208
  }
204
209
  )
205
- else: # not showing country and not showing country code
210
+ else: # when you are allowed to change country
206
211
  fields.append(
207
212
  {
208
- "label": str(self.state_label),
213
+ "label": str(self.state_or_province_label),
209
214
  "field": self.attr_name("state"),
210
215
  "default": default_state if default_state else "",
211
216
  }
212
217
  )
213
- if country_code == "US":
218
+ if country_code == "US" and not show_country:
214
219
  fields.append(
215
220
  {
216
221
  "label": str(self.zip_label),
@@ -521,7 +526,7 @@ class ALAddress(Address):
521
526
 
522
527
  Args:
523
528
  include_unit (bool): If True, includes the unit in the formatted address. Defaults to True.
524
- omit_default_country (bool): If True, omits the default country from the formatted address. Defaults to True.
529
+ omit_default_country (bool): If True, doesn't show the Docassemble default country in the formatted address. Defaults to True.
525
530
  language (str, optional): Language for the address format.
526
531
  show_country (bool, optional): If True, includes the country in the formatted address.
527
532
  If None, decides based on the country attribute.
@@ -843,26 +848,24 @@ class ALIndividual(Individual):
843
848
  """
844
849
  nums = []
845
850
  if hasattr(self, "mobile_number") and self.mobile_number:
851
+ fmt_number = None
846
852
  try:
847
- nums.append(
848
- {
849
- phone_number_formatted(
850
- self.mobile_number, country=country
851
- ): "cell"
852
- }
853
- )
853
+ fmt_number = phone_number_formatted(self.mobile_number, country=country)
854
854
  except:
855
+ fmt_number = None
856
+ if fmt_number:
857
+ nums.append({fmt_number: "cell"})
858
+ else:
855
859
  nums.append({self.mobile_number: "cell"})
856
860
  if hasattr(self, "phone_number") and self.phone_number:
861
+ fmt_number = None
857
862
  try:
858
- nums.append(
859
- {
860
- phone_number_formatted(
861
- self.phone_number, country=country
862
- ): "other"
863
- }
864
- )
863
+ fmt_number = phone_number_formatted(self.phone_number, country=country)
865
864
  except:
865
+ fmt_number = None
866
+ if fmt_number:
867
+ nums.append({fmt_number: "other"})
868
+ else:
866
869
  nums.append({self.phone_number: "other"})
867
870
  if len(nums) < 1:
868
871
  return ""
@@ -873,10 +876,7 @@ class ALIndividual(Individual):
873
876
  return str(self.impounded_phone_output_label)
874
877
  elif len(nums) > 1:
875
878
  return comma_list(
876
- [
877
- list(num.keys())[0] + " (" + list(num.values())[0] + ")"
878
- for num in nums
879
- ]
879
+ [f"{list(num.keys())[0]} ({list(num.values())[0]})" for num in nums]
880
880
  )
881
881
  elif len(nums):
882
882
  return list(nums[0].keys())[0]
@@ -366,10 +366,18 @@ content: |
366
366
  MAIN_METADATA = next(iter(interview_metadata.values()))
367
367
  %>
368
368
  % else:
369
- <% MAIN_METADATA = {} %>
369
+ <% MAIN_METADATA = all_variables(special='metadata') %>
370
370
  % endif
371
- % if MAIN_METADATA.get("original_form") and not MAIN_METADATA.get("original_form", "").strip() == "None" and MAIN_METADATA.get("original_form").startswith("http"):
372
- [View the original version of this form](${ MAIN_METADATA.get("original_form") }).
371
+ <% ORIGINAL_FORMS = MAIN_METADATA.get("original_form", []) if isinstance(MAIN_METADATA.get("original_form"), list) else ([MAIN_METADATA.get("original_form", "")] if MAIN_METADATA.get("original_form") else []) %>
372
+
373
+ % if len(ORIGINAL_FORMS) > 1:
374
+ View the original version of this form at the links below:
375
+
376
+ % for url in [url for url in ORIGINAL_FORMS if url.strip() != "None" and url.startswith("http")]:
377
+ * [${ url }](${ url })
378
+ % endfor
379
+ % elif len(ORIGINAL_FORMS) == 1:
380
+ [View the original version of this form](${ ORIGINAL_FORMS[0] }).
373
381
  % endif
374
382
 
375
383
  % if package_updated_on:
@@ -426,8 +434,10 @@ continue button field: al_exit_logout_confirmation
426
434
  metadata:
427
435
  error action: al_custom_error_action
428
436
  ---
437
+ # Only necessary to ignore playground "undefined names" warning
429
438
  objects:
430
439
  - MAIN_METADATA: DAEmpty()
440
+ - ORIGINAL_FORMS: DAEmpty()
431
441
  ---
432
442
  id: custom error action
433
443
  event: al_custom_error_action
@@ -445,8 +455,9 @@ subquestion: |
445
455
  MAIN_METADATA = next(iter(interview_metadata.values()))
446
456
  %>
447
457
  % else:
448
- <% MAIN_METADATA = {} %>
458
+ <% MAIN_METADATA = all_variables(special='metadata') %>
449
459
  % endif
460
+ <% ORIGINAL_FORMS = MAIN_METADATA.get("original_form", []) if isinstance(MAIN_METADATA.get("original_form"), list) else ([MAIN_METADATA.get("original_form", "")] if MAIN_METADATA.get("original_form") else []) %>
450
461
 
451
462
  We ran into an error when we tried to load this screen.
452
463
 
@@ -459,8 +470,13 @@ subquestion: |
459
470
  % if al_enable_incomplete_downloads:
460
471
  * Try to [download your work in progress](${ url_action("al_error_action_download_screen") })
461
472
  % endif
462
- % if MAIN_METADATA.get("original_form") and not MAIN_METADATA.get("original_form", "").strip() == "None":
463
- * [Download a blank "${ all_variables(special='metadata').get("title", "").strip() }"](${ MAIN_METADATA.get("original_form") } )
473
+ % if len(ORIGINAL_FORMS) > 1:
474
+ * Download a blank "${ all_variables(special='metadata').get("title", "").strip() }":
475
+ % for url in ORIGINAL_FORMS:
476
+ * [${ url }](${ url } )
477
+ % endfor
478
+ % elif len(ORIGINAL_FORMS) == 1:
479
+ * [Download a blank "${ all_variables(special='metadata').get("title", "").strip() }"]( ${ ORIGINAL_FORMS[0] })
464
480
  % endif
465
481
  * Visit the [${ AL_ORGANIZATION_TITLE } home page](${ AL_ORGANIZATION_HOMEPAGE }) and try another interview
466
482
  % if al_show_email_to_user_on_errors and get_config("error notification email"):