Skip to content

Commit

Permalink
Added: UI all approval page (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
signebedi committed Aug 26, 2024
1 parent 113bad2 commit 0fae807
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 27 deletions.
41 changes: 35 additions & 6 deletions libreforms_fastapi/app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ def make_immutable_map(nested_dict):
for k, v in nested_dict.items()
})

# @parameterized_lru_cache(maxsize=128)
@parameterized_lru_cache(maxsize=128)
def cache_form_stage_data(
form_name: str,
form_stages: Map,
Expand All @@ -196,7 +196,7 @@ def cache_form_stage_data(
return stage_dict

# @parameterized_lru_cache(maxsize=128)
# @lru_cache() # Opt for a standard cache because we probably need to rebuild this entire cache when there are changes
@lru_cache() # Opt for a standard cache because we probably need to rebuild this entire cache when there are changes
def cache_form_stage_data_for_specified_user(
form_name: str,
form_stages: Map,
Expand Down Expand Up @@ -1371,10 +1371,15 @@ async def api_form_read_all_needing_action(
mailer = Depends(get_mailer),
doc_db = Depends(get_doc_db),
session: SessionLocal = Depends(get_db),
key: str = Depends(X_API_KEY)
key: str = Depends(X_API_KEY),
return_full_records_flat: bool = False,
return_count_only: bool = False,

):
"""
This method returns a dict of all the documents needing action from the current user.
This method returns a dict of all the documents needing action from the current user. Pass the
`return_full_records_flat` option to get all the records in full, and to flatten these into a
list of documents. Pass the `return_count_only` option to return an int count of actions needed.
"""

# Ugh, I'd like to find a more efficient way to get the user data. But alas, that
Expand Down Expand Up @@ -1404,7 +1409,7 @@ async def api_form_read_all_needing_action(
# Create a recursive Map of the form_stages
__mapped_form_stages = make_immutable_map(__form_model.form_stages)

print ('\n\n\n', __mapped_form_stages)
# print ('\n\n\n', __mapped_form_stages)

__documents = cache_form_stage_data_for_specified_user(
form_name=form_name,
Expand All @@ -1416,6 +1421,30 @@ async def api_form_read_all_needing_action(
dict_of_return_values[form_name] = __documents


if return_count_only:

__record_count = sum(len(records) for records in dict_of_return_values.values())

return {"record_count": __record_count}

if return_full_records_flat:

__temp = []
seen_records = set()

for __form_name, __records in dict_of_return_values.items():
for __record_id in __records:
if __record_id not in seen_records:
__record = doc_db.get_one_document(
form_name=__form_name,
document_id=__record_id,
)
__temp.append(__record)
seen_records.add(__record_id)

return {"documents": __temp}


# Write this query to the TransactionLog
if config.COLLECT_USAGE_STATISTICS:

Expand All @@ -1431,7 +1460,7 @@ async def api_form_read_all_needing_action(
)


return dict_of_return_values
return {"documents": dict_of_return_values}


# Read one form
Expand Down
43 changes: 42 additions & 1 deletion libreforms_fastapi/app/templates/base.html.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,17 @@
</div>
</li>
{% endif %}
<li><a class="dropdown-item" href="{{ url_for('ui_form_review_and_approval') }}">Review & Approval</a></li>
<li>
<a class="dropdown-item" href="{{ url_for('ui_form_review_and_approval') }}">
<div class="d-flex justify-content-between align-items-center">
<span>Review & Approval</span>
<span id="actionBadgeContainer" style="margin-left: 5px;"></span>
</div>
</a>
</li>



</ul>
</div>

Expand Down Expand Up @@ -426,6 +436,36 @@
{% if request.user.is_authenticated %}
$.ajax({
url: '/api/form/read_all_needing_action?return_count_only=true',
type: 'GET',
dataType: 'json',
beforeSend: function(xhr) {
xhr.setRequestHeader('X-API-KEY', "{{ request.user.api_key }}");
},
success: function(response) {
// console.log('AJAX response:', response); // Debugging: log the entire response
// Assuming response.record_count contains the number of actions needed
if (response.record_count && response.record_count > 0) {
// Create the badge
var badge = `<span class="badge bg-primary">${response.record_count}</span>`;
// Insert the badge into the container
$('#actionBadgeContainer').html(badge);
} else {
// Clear the badge if record_count is 0 or undefined
$('#actionBadgeContainer').empty();
}
},
error: function(xhr, status, error) {
console.error('Error:', status, error);
}
});
if (localStorage.getItem('jwt_token')) {
$.ajax({
url: '/api/auth/refresh',
Expand All @@ -444,6 +484,7 @@
});
} else {
console.log("No JWT token found in localStorage.");
}
Expand Down
41 changes: 21 additions & 20 deletions libreforms_fastapi/app/templates/review_and_approval.html.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
There are no submissions that require your review or approval at this time.
</p>

{#

<div class="container table-responsive">
<div class="spinner-border spinner-border-sm loading-circle" role="status"></div>
<table id="readAllTable" class="table table-hover table-striped table-light" style="display: none;">
Expand All @@ -33,15 +33,15 @@
</tbody>
</table>
</div>
#}


{% endblock %}

{% block scripts %}
<script src="{{url_for('static', path='js/datatables.js')}}"></script>
<script>
/*
$(document).ready(function () {
const spinner = document.querySelector('.loading-circle');
Expand All @@ -58,16 +58,25 @@ $(document).ready(function () {
}
return str;
}
function formatObject(obj) {
return Object.entries(obj)
.map(([key, value]) => `<strong>${key}</strong>: ${value}`)
.join(', ');
}
// Wrap the AJAX call in a function that returns a Promise
function fetchData(formName) {
function fetchData() {
return new Promise((resolve, reject) => {
$.ajax({
url: `/api/form/read_all/${formName}?return_when_empty=true`,
url: `/api/form/read_all_needing_action?return_full_records_flat=true`,
type: "GET",
dataType: 'json',
beforeSend: function(xhr){xhr.setRequestHeader('X-API-KEY', apiKey);},
success: function(formData) {
resolve(formData.documents);
console.log(formData.documents);
},
error: function(xhr, status, error) {
reject(error);
Expand All @@ -76,19 +85,11 @@ $(document).ready(function () {
});
}
// Create an array of promises
let promises = formNames.map(formName => fetchData(formName));
// Use Promise.allSettled to process data after all AJAX calls are complete
Promise.allSettled(promises).then(results => {
results.forEach(result => {
if (result.status === 'fulfilled') {
allFormData = allFormData.concat(result.value);
}
// else {
// console.error("Failed to fetch data for form:", result.reason);
// }
});
// Use .then() to process data after the AJAX call is complete
fetchData().then(formData => {
allFormData = allFormData.concat(formData);
console.log(allFormData);
Expand All @@ -97,7 +98,8 @@ $(document).ready(function () {
let row = `<tr>
<td><a href="/ui/form/read_one/${form['metadata']['form_name']}/${form['metadata']['document_id']}">${form['metadata']['document_id']}</a></td>
<td>${form['metadata']['form_name'].replace(/_/g, ' ')}</td>
<td>${GFG(JSON.stringify(form['data']), 60)}</td>
{# <td>${GFG(JSON.stringify(form['data']), 60)}</td> #}
<td>${formatObject(form['data'])}</td>
<td>
<a target="_blank" href="/ui/auth/p/${form['metadata']['last_editor']}" class="badge bg-primary text-decoration-none" style=" {%if not config['OTHER_PROFILES_ENABLED'] and not request.user.site_admin%} pointer-events: none;{%endif%}" aria-label="Link to ${form['metadata']['last_editor']}">
${form['metadata']['last_editor']}
Expand Down Expand Up @@ -140,7 +142,6 @@ $(document).ready(function () {
});
});
*/
</script>

{% endblock %}

0 comments on commit 0fae807

Please sign in to comment.