Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature delete records by source reference id #3649

Merged
merged 2 commits into from
Dec 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions bims/api_urls.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from django.urls import re_path, include, path

from bims.api_views.reference import DeleteRecordsByReferenceId
# from rest_framework.documentation import include_docs_urls
from bims.api_views.boundary import (
BoundaryList,
Expand Down Expand Up @@ -320,8 +322,10 @@
),
re_path(r'^gbif-ids/download/$',
GbifIdsDownloader.as_view()),

path('download-layer-data/<int:layer_id>/<str:query_filter>/',
DownloadLayerData.as_view(),
name='download-layer-data')
name='download-layer-data'),
path('delete-records-by-source-reference-id/<int:source_reference_id>/',
DeleteRecordsByReferenceId.as_view(),
name='delete-records-by-source-reference-id')
]
68 changes: 68 additions & 0 deletions bims/api_views/reference.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from django.http import (
Http404, HttpResponseServerError, HttpResponseForbidden
)
from django.shortcuts import get_object_or_404
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from bims.models.source_reference import (
SourceReference
)
from bims.models.biological_collection_record import (
BiologicalCollectionRecord
)
from bims.models.chemical_record import (
ChemicalRecord
)
from bims.models.decision_support_tool import DecisionSupportTool


class DeleteRecordsByReferenceId(APIView):
"""
API endpoint for deleting BiologicalCollectionRecord and ChemicalRecord
instances associated with a given SourceReference ID.
"""

def post(self, request, *args, **kwargs):
if not request.user.is_superuser:
return HttpResponseForbidden(
'Only superusers are allowed to perform this action.'
)

source_reference_id = kwargs.get('source_reference_id')
if not source_reference_id:
raise Http404('Missing id')

try:
source_reference = get_object_or_404(
SourceReference,
pk=source_reference_id
)
messages = []
bio_records = BiologicalCollectionRecord.objects.filter(source_reference_id=source_reference_id)
if bio_records.exists():
DecisionSupportTool.objects.filter(
biological_collection_record__id__in=list(bio_records.values_list('id', flat=True))
).delete()
BiologicalCollectionRecord.objects.filter(source_reference_id=source_reference_id).delete()
messages.append(
'BiologicalCollectionRecord successfully deleted'
)
else:
messages.append("No BiologicalCollectionRecord found for the given reference ID.")

if ChemicalRecord.objects.filter(source_reference_id=source_reference_id).exists():
ChemicalRecord.objects.filter(source_reference_id=source_reference_id).delete()
messages.append(
'ChemicalRecord successfully deleted'
)
else:
messages.append("No ChemicalRecord found for the given reference ID.")

return Response(
{'message': messages},
status=status.HTTP_200_OK)

except Exception as e:
# In case of any other error, return a 500 Internal Server Error
return HttpResponseServerError(f'An error occurred: {e}')
5 changes: 4 additions & 1 deletion bims/models/decision_support_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,7 @@ class DecisionSupportTool(models.Model):
)

def __str__(self):
return f'{self.name} - {self.biological_collection_record.uuid}'
try:
return f'{self.name} - {self.biological_collection_record.uuid}'
except Exception as e:
return f'{self.name}'
2 changes: 1 addition & 1 deletion bims/models/survey.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import uuid

from django.db import models
from django.db.models.signals import post_delete, pre_delete
from django.db.models.signals import pre_delete
from django.dispatch import receiver
from django.utils import timezone
from bims.models import LocationSite
Expand Down
59 changes: 59 additions & 0 deletions bims/static/css/source_reference_list.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
.card {
margin-bottom: 10px;
}

.custom-control-label {
max-width: 80%;
}

.reference-filter-title {
margin-bottom: 0 !important;
font-weight: bold;
}
.badge-occurrences {
font-size: 9pt;
padding-left: 10px;
padding-right: 10px;
padding-top: 8px;
padding-bottom: 8px;
}
.badge-zero {
background-color: #b8b8b8;
}
.reference-type-label {
text-transform: uppercase;
font-weight: 300;
font-size: 10pt;
}
.active.active:hover {
color: white;
}
.input-group-append:hover {
cursor: pointer;
}
.loading-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.8);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
}

.loader {
border: 5px solid #f3f3f3;
border-top: 5px solid #3498db;
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 2s linear infinite;
}

@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
76 changes: 76 additions & 0 deletions bims/static/js/non_requirejs/source_reference_list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
$('.copy-document-id').click(function (e) {
let documentId = window.location.origin + '/documents/' + $(e.target).data('document-id');
/* Copy the text inside the text field */
navigator.clipboard.writeText(documentId);
/* Alert the copied text */
alert("Copied the text: " + documentId);
})

$('.custom-control-input').change(function (e) {
let $parent = $(e.target).parent().parent();
let filterName = $parent.data('filter');
let checkedVals = $parent.find(':checkbox:checked').map(function () {
return this.value;
}).get();
insertParam(filterName, checkedVals);
})

$('.input-group-append').click(function (e) {
let value = $('#search-input').val();
insertParam('q', value);
})

$('.delete-reference').click(function (e) {
e.preventDefault();
const referenceId = $(e.target).data('reference-id');
let r = confirm("Are you sure you want to remove this reference?");
if (r === true) {
$.ajax({
url: "/delete-source-reference/",
headers: {"X-CSRFToken": csrfToken},
type: 'POST',
data: {
'reference_id': referenceId
},
success: function (res) {
location.reload();
}
});
}
})

