Merge pull request #546 from sartography/chore/create-template-option-745

Chore/create template option #745
This commit is contained in:
Dan Funk 2022-05-25 16:26:52 -04:00 committed by GitHub
commit d517f003e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 20 deletions

View File

@ -22,9 +22,13 @@ class CompleteTemplate(Script):
return """Using the Jinja template engine, takes data available in the current task, and uses it to populate return """Using the Jinja template engine, takes data available in the current task, and uses it to populate
a word document that contains Jinja markup. Please see https://docxtpl.readthedocs.io/en/latest/ a word document that contains Jinja markup. Please see https://docxtpl.readthedocs.io/en/latest/
for more information on exact syntax. for more information on exact syntax.
Takes two arguments:
Takes two required arguments:
1. The name of a MS Word docx file to use as a template. 1. The name of a MS Word docx file to use as a template.
2. The 'code' of the IRB Document as set in the documents.xlsx file." 2. The 'code' of the IRB Document as set in the documents.xlsx file.
And one optional argument:
1. The name for the generated file. Otherwise, we use the first argument.
""" """
def do_task_validate_only(self, task, study_id, workflow_id, *args, **kwargs): def do_task_validate_only(self, task, study_id, workflow_id, *args, **kwargs):
@ -33,14 +37,16 @@ Takes two arguments:
self.process_template(task, study_id, workflow, *args, **kwargs) self.process_template(task, study_id, workflow, *args, **kwargs)
def do_task(self, task, study_id, workflow_id, *args, **kwargs): def do_task(self, task, study_id, workflow_id, *args, **kwargs):
workflow_spec_service = WorkflowSpecService()
workflow = session.query(WorkflowModel).filter(WorkflowModel.id == workflow_id).first() workflow = session.query(WorkflowModel).filter(WorkflowModel.id == workflow_id).first()
final_document_stream = self.process_template(task, study_id, workflow, *args, **kwargs) final_document_stream = self.process_template(task, study_id, workflow, *args, **kwargs)
file_name = args[0] template_file_name = args[0]
irb_doc_code = args[1] irb_doc_code = args[1]
file_name = None
if len(args) > 2:
file_name = args[2]
UserFileService.add_workflow_file(workflow_id=workflow_id, UserFileService.add_workflow_file(workflow_id=workflow_id,
task_spec_name=task.get_name(), task_spec_name=task.get_name(),
name=file_name, name=file_name if file_name else template_file_name,
content_type=CONTENT_TYPES['docx'], content_type=CONTENT_TYPES['docx'],
binary_data=final_document_stream.read(), binary_data=final_document_stream.read(),
irb_doc_code=irb_doc_code) irb_doc_code=irb_doc_code)
@ -77,7 +83,8 @@ Takes two arguments:
raise WorkflowTaskExecException(task, ae.message, exception=ae, line_number=ae.line_number, raise WorkflowTaskExecException(task, ae.message, exception=ae, line_number=ae.line_number,
error_line=ae.error_line) error_line=ae.error_line)
def get_image_file_data(self, fields_str, task): @staticmethod
def get_image_file_data(fields_str, task):
image_file_data = [] image_file_data = []
images_field_str = re.sub(r'[\[\]]', '', fields_str) images_field_str = re.sub(r'[\[\]]', '', fields_str)
images_field_keys = [v.strip() for v in images_field_str.strip().split(',')] images_field_keys = [v.strip() for v in images_field_str.strip().split(',')]

View File

