Upload app.py
Browse files* Public login
* scroll to outputs
* link to PDF guide
* cleaner section titles
app.py
CHANGED
@@ -90,8 +90,6 @@ def generate_pdf(*sections: str) -> str:
|
|
90 |
pdf.ln(line_height)
|
91 |
|
92 |
for section in sections:
|
93 |
-
# debug
|
94 |
-
print("Adding section:", section)
|
95 |
pdf.multi_cell(w=0, h=line_height, text=section)
|
96 |
pdf.ln(line_height) # Single spacing
|
97 |
|
@@ -137,16 +135,29 @@ def generate_docx(*sections: str) -> str:
|
|
137 |
|
138 |
def build_drafter() -> Tuple[LoggedComponents, gr.Blocks]:
|
139 |
with gr.Blocks(theme=gr.themes.Soft(), title="LOI writer") as demo:
|
140 |
-
gr.Markdown(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
|
142 |
with gr.Row():
|
143 |
with gr.Column():
|
144 |
gr.Markdown(
|
145 |
-
"""<h2>
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
)
|
151 |
org_name_text = gr.Textbox(label="*Name of your organization", lines=1)
|
152 |
org_ein_text = gr.Textbox(label="EIN of your organization", lines=1)
|
@@ -158,15 +169,15 @@ def build_drafter() -> Tuple[LoggedComponents, gr.Blocks]:
|
|
158 |
with gr.Row():
|
159 |
with gr.Column(scale=7):
|
160 |
gr.Markdown(
|
161 |
-
"""<h2>
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
)
|
171 |
with gr.Column(scale=1):
|
172 |
autofill_btn = gr.Button("AutoFill (Optional)")
|
@@ -179,7 +190,11 @@ def build_drafter() -> Tuple[LoggedComponents, gr.Blocks]:
|
|
179 |
funder_candid_id = gr.Text(visible=False, interactive=False)
|
180 |
|
181 |
gr.HTML("<div style='margin-bottom: 20px;'></div>")
|
182 |
-
gr.Markdown(
|
|
|
|
|
|
|
|
|
183 |
|
184 |
projects_text = gr.Textbox(
|
185 |
label="*Main projects",
|
@@ -246,7 +261,9 @@ def build_drafter() -> Tuple[LoggedComponents, gr.Blocks]:
|
|
246 |
|
247 |
with gr.Accordion():
|
248 |
gr.Markdown("""
|
249 |
-
<h2>Step 4:
|
|
|
|
|
250 |
""")
|
251 |
gr.Markdown("<h3>Organization Description</h3>")
|
252 |
capacity_text = gr.Textbox(
|
@@ -340,17 +357,16 @@ def build_drafter() -> Tuple[LoggedComponents, gr.Blocks]:
|
|
340 |
)
|
341 |
|
342 |
gr.Markdown(
|
343 |
-
|
344 |
-
|
|
|
345 |
write_btn = gr.Button("Write LOI")
|
346 |
|
347 |
with gr.Column():
|
348 |
gr.Markdown(
|
349 |
-
"""<h2>
|
350 |
-
|
351 |
-
|
352 |
-
</h2>"""
|
353 |
-
)
|
354 |
opening = gr.Textbox(label="Opening", interactive=True, lines=3)
|
355 |
create_editable_section("Opening", JS, update_highlighted_text, opening)
|
356 |
|
@@ -371,11 +387,9 @@ def build_drafter() -> Tuple[LoggedComponents, gr.Blocks]:
|
|
371 |
create_editable_section("Conclusion", JS, update_highlighted_text, conclusion)
|
372 |
|
373 |
gr.Markdown(
|
374 |
-
"""<h2>
|
375 |
-
|
376 |
-
|
377 |
-
</h2>"""
|
378 |
-
)
|
379 |
|
380 |
with gr.Row():
|
381 |
download_pdf_button = gr.Button("Download as PDF")
|
@@ -385,14 +399,16 @@ def build_drafter() -> Tuple[LoggedComponents, gr.Blocks]:
|
|
385 |
download_pdf_button.click(
|
386 |
generate_pdf,
|
387 |
inputs=[opening, org_desc, need, project_desc, fund_request, conclusion],
|
388 |
-
outputs=gr.File(label="Download as PDF")
|
|
|
389 |
)
|
390 |
|
391 |
# pylint: disable=no-member
|
392 |
download_word_button.click(
|
393 |
generate_docx,
|
394 |
inputs=[opening, org_desc, need, project_desc, fund_request, conclusion],
|
395 |
-
outputs=gr.File(label="Download as docx")
|
|
|
396 |
)
|
397 |
|
398 |
# pylint: disable=no-member
|
@@ -412,6 +428,7 @@ def build_drafter() -> Tuple[LoggedComponents, gr.Blocks]:
|
|
412 |
funder_json,
|
413 |
funder_candid_id
|
414 |
],
|
|
|
415 |
api_name=False,
|
416 |
queue=True,
|
417 |
)
|
@@ -460,6 +477,7 @@ def build_drafter() -> Tuple[LoggedComponents, gr.Blocks]:
|
|
460 |
follow_up_text
|
461 |
],
|
462 |
outputs=[opening, org_desc, need, project_desc, fund_request, conclusion],
|
|
|
463 |
api_name=False,
|
464 |
queue=True,
|
465 |
)
|
@@ -610,6 +628,7 @@ if __name__ == '__main__':
|
|
610 |
show_api=False,
|
611 |
auth=[
|
612 |
(os.getenv("APP_USERNAME"), os.getenv("APP_PASSWORD")),
|
|
|
613 |
],
|
614 |
auth_message="Login to Candid's letter of intent demo"
|
615 |
)
|
|
|
90 |
pdf.ln(line_height)
|
91 |
|
92 |
for section in sections:
|
|
|
|
|
93 |
pdf.multi_cell(w=0, h=line_height, text=section)
|
94 |
pdf.ln(line_height) # Single spacing
|
95 |
|
|
|
135 |
|
136 |
def build_drafter() -> Tuple[LoggedComponents, gr.Blocks]:
|
137 |
with gr.Blocks(theme=gr.themes.Soft(), title="LOI writer") as demo:
|
138 |
+
gr.Markdown(
|
139 |
+
"""
|
140 |
+
<h1>Demo: LOI writer</h1>
|
141 |
+
|
142 |
+
<p>
|
143 |
+
Please read the <a
|
144 |
+
href='https://candid.org/content/download/1638602/33925838/file/Guide%20LOI%20Writer.pdf'
|
145 |
+
target="_blank"
|
146 |
+
rel="noopener noreferrer"
|
147 |
+
>guide</a> to get started.
|
148 |
+
</p>
|
149 |
+
<hr>
|
150 |
+
"""
|
151 |
+
)
|
152 |
|
153 |
with gr.Row():
|
154 |
with gr.Column():
|
155 |
gr.Markdown(
|
156 |
+
"""<h2>Step 1: Organization lookups</h2>
|
157 |
+
Enter the name/EIN of your nonprofit and the name/EIN of the intended funder.
|
158 |
+
Use <a href='https://beta.candid.org/' target="_blank" rel="noopener noreferrer">Candid</a>
|
159 |
+
to find this information, if not known.
|
160 |
+
"""
|
161 |
)
|
162 |
org_name_text = gr.Textbox(label="*Name of your organization", lines=1)
|
163 |
org_ein_text = gr.Textbox(label="EIN of your organization", lines=1)
|
|
|
169 |
with gr.Row():
|
170 |
with gr.Column(scale=7):
|
171 |
gr.Markdown(
|
172 |
+
"""<h2>Step 2: Data autofill</h2>
|
173 |
+
Autofill with data you have
|
174 |
+
<a
|
175 |
+
href='https://candid.org/share-your-impact'
|
176 |
+
target="_blank"
|
177 |
+
rel="noopener noreferrer"
|
178 |
+
> shared with Candid</a>.
|
179 |
+
Contents can be reviewed and edited before used for LOI generation
|
180 |
+
"""
|
181 |
)
|
182 |
with gr.Column(scale=1):
|
183 |
autofill_btn = gr.Button("AutoFill (Optional)")
|
|
|
190 |
funder_candid_id = gr.Text(visible=False, interactive=False)
|
191 |
|
192 |
gr.HTML("<div style='margin-bottom: 20px;'></div>")
|
193 |
+
gr.Markdown(
|
194 |
+
"""
|
195 |
+
<h2>Step 3: Add project details</h2>
|
196 |
+
Provide the basic information to make your "ask" clear
|
197 |
+
""")
|
198 |
|
199 |
projects_text = gr.Textbox(
|
200 |
label="*Main projects",
|
|
|
261 |
|
262 |
with gr.Accordion():
|
263 |
gr.Markdown("""
|
264 |
+
<h2>Step 4: Additional questions</h2>
|
265 |
+
Consider answering the following questions to make your LOI sections more detailed and
|
266 |
+
compelling
|
267 |
""")
|
268 |
gr.Markdown("<h3>Organization Description</h3>")
|
269 |
capacity_text = gr.Textbox(
|
|
|
357 |
)
|
358 |
|
359 |
gr.Markdown(
|
360 |
+
"""<h2>Step 5: Review and submit</h2>
|
361 |
+
Review your input and submit for generation
|
362 |
+
""")
|
363 |
write_btn = gr.Button("Write LOI")
|
364 |
|
365 |
with gr.Column():
|
366 |
gr.Markdown(
|
367 |
+
"""<h2>Step 6: Review the generated sections</h2>
|
368 |
+
Click on "Edit Section" to run the editorial AI for rewrite suggestions, or make your own edits.
|
369 |
+
""")
|
|
|
|
|
370 |
opening = gr.Textbox(label="Opening", interactive=True, lines=3)
|
371 |
create_editable_section("Opening", JS, update_highlighted_text, opening)
|
372 |
|
|
|
387 |
create_editable_section("Conclusion", JS, update_highlighted_text, conclusion)
|
388 |
|
389 |
gr.Markdown(
|
390 |
+
"""<h2>Step 7: Output to file</h2>
|
391 |
+
Select your preferred document type and scroll to the bottom of the page to download the file.
|
392 |
+
""")
|
|
|
|
|
393 |
|
394 |
with gr.Row():
|
395 |
download_pdf_button = gr.Button("Download as PDF")
|
|
|
399 |
download_pdf_button.click(
|
400 |
generate_pdf,
|
401 |
inputs=[opening, org_desc, need, project_desc, fund_request, conclusion],
|
402 |
+
outputs=gr.File(label="Download as PDF"),
|
403 |
+
scroll_to_output=True
|
404 |
)
|
405 |
|
406 |
# pylint: disable=no-member
|
407 |
download_word_button.click(
|
408 |
generate_docx,
|
409 |
inputs=[opening, org_desc, need, project_desc, fund_request, conclusion],
|
410 |
+
outputs=gr.File(label="Download as docx"),
|
411 |
+
scroll_to_output=True
|
412 |
)
|
413 |
|
414 |
# pylint: disable=no-member
|
|
|
428 |
funder_json,
|
429 |
funder_candid_id
|
430 |
],
|
431 |
+
scroll_to_output=True,
|
432 |
api_name=False,
|
433 |
queue=True,
|
434 |
)
|
|
|
477 |
follow_up_text
|
478 |
],
|
479 |
outputs=[opening, org_desc, need, project_desc, fund_request, conclusion],
|
480 |
+
scroll_to_output=True,
|
481 |
api_name=False,
|
482 |
queue=True,
|
483 |
)
|
|
|
628 |
show_api=False,
|
629 |
auth=[
|
630 |
(os.getenv("APP_USERNAME"), os.getenv("APP_PASSWORD")),
|
631 |
+
(os.getenv("APP_PUBLIC_USERNAME"), os.getenv("APP_PUBLIC_PASSWORD")),
|
632 |
],
|
633 |
auth_message="Login to Candid's letter of intent demo"
|
634 |
)
|