Skip to content

Commit

Permalink
Merge pull request #354 from RTIInternational/dev
Browse files Browse the repository at this point in the history
Deploy July's updates
  • Loading branch information
AstridKery authored Jul 30, 2024
2 parents 866ed00 + e565451 commit f28d2e9
Show file tree
Hide file tree
Showing 18 changed files with 379 additions and 58 deletions.
10 changes: 9 additions & 1 deletion backend/django/core/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,21 @@ class Meta:

class IRRLogModelSerializer(serializers.ModelSerializer):
profile = serializers.StringRelatedField(many=False, read_only=True)
label_name = serializers.SerializerMethodField()
label_description = serializers.SerializerMethodField()
timestamp = serializers.DateTimeField(
default_timezone=pytz.timezone(TIME_ZONE_FRONTEND), format="%Y-%m-%d, %I:%M %p"
)

class Meta:
model = IRRLog
fields = ("data", "profile", "label", "timestamp")
fields = ("data", "profile", "label", "label_name", "label_description", "timestamp")

def get_label_name(self, obj):
return obj.label.name if obj.label else None

def get_label_description(self, obj):
return obj.label.description if obj.label else None


class IRRLog(serializers.HyperlinkedModelSerializer):
Expand Down
31 changes: 31 additions & 0 deletions backend/django/core/templates/projects/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ <h5 class="panel-title">
{% endif %}
{% endif %}
{% endif %}
{% if project.percentage_irr > 0 %}
<button id="download-irr-log-btn" class="btn btn-primary" onclick="downloadIRRLog({{ project.pk }})">Download IRR Log</button>
{% endif %}
</div>
</div>
</div>
Expand Down Expand Up @@ -346,6 +349,32 @@ <h5 class="panel-title">
xhttp.send();
}

/*
* When the download IRR log button is pressed, download the IRR log as a csv file
*/
function downloadIRRLog(projectId) {
var url = `/api/download_irr_log/${projectId}/`;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState === 4 && xhttp.status === 200) {
var blob = new Blob([xhttp.response], {type: 'text/csv'});
var downloadUrl = window.URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = downloadUrl;
a.download = 'irr_log_' + projectId + '.csv';
document.body.appendChild(a);
a.click();
a.remove();
window.URL.revokeObjectURL(downloadUrl);
} else if (xhttp.readyState === 4 && xhttp.status !== 200) {
console.error('Error downloading the file:', xhttp.statusText);
}
};
xhttp.open('GET', url, true);
xhttp.responseType = 'blob'; // Set the response type to blob for binary data
xhttp.send();
}


/*
* When the ingest datatable button is pressed, SMART pulls the entire
Expand Down Expand Up @@ -396,5 +425,7 @@ <h5 class="panel-title">
}
})
});


</script>
{% endblock %}
1 change: 1 addition & 0 deletions backend/django/core/templates/smart/smart.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
{% endif %}
window.ADMIN = {{admin}};
window.PROJECT_USES_IRR = {{project_uses_irr}};
window.PROJECT_SUGGESTION_MAX = {{project_suggestion_max}};

window.onload = function (e) {
$.ajax({
Expand Down
2 changes: 2 additions & 0 deletions backend/django/core/urls/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
re_path(r"^get_irr_metrics/(?P<project_pk>\d+)/$", api_admin.get_irr_metrics),
re_path(r"^heat_map_data/(?P<project_pk>\d+)/$", api_admin.heat_map_data),
re_path(r"^perc_agree_table/(?P<project_pk>\d+)/$", api_admin.perc_agree_table),
re_path(r"^irr_log/(?P<project_pk>\d+)/$", api_admin.irr_log),
re_path(r"^project_status/(?P<project_pk>\d+)/$", api_admin.get_project_status),
re_path(
r"^unassign_coder/(?P<project_pk>\d+)/(?P<profile_id>\d+)/$",
Expand All @@ -100,6 +101,7 @@
re_path(
r"^download_data/(?P<project_pk>\d+)/(?P<unverified>\d)/$", api.download_data
),
re_path(r"^download_irr_log/(?P<project_pk>\d+)/$", api.download_irr_log),
re_path(
r"^download_model/(?P<project_pk>\d+)/(?P<unverified>\d)/$", api.download_model
),
Expand Down
26 changes: 25 additions & 1 deletion backend/django/core/views/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response

from core.models import Project
from core.models import Project, IRRLog
from core.permissions import IsAdminOrCreator
from core.templatetags import project_extras
from core.utils.util import get_labeled_data
Expand Down Expand Up @@ -136,6 +136,30 @@ def download_model(request, project_pk, unverified):
return response


@api_view(["GET"])
@permission_classes((IsAdminOrCreator,))
def download_irr_log(request, project_pk):
response = HttpResponse(
content_type="text/csv",
headers={
"Content-Disposition": f'attachment; filename="irr_log_{project_pk}.csv"'
},
)

writer = csv.writer(response)
writer.writerow(["text", "label", "username", "timestamp"])

logs = IRRLog.objects.filter(data__project_id=project_pk).select_related(
"data", "profile", "label"
)

for log in logs:
label_name = log.label.name if log.label else ""
writer.writerow([log.data.text, label_name, log.profile.user, log.timestamp])

return response


@api_view(["POST"])
@permission_classes((IsAdminOrCreator,))
def import_database_table(request, project_pk):
Expand Down
22 changes: 22 additions & 0 deletions backend/django/core/views/api_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from postgres_stats.aggregates import Percentile
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from core.serializers import IRRLogModelSerializer

from core.models import (
AssignedData,
Expand Down Expand Up @@ -287,6 +288,27 @@ def perc_agree_table(request, project_pk):
return Response({"data": user_agree})


@api_view(["GET"])
@permission_classes((IsAdminOrCreator,))
def irr_log(request, project_pk):
"""Gets IRR user labels for a project.
Optionally filters to include only logs with label disagreements (i.e., data in the
admin queue) based on a query parameter.
"""
project = Project.objects.get(pk=project_pk)

admin_queue_only = request.query_params.get("admin", "false").lower() == "true"

irr_log = IRRLog.objects.filter(data__project=project)
if admin_queue_only:
irr_log = irr_log.filter(data__queues__type="admin")

irr_log_serialized = IRRLogModelSerializer(irr_log, many=True).data

return Response({"irr_log": irr_log_serialized})


@api_view(["GET"])
@permission_classes((IsAdminOrCreator,))
def heat_map_data(request, project_pk):
Expand Down
Loading

0 comments on commit f28d2e9

Please sign in to comment.