@ -8,13 +8,14 @@
<bpmn:userTask id="Activity_GetData" name="Get Data" camunda:formKey="DataForm"> <bpmn:userTask id="Activity_GetData" name="Get Data" camunda:formKey="DataForm">
<bpmn:extensionElements> <bpmn:extensionElements>
<camunda:formData> <camunda:formData>
<camunda:formField id="file_name" label="'File Name'" type="string" /> <camunda:formField id="template_file_name" label="&#39;File Name&#39;" type="string" />
<camunda:formField id="irb_doc_code" label="'IRB Doc Code'" type="enum"> <camunda:formField id="irb_doc_code" label="&#39;IRB Doc Code&#39;" type="enum">
<camunda:value id="Study_App_Doc" name="Study_App_Doc" /> <camunda:value id="Study_App_Doc" name="Study_App_Doc" />
<camunda:value id="Study_Protocol" name="Study_Protocol" /> <camunda:value id="Study_Protocol" name="Study_Protocol" />
</camunda:formField> </camunda:formField>
<camunda:formField id="name" label="'Name'" type="string" defaultValue="World" /> <camunda:formField id="name" label="&#39;Name&#39;" type="string" defaultValue="World" />
<camunda:formField id="include_me" type="string" /> <camunda:formField id="include_me" type="string" />
<camunda:formField id="file_name" label="&#39;File Name&#39;" type="string" />
</camunda:formData> </camunda:formData>
</bpmn:extensionElements> </bpmn:extensionElements>
<bpmn:incoming>Flow_1lthj06</bpmn:incoming> <bpmn:incoming>Flow_1lthj06</bpmn:incoming>
@ -26,7 +27,10 @@
<bpmn:outgoing>Flow_0ltznd4</bpmn:outgoing> <bpmn:outgoing>Flow_0ltznd4</bpmn:outgoing>
<bpmn:script>print(f'name is {name}.') <bpmn:script>print(f'name is {name}.')
print(f'include_me is {include_me}') print(f'include_me is {include_me}')
result = complete_template(file_name, irb_doc_code)</bpmn:script> if 'file_name' in globals():
result = complete_template(template_file_name, irb_doc_code, file_name)
else:
result = complete_template(template_file_name, irb_doc_code)</bpmn:script>
</bpmn:scriptTask> </bpmn:scriptTask>
<bpmn:sequenceFlow id="Flow_0ltznd4" sourceRef="Activity_CompleteTemplate" targetRef="Activity_DisplayData" /> <bpmn:sequenceFlow id="Flow_0ltznd4" sourceRef="Activity_CompleteTemplate" targetRef="Activity_DisplayData" />
<bpmn:manualTask id="Activity_DisplayData" name="Display Data"> <bpmn:manualTask id="Activity_DisplayData" name="Display Data">
@ -61,18 +65,18 @@ result = complete_template(file_name, irb_doc_code)</bpmn:script>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1"> <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="99" width="36" height="36" /> <dc:Bounds x="179" y="99" width="36" height="36" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_10trg2t_di" bpmnElement="Activity_GetData">
<dc:Bounds x="273" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1u6kbns_di" bpmnElement="Activity_CompleteTemplate">
<dc:Bounds x="432" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_14dp1gz_di" bpmnElement="Activity_DisplayData"> <bpmndi:BPMNShape id="Activity_14dp1gz_di" bpmnElement="Activity_DisplayData">
<dc:Bounds x="590" y="77" width="100" height="80" /> <dc:Bounds x="590" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0edltir_di" bpmnElement="Event_0edltir"> <bpmndi:BPMNShape id="Event_0edltir_di" bpmnElement="Event_0edltir">
<dc:Bounds x="752" y="99" width="36" height="36" /> <dc:Bounds x="752" y="99" width="36" height="36" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1u6kbns_di" bpmnElement="Activity_CompleteTemplate">
<dc:Bounds x="432" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_10trg2t_di" bpmnElement="Activity_GetData">
<dc:Bounds x="273" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane> </bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram> </bpmndi:BPMNDiagram>
</bpmn:definitions> </bpmn:definitions>

View File

@ -39,25 +39,45 @@ class TestCompleteTemplate(unittest.TestCase):
class TestEmbeddedTemplate(BaseTest): class TestEmbeddedTemplate(BaseTest):
def test_embedded_template(self): def run_docx_embedded_workflow(self, data):
self.create_reference_document() self.create_reference_document()
workflow = self.create_workflow('docx_embedded') workflow = self.create_workflow('docx_embedded')
workflow_api = self.get_workflow_api(workflow) workflow_api = self.get_workflow_api(workflow)
task = workflow_api.next_task task = workflow_api.next_task
workflow_api = self.complete_form(workflow, task, data)
return workflow_api
def test_embedded_template(self):
data = {'include_me': 'Hello {{ name }}!', data = {'include_me': 'Hello {{ name }}!',
'name': 'World', 'name': 'World',
'file_name': 'simple.docx', 'template_file_name': 'simple.docx',
'irb_doc_code': 'Study_App_Doc'} 'irb_doc_code': 'Study_App_Doc'}
self.complete_form(workflow, task, data) workflow_api = self.run_docx_embedded_workflow(data)
# Get the file data created for us in the workflow # Get the file data created for us in the workflow
file_model = session.query(FileModel).\ file_model = session.query(FileModel).\
filter(FileModel.workflow_id == workflow.id).\ filter(FileModel.workflow_id == workflow_api.id).\
filter(FileModel.irb_doc_code == 'Study_App_Doc').\ filter(FileModel.irb_doc_code == 'Study_App_Doc').\
first() first()
# If we don't pass file_name, name should be set to template_file_name
self.assertEqual(data['template_file_name'], file_model.name)
# read the data as a word document # read the data as a word document
document = docx.Document(BytesIO(file_model.data)) document = docx.Document(BytesIO(file_model.data))
# Make sure 'Hello World!' is there # Make sure 'Hello World!' is there
self.assertEqual('Hello World!', document.paragraphs[4].text) self.assertEqual('Hello World!', document.paragraphs[4].text)
data = {'include_me': 'Hello {{ name }}!',
'name': 'World',
'template_file_name': 'simple.docx',
'irb_doc_code': 'Study_App_Doc',
'file_name': 'test_file_name.docx'}
workflow_api = self.run_docx_embedded_workflow(data)
file_model = session.query(FileModel).\
filter(FileModel.workflow_id == workflow_api.id).\
filter(FileModel.irb_doc_code == 'Study_App_Doc').\
first()
# If we do pass file_name, name should be set to file_name
self.assertEqual(data['file_name'], file_model.name)