$('.delete-records').click(function (e) {
e.preventDefault();
const referenceId = $(e.target).data('reference-id');
const totalRecords = $(e.target).data('total-records');
const totalPhysico = $(e.target).data('total-physico-chemical-data');
let r = confirm(
`Are you sure you want to remove ${totalRecords} records and ${totalPhysico}
Physico-chemical data associated with this source reference?`);
if (r) {
document.getElementById('loading-animation').style.display = 'flex';
console.log('called');
$.ajax({
url: `/api/delete-records-by-source-reference-id/${referenceId}/`,
type: 'POST',
headers: {"X-CSRFToken": csrfToken},
success: function(response) {
window.location.reload();
},
error: function(xhr, textStatus, errorThrown) {
alert('Error: ' + errorThrown);
document.getElementById('loading-animation').style.display = 'none';
}
});
}

})


$('.apply-author-filter').click(function(e) {
const $target = $(e.target).parent();
const authorIds = $target.find('.author_result').map(function () {
return $(this).data("author-id");
}).get();
insertParam('collectors', authorIds.join(','))
})
107 changes: 20 additions & 87 deletions bims/templates/source_reference_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,45 +8,16 @@
{% block pre-head %}
<link rel="stylesheet"
href="{% static "lib/select2-4.1.0/css/select2.min.css" %}">
<style>
.card {
margin-bottom: 10px;
}

.custom-control-label {
max-width: 80%;
}

.reference-filter-title {
margin-bottom: 0 !important;
font-weight: bold;
}
.badge-occurrences {
font-size: 9pt;
padding-left: 10px;
padding-right: 10px;
padding-top: 8px;
padding-bottom: 8px;
}
.badge-zero {
background-color: #b8b8b8;
}
.reference-type-label {
text-transform: uppercase;
font-weight: 300;
font-size: 10pt;
}
.active.active:hover {
color: white;
}
.input-group-append:hover {
cursor: pointer;
}
</style>
<link rel="stylesheet"
href="{% static "css/source_reference_list.css" %}">
{% endblock %}

{% block body_content %}
<!-- Page Header -->
<div id="loading-animation" class="loading-container">
<!-- Here, you can use an image or any animation you like -->
<div class="loader"></div>
</div>
<div class="body-container container">
<div class="dashboard-title">
<h2>Explore Source References&nbsp;<span class="vertical-separator"></span>{{ page_obj.paginator.count }} Result{% if page_obj.paginator.count > 1 %}s{% endif %}</h2>
Expand Down Expand Up @@ -150,8 +121,17 @@ <h5 class="card-title">{{ source_reference.link_template | safe }}</h5>
<a href="/edit-source-reference/{{ source_reference.id }}/?next={{ request.get_full_path | urlencode }}" class="badge badge-primary badge-occurrences">Update</a>
</div>
<div class="float-right">
<a href="#" class="badge badge-danger badge-occurrences delete-reference" data-reference-id="{{ source_reference.id }}">Delete</a>&nbsp;
<a href="#" class="badge badge-danger badge-occurrences delete-reference" data-reference-id="{{ source_reference.id }}">Delete source reference</a>&nbsp;
</div>
{% if source_reference.occurrences > 0 or source_reference.chemical_records > 0 %}
<div class="float-right">
<a href="#" class="badge badge-warning badge-occurrences delete-records"
data-reference-id="{{ source_reference.id }}"
data-total-physico-chemical-data="{{ source_reference.chemical_records }}"
data-total-records="{{ source_reference.occurrences }}"
>Delete records</a>&nbsp;
</div>
{% endif %}
{% endif %}
</div>
</div>
Expand All @@ -176,58 +156,11 @@ <h5 class="card-title">{{ source_reference.link_template | safe }}</h5>
<script src="{% static "js/utils/insert_param_to_url.js" %}"></script>
<script src="{% static "js/non_requirejs/multi_author_select.js" %}"></script>
<script>

const csrfToken = '{{ csrf_token }}';
const authorIds = [];

$('.copy-document-id').click(function (e) {
let documentId = window.location.origin + '/documents/' + $(e.target).data('document-id');
/* Copy the text inside the text field */
navigator.clipboard.writeText(documentId);
/* Alert the copied text */
alert("Copied the text: " + documentId);
})

$('.custom-control-input').change(function (e) {
let $parent = $(e.target).parent().parent();
let filterName = $parent.data('filter');
let checkedVals = $parent.find(':checkbox:checked').map(function () {
return this.value;
}).get();
insertParam(filterName, checkedVals);
})

$('.input-group-append').click(function (e) {
let value = $('#search-input').val();
insertParam('q', value);
})

$('.delete-reference').click(function (e) {
e.preventDefault();
const referenceId = $(e.target).data('reference-id');
let r = confirm("Are you sure you want to remove this reference?");
if (r === true) {
$.ajax({
url: "/delete-source-reference/",
headers: {"X-CSRFToken": csrfToken},
type: 'POST',
data: {
'reference_id': referenceId
},
success: function (res) {
location.reload();
}
});
}
})

$('.apply-author-filter').click(function(e) {
const $target = $(e.target).parent();
const authorIds = $target.find('.author_result').map(function () {
return $(this).data("author-id");
}).get();
insertParam('collectors', authorIds.join(','))
})

window.onload = function() {
document.getElementById('loading-animation').style.display = 'none';
};
</script>
<script src="{% static "js/non_requirejs/source_reference_list.js" %}"></script>
{% endblock %}
Loading
Loading