Skip to content

Commit

Permalink
Added: support for including reviewer comments with an approval decis…
Browse files Browse the repository at this point in the history
…ion (#337)
  • Loading branch information
signebedi committed Sep 15, 2024
1 parent 2115415 commit 62bc6bd
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
10 changes: 9 additions & 1 deletion libreforms_fastapi/app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2722,10 +2722,13 @@ async def api_form_sign(
doc_db = Depends(get_doc_db),
session: SessionLocal = Depends(get_db),
key: str = Depends(X_API_KEY),
reviewer_comments: str = "",
):
"""
Digitally signs a specific document in a form that requires approval and routes
to the next form stage. Logs the signing action.
to the next form stage. Logs the signing action. You can pass a `reviewer_comments`
query param to associate comments with the review action that is taking place. This
field has a max length of 300 characters.
"""

if not config.API_ENABLED:
Expand All @@ -2739,6 +2742,10 @@ async def api_form_sign(
if action not in permitted_actions:
raise HTTPException(status_code=404, detail=f"Form '{action}' not permitted")

# Ensure reviewer_comments does not exceed 300 characters
if len(reviewer_comments) > 300:
raise HTTPException(status_code=400, detail="Reviewer comments cannot exceed 300 characters.")

# Ugh, I'd like to find a more efficient way to get the user data. But alas, that
# the sqlalchemy-signing table is not optimized alongside the user model...
user = session.query(User).filter_by(api_key=key).first()
Expand Down Expand Up @@ -2782,6 +2789,7 @@ async def api_form_sign(
# Build the metadata field
metadata={
doc_db.last_editor_field: user.username,
doc_db.reviewer_comments_field: reviewer_comments
}

# Add the remote addr host if enabled
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@
<p>You are currently in the Review & Approval interface for this submission. You can see its details below. If you would like to go back to the general Review & Approval page, click <a href="/ui/form/review_and_approval">here</a>. If you would like to view this submission outside the Review & Approval interface, click <a href="/ui/form/read_one/{{ form_name }}/{{ document_id }}">here</a>.</p>
<p>The current stage for this submission is <code><span id="currentFormStage">{{stage_conf["label"] if "label" in stage_conf.keys() else form_stage}}</span></code>.</p>


{% if "on_approve" in stage_conf.keys() or
"on_deny" in stage_conf.keys() or
"on_pushback" in stage_conf.keys() or
"on_confirm" in stage_conf.keys() %}
<fieldset style="padding-bottom: 20px;">
<label aria-labelledby="reviewer_comments_help" for="reviewer_comments" class="form-check-label set-bold">Reviewer Comments</label>
<span id="reviewer_comments_help" class="form-text">Optional. Use this space to provide any reviewer comments you would like to attach along with your decision. These comments will be automatically added when you select an action below. Max length: 300 characters.</span>
<textarea maxlength="300" class="form-control" id="reviewer_comments" name="reviewer_comments" rows="3" placeholder="Add your comments here..."></textarea>
</fieldset>

{% endif %}

{% if "on_approve" in stage_conf.keys()%}
<button onclick="signForm('approve');" id="form_approval" class="btn btn-primary" disabled>I approve this submission</button>
{% endif %}
Expand Down Expand Up @@ -72,8 +85,18 @@
{% endif %}
function signForm(action) {
// Get the value from the reviewer_comments textarea
const reviewerComments = document.getElementById('reviewer_comments').value;
// Construct the query parameter for reviewer_comments if it's not empty
let queryParams = "";
if (reviewerComments.trim() !== "") {
queryParams = `?reviewer_comments=${encodeURIComponent(reviewerComments.trim())}`;
}
$.ajax({
url: `/api/form/sign/${formName}/${documentId}/${action}`,
url: `/api/form/sign/${formName}/${documentId}/${action}${queryParams}`,
type: 'PATCH',
headers: {
'X-API-KEY': apiKey,
Expand Down
4 changes: 4 additions & 0 deletions libreforms_fastapi/utils/document_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ def _initialize_metadata_fields(self):
# [self.created_by_field, self.last_editor_field, field_name, field_name]
self.linked_to_form_field = "linked_form_fields"
# [(field_name, form_name, [display_field, display_field])]
self.reviewer_comments_field = "reviewer_comments"

return [
self.form_name_field,
Expand All @@ -248,6 +249,7 @@ def _initialize_metadata_fields(self):
self.journal_field,
self.linked_to_user_field,
self.linked_to_form_field,
self.reviewer_comments_field,
]
@abstractmethod
def _initialize_database_collections(self):
Expand Down Expand Up @@ -732,6 +734,7 @@ def advance_document_stage(
self.last_modified_field: current_timestamp.isoformat(),
self.last_editor_field: metadata.get(self.last_editor_field, None),
self.ip_address_field: metadata.get(self.ip_address_field, None),
self.reviewer_comments_field: metadata.get(self.reviewer_comments_field, ""),
},
}

Expand Down Expand Up @@ -808,6 +811,7 @@ def advance_document_stage(
document['metadata'][self.last_modified_field] = current_timestamp.isoformat()
document['metadata'][self.last_editor_field] = metadata.get(self.last_editor_field, None)
document['metadata'][self.ip_address_field] = metadata.get(self.ip_address_field, None)
document['metadata'][self.reviewer_comments_field] = metadata.get(self.reviewer_comments_field, "")
document['metadata'][self.journal_field] = journal

# Set the form stage stored in the document's metadata to the
Expand Down

0 comments on commit 62bc6bd

Please sign in to comment.