-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #29 from GSA-TTS/view-models
View models
- Loading branch information
Showing
16 changed files
with
332 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
from dataclasses import dataclass | ||
from datetime import datetime | ||
import json | ||
import numpy as np | ||
from typing import Union, List, Tuple | ||
from nad_ch.domain.entities import Entity, DataProvider, DataSubmission | ||
|
||
|
||
def get_view_model(entity: Union[Entity, List[Entity]]) -> Union[Entity, List[Entity]]: | ||
""" | ||
Provide a single factory function that an application use case can call in order to | ||
get a static view model object that it can return to its caller. | ||
""" | ||
entity_to_vm_function_map = { | ||
DataProvider: create_data_provider_vm, | ||
DataSubmission: create_data_submission_vm, | ||
} | ||
|
||
# Check if the input is a list of entities | ||
if isinstance(entity, list): | ||
# Process each entity in the list using a list comprehension | ||
return [get_view_model(single_entity) for single_entity in entity] | ||
|
||
# Process a single entity | ||
entity_type = type(entity) | ||
if entity_type in entity_to_vm_function_map: | ||
mapping_function = entity_to_vm_function_map[entity_type] | ||
return mapping_function(entity) # Call the mapping function for the entity | ||
else: | ||
raise ValueError(f"No mapping function defined for entity type: {entity_type}") | ||
|
||
|
||
@dataclass | ||
class DataProviderViewModel: | ||
id: int | ||
date_created: str | ||
name: str | ||
|
||
|
||
def create_data_provider_vm(provider: DataProvider) -> DataProviderViewModel: | ||
return DataProviderViewModel( | ||
id=provider.id, | ||
date_created=present_date(provider.created_at), | ||
name=provider.name, | ||
) | ||
|
||
|
||
@dataclass | ||
class DataSubmissionViewModel: | ||
id: int | ||
date_created: str | ||
filename: str | ||
provider_name: str | ||
report: str | ||
|
||
|
||
def create_data_submission_vm(submission: DataSubmission) -> DataSubmissionViewModel: | ||
# TODO make this be an empty array so the frontend doesn't have to check for None | ||
report_json = None | ||
if submission.report is not None: | ||
enriched_report = enrich_report(submission.report) | ||
report_json = json.dumps(enriched_report) | ||
|
||
return DataSubmissionViewModel( | ||
id=submission.id, | ||
date_created=present_date(submission.created_at), | ||
filename=submission.filename, | ||
provider_name=submission.provider.name, | ||
report=report_json, | ||
) | ||
|
||
|
||
def enrich_report(report: dict) -> dict: | ||
for feature in report.get("features", []): | ||
percent_populated, percent_empty = calculate_percentages( | ||
feature.get("populated_count"), feature.get("null_count") | ||
) | ||
|
||
feature["populated_percentage"] = present_percentage(percent_populated) | ||
feature["null_percentage"] = present_percentage(percent_empty) | ||
|
||
return report | ||
|
||
|
||
def present_date(date: datetime) -> str: | ||
return date.strftime("%B %d, %Y") | ||
|
||
|
||
def calculate_percentages(populated_count: int, null_count: int) -> Tuple[float, float]: | ||
total_fields = populated_count + null_count | ||
populated_percentage = (populated_count / total_fields) * 100 | ||
null_percentage = (null_count / total_fields) * 100 | ||
return populated_percentage, null_percentage | ||
|
||
|
||
def present_percentage(percentage: float) -> str: | ||
rounded_percentage = np.around(percentage, 2) | ||
formatted_string = ( | ||
f"{rounded_percentage:05.2f}%" if rounded_percentage != 0 else "00.00%" | ||
) | ||
return formatted_string |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
...ontrollers/web/templates/layout/base.html → ...trollers/web/templates/_layouts/base.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
{% extends "layout/base.html" %} {% block title %}Home Page{% endblock %} {% | ||
{% extends "_layouts/base.html" %} {% block title %}Home Page{% endblock %} {% | ||
block content %} | ||
<h1>Welcome to the NAD Collaboration Hub</h1> | ||
{% endblock %} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{% extends "_layouts/base.html" %} {% block title %}Home Page{% endblock %} | ||
{%block content %} | ||
<h1>Reports</h1> | ||
{% if submissions %} | ||
<table class="usa-table usa-table--borderless"> | ||
<thead> | ||
<tr> | ||
<th scope="col">Name</th> | ||
<th scope="col">Date Created</th> | ||
<th scope="col">View</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{% for sub in submissions %} | ||
<tr> | ||
<th scope="row">{{ sub.filename }}</th> | ||
<td>{{ sub.date_created }}</td> | ||
<td> | ||
<a | ||
href="{{ url_for('home.view_report', submission_id=sub.id, _external=True) }}" | ||
>View</a | ||
> | ||
</td> | ||
</tr> | ||
{% endfor %} | ||
</tbody> | ||
</table> | ||
{% else %} | ||
<p>You haven't uploaded any data submissions yet.</p> | ||
{% endif %} {% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{% extends "_layouts/base.html" %} {% block title %}Report{% endblock %} {%block | ||
content %} | ||
<h1>Report</h1> | ||
{% if submission %} | ||
<p>{{ submission.filename }}</p> | ||
<p>{{ submission.date_created}}</p> | ||
{% else %} | ||
<p>No such submission exists.</p> | ||
{% endif %} {% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.