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

Updates from multi-tenant #4159

Closed
wants to merge 70 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
b2bb490
Update django to 4.2.11 (#4035)
dimasciput Jul 2, 2024
2991053
Change to first 3 letters of the park name in the add site form (#4036)
dimasciput Jul 3, 2024
330d7a8
Update uploader to accommodate sanparks template (#4038)
dimasciput Jul 4, 2024
7725c33
Improve remove occurrences by taxon group tool (#4042)
dimasciput Jul 4, 2024
ee6e90b
Fix diagram chart in landing page (#4043)
dimasciput Jul 4, 2024
c20b803
Disconnect easy_audit signals when harvesting data (#4044)
dimasciput Jul 5, 2024
c04d9de
Add identified by for biological_collection_record (#4045)
dimasciput Jul 5, 2024
7a6918a
Update add_taxa_to_taxon_group (#4046)
dimasciput Jul 5, 2024
010c4e2
Implement pdf checklist (#4047)
dimasciput Jul 8, 2024
63086ec
Simplify the navigatian bar for fada (#4048)
dimasciput Jul 9, 2024
05cfa12
Add parent to edit taxon form (#4049)
dimasciput Jul 9, 2024
16ec60a
Add taxonomy status to edit form (#4050)
dimasciput Jul 9, 2024
659648c
Fix download csv taxa list (#4052)
dimasciput Jul 10, 2024
447a0df
Fix taxon review (#4054)
dimasciput Jul 10, 2024
6d94119
Uncomment codes
dimasciput Jul 10, 2024
5c887a5
Fix issue with close button not working on the first click (#4055)
dimasciput Jul 10, 2024
195c473
Improve taxonomy update proposal workflow (#4057)
dimasciput Jul 11, 2024
c7b6f27
Show tags in edit taxon form (#4058)
dimasciput Jul 11, 2024
34eb928
Fix add new taxon (#4060)
dimasciput Jul 11, 2024
b9b0044
Improve taxon management speed (#4064)
dimasciput Jul 12, 2024
e3a1f83
Impelement edit and query for biographic distributions (#4065)
dimasciput Jul 12, 2024
214c2c5
Fix author in add new taxon (#4066)
dimasciput Jul 14, 2024
224f9ce
Add filter by author (#4067)
dimasciput Jul 14, 2024
17627b1
Add family, genus, and species filter (#4068)
dimasciput Jul 15, 2024
a2f068e
Improve easy audit crudevents (#4069)
dimasciput Jul 15, 2024
dbbb553
Fix easy audit event bugs (#4070)
dimasciput Jul 15, 2024
5c98a58
Update taxa uploader for FADA (#4071)
dimasciput Jul 15, 2024
5aa2766
Fix email current site (#4072)
dimasciput Jul 16, 2024
4ab7671
Fix migration (#4073)
dimasciput Jul 16, 2024
6b8e34f
Fix incorrect selected taxon group in the taxon management (#4077)
dimasciput Jul 17, 2024
6df1b7e
Update add_location_site_view_tenant (#4076)
dimasciput Jul 17, 2024
d7c3f92
Change data confidence fields to char field (#4089)
dimasciput Jul 22, 2024
7a37c86
Fix html tags on the email content (#4090)
dimasciput Jul 22, 2024
ba7002f
Fix sort by occurrences for module search (#4091)
dimasciput Jul 22, 2024
153c066
Fix update synonym (#4092)
dimasciput Jul 22, 2024
67c1966
Improve taxa download (#4093)
dimasciput Jul 22, 2024
390e405
Handle full subspecies name in taxa upload (#4094)
dimasciput Jul 22, 2024
e48d8c5
Fix Water temperature sites are not opening on the side panel (#4096)
dimasciput Jul 23, 2024
4580de0
Fix download request and pdf checklist (#4099)
dimasciput Jul 23, 2024
a09e3f1
Fix missing SASS dashboard button (#4100)
dimasciput Jul 24, 2024
6ace0ed
Fix the taxa upload bug with multiple IUCN statuses (#4101)
dimasciput Jul 24, 2024
0f28002
Fix taxa upload test (#4102)
dimasciput Jul 24, 2024
722baac
Add ability to add new taxon with higher taxonomic ranks (#4103)
dimasciput Jul 25, 2024
f77cf86
Fix download request in the taxon management (#4110)
dimasciput Jul 25, 2024
30f6eba
Fix database connection closed (#4111)
dimasciput Jul 25, 2024
9e310a9
Include tags and attributes in csv file download (#4112)
dimasciput Jul 25, 2024
80499da
Use forked django-dbconn-retry (#4113)
dimasciput Jul 25, 2024
ae3d842
Fix csv checklist download (#4120)
dimasciput Jul 30, 2024
36684e4
Cites listing download taxa (#4126)
dimasciput Aug 2, 2024
9cb2eca
Hide secret values (#4127)
dimasciput Aug 5, 2024
14595e7
Ignore easy-audit pre-save error (#4130)
dimasciput Aug 5, 2024
4d24e97
Fix interface error when downloading taxa list (#4131)
dimasciput Aug 5, 2024
2541302
Invasions filter (#4133)
dimasciput Aug 6, 2024
45c0612
Fix download taxa list because interface closed (#4136)
dimasciput Aug 8, 2024
f04d299
Filter occurrences by data_type (#4135)
dimasciput Aug 8, 2024
09c2f9c
Show progress when downloading taxa (#4139)
dimasciput Aug 8, 2024
3db2a84
Update Download data CSV (#4138)
dimasciput Aug 8, 2024
ba2bfb4
Get centroid of park from csv (#4140)
dimasciput Aug 12, 2024
93e34d5
Fix multi-sites overview (#4141)
dimasciput Aug 12, 2024
81e31b2
Update script to fix year bug (#4142)
dimasciput Aug 12, 2024
0a47b4a
Update and improve csv generator (#4143)
dimasciput Aug 13, 2024
9ba902a
Add link to taxa admin for FBIS (#4144)
dimasciput Aug 13, 2024
2b456a9
Check for unfinished downloads before allowing new CSV, PDF, or XLS r…
dimasciput Aug 13, 2024
e961295
Fix missing SASS dashboard (#4148)
dimasciput Aug 14, 2024
5676b0c
Put Biodiversity Records above stats (#4150)
dimasciput Aug 14, 2024
69f6933
Update user downloads count and add citation to navbar for fbis (#4151)
dimasciput Aug 14, 2024
f407f3d
Fix sign up not sending email, hide username in signup form (#4152)
dimasciput Aug 14, 2024
0a05a92
Show common names in taxon management page (#4156)
dimasciput Aug 16, 2024
41e6522
Multi tenant mini sass (#4157)
dimasciput Aug 18, 2024
7e5b46e
Upgrade django to 4.2.15 (#4158)
dimasciput Aug 18, 2024
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
2 changes: 2 additions & 0 deletions bims/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
from .celery import app as celery_app # noqa

default_app_config = 'bims.apps.BimsAppConfig'
47 changes: 41 additions & 6 deletions bims/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

from django_json_widget.widgets import JSONEditorWidget

from bims.admins.site_setting import SiteSettingAdmin
from bims.tasks import fetch_vernacular_names
from bims.utils.endemism import merge_endemism
from bims.utils.sampling_method import merge_sampling_method
Expand Down Expand Up @@ -115,7 +116,8 @@
TaxonomyUpdateProposal,
TaxonomyUpdateReviewer,
CITESListingInfo,
ImportTask
ImportTask,
Invasion
)
from bims.models.climate_data import ClimateData
from bims.utils.fetch_gbif import merge_taxa_data
Expand Down Expand Up @@ -364,6 +366,11 @@ def save_model(self, request, obj, form, change):
obj.save()


class InvasionAdmin(OrderedModelAdmin):
ordering = ('order',)
list_display = ('id', 'move_up_down_links', 'category')


class IUCNStatusAdmin(OrderedModelAdmin):
list_display = ('id', 'get_category_display', 'move_up_down_links',
'order', 'sensitive',
Expand Down Expand Up @@ -482,7 +489,6 @@ class Media:
)
list_filter = (
('collection_date', DateRangeFilter),
'taxonomy',
'taxonomy__origin',
'record_type__name',
'sampling_method',
Expand Down Expand Up @@ -977,6 +983,26 @@ class SearchProcessAdmin(admin.ModelAdmin):
'category',
'finished')

def delete_model(self, request, obj):
if obj.locked:
self.message_user(
request,
"This record is locked and cannot be deleted.",
level='warning')
else:
super().delete_model(request, obj)

def delete_queryset(self, request, queryset):
for obj in queryset:
if obj.locked:
self.message_user(
request,
f"Record with ID {obj.id} is locked and cannot be deleted.",
level='warning')
queryset = queryset.filter(locked=False)
if queryset:
super().delete_queryset(request, queryset)


class PageviewAdmin(admin.ModelAdmin):
date_hierarchy = 'view_time'
Expand Down Expand Up @@ -1115,7 +1141,8 @@ class TaxonomyAdmin(admin.ModelAdmin):

raw_id_fields = (
'parent',
'accepted_taxonomy'
'accepted_taxonomy',
'source_reference'
)

actions = ['merge_taxa', 'update_taxa', 'fetch_common_names', 'fetch_cites_listing']
Expand Down Expand Up @@ -1901,7 +1928,11 @@ class TaxonomyUpdateProposalAdmin(admin.ModelAdmin):
'original_taxonomy',
'scientific_name',
'canonical_name',
'status'
'status',
'created_at'
)
autocomplete_fields = (
'vernacular_names',
)


Expand All @@ -1916,7 +1947,7 @@ class TaxonomyUpdateReviewerAdmin(admin.ModelAdmin):
@admin.register(CITESListingInfo)
class CITESListingInfoAdmin(admin.ModelAdmin):
list_display = ('appendix', 'effective_at', 'taxonomy')
list_filter = ('appendix', 'effective_at', 'taxonomy')
list_filter = ('appendix', 'effective_at')
search_fields = ('annotation', 'taxonomy__name')
raw_id_fields = ('taxonomy',)

Expand Down Expand Up @@ -1984,7 +2015,7 @@ class ImportTaskAdmin(admin.ModelAdmin):
admin.site.register(SpatialScaleGroup, SpatialScaleGroupAdmin)
admin.site.register(SamplingMethod, SamplingMethodAdmin)
admin.site.register(SiteImage, SiteImageAdmin)
admin.site.register(SiteSetting, PreferencesAdmin)
admin.site.register(SiteSetting, SiteSettingAdmin)
admin.site.register(GeocontextSetting, PreferencesAdmin)
admin.site.register(ChemicalRecord, ChemicalRecordAdmin)
admin.site.register(Chem, ChemAdmin)
Expand Down Expand Up @@ -2061,3 +2092,7 @@ class ImportTaskAdmin(admin.ModelAdmin):
TaxonomyUpdateReviewer,
TaxonomyUpdateReviewerAdmin
)
admin.site.register(
Invasion,
InvasionAdmin
)
File renamed without changes.
76 changes: 76 additions & 0 deletions bims/admins/site_setting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from django import forms
from preferences.admin import PreferencesAdmin

from bims.models.site_setting import SiteSetting

SECRET_INPUTS = [
'recaptcha_secret_key',
'iucn_api_key',
'cites_token_api',
'virtual_museum_token',
'resend_api_key',
'github_feedback_token'
]


class SiteSettingAdminForm(forms.ModelForm):
class Meta:
model = SiteSetting
fields = '__all__'

recaptcha_secret_key = forms.CharField(
widget=forms.PasswordInput(render_value=True),
required=False
)

iucn_api_key = forms.CharField(
widget=forms.PasswordInput(render_value=True),
required=False
)

cites_token_api = forms.CharField(
widget=forms.PasswordInput(render_value=True),
required=False
)

virtual_museum_token = forms.CharField(
widget=forms.PasswordInput(render_value=True),
required=False
)

resend_api_key = forms.CharField(
widget=forms.PasswordInput(render_value=True),
required=False
)

github_feedback_token = forms.CharField(
widget=forms.PasswordInput(render_value=True),
required=False
)

minisass_token = forms.CharField(
widget=forms.PasswordInput(render_value=True),
required=False
)

def __init__(self, *args, **kwargs):
super(SiteSettingAdminForm, self).__init__(*args, **kwargs)
if self.instance and self.instance.pk:
for secret_input in SECRET_INPUTS:
self.fields[secret_input].widget.attrs['placeholder'] = '******'
self.fields[secret_input].required = False


class SiteSettingAdmin(PreferencesAdmin):
form = SiteSettingAdminForm

def save_model(self, request, obj, form, change):
if change:
for secret_input in SECRET_INPUTS:
if secret_input in form.changed_data:
setattr(obj, secret_input, form.cleaned_data[secret_input])
else:
current_value = getattr(obj, secret_input)
setattr(obj, secret_input, current_value)
obj.save()

13 changes: 13 additions & 0 deletions bims/api_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
IsHarvestingGeocontext, HarvestGeocontextView, ClearHarvestingGeocontextCache,
GetGeocontextLogLinesView
)
from bims.api_views.minisass_observations import MiniSASSObservationsView
from bims.api_views.invasions import InvasionsList
from bims.api_views.taxon_update import UpdateTaxon, ReviewTaxonProposal
from bims.api_views.reference import DeleteRecordsByReferenceId
# from rest_framework.documentation import include_docs_urls
Expand All @@ -26,6 +28,7 @@
NonBiodiversityLayerList, DownloadLayerData
)
from bims.api_views.search_module import SearchModuleAPIView

from bims.api_views.taxon import (
TaxonDetail,
FindTaxon,
Expand Down Expand Up @@ -117,6 +120,7 @@
)
from bims.api_views.wetland_data import WetlandDataApiView
from bims.views.cites import TaxaCitesStatusAPIView
from mobile.api_views.taxon_group import TaxonGroupTotalValidated

urlpatterns = [
re_path(r'^location-type/(?P<pk>[0-9]+)/allowed-geometry/$',
Expand Down Expand Up @@ -229,6 +233,9 @@
re_path(r'^endemism-list/$',
EndemismList.as_view(),
name='endemism-list'),
re_path(r'^invasions-list/$',
InvasionsList.as_view(),
name='invasions-list'),
re_path(r'^spatial-scale-filter-list/$',
SpatialScaleFilterList.as_view(),
name='spatial-scale-filter-list'),
Expand Down Expand Up @@ -370,4 +377,10 @@
path('harvesting-geocontext-logs/',
GetGeocontextLogLinesView.as_view(),
name='get_log_lines'),
path('minisass-observations/',
MiniSASSObservationsView.as_view(),
name='minisass-observations'),
path('taxon-group-validated/<int:id>/',
TaxonGroupTotalValidated.as_view(),
name='taxon-group-total-validated'),
]
117 changes: 114 additions & 3 deletions bims/api_views/checklist.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,24 @@
from django.conf import settings
from django.http import Http404
from preferences import preferences
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4, landscape
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import cm
from reportlab.platypus import SimpleDocTemplate, TableStyle, Table, Spacer
from reportlab.platypus.para import Paragraph
from rest_framework.response import Response
from rest_framework.views import APIView

from bims.api_views.search import CollectionSearch
from bims.enums import TaxonomicRank
from bims.models.taxonomy import Taxonomy
from bims.utils.domain import get_current_domain
from bims.models.download_request import DownloadRequest
from bims.serializers.checklist_serializer import ChecklistSerializer
from bims.serializers.checklist_serializer import (
ChecklistSerializer,
ChecklistPDFSerializer
)
from bims.utils.url import parse_url_to_filters
from bims.tasks.checklist import download_checklist
from bims.tasks.email_csv import send_csv_via_email
Expand Down Expand Up @@ -60,11 +71,32 @@ def generate_checklist(download_request_id):
search = CollectionSearch(filters)
batch_size = 1000
collection_records = search.process_search().distinct('taxonomy')
module_name = ''

if collection_records.count() > 0:
module_name = collection_records.values_list(
'module_group__name',
flat=True
)[0]

if (
download_request.resource_type and
download_request.resource_type.lower() == 'pdf'
):
return generate_pdf_checklist(
download_request, module_name, collection_records, batch_size)
else:
return generate_csv_checklist(
download_request, module_name, collection_records, batch_size)


def generate_csv_checklist(download_request, module_name, collection_records, batch_size):
site_domain_name = get_current_domain()

csv_file_path = os.path.join(
settings.MEDIA_ROOT,
'checklists',
f'checklist_{download_request_id}.csv')
f'{site_domain_name}_checklist_{module_name}_{download_request.id}.csv')
os.makedirs(os.path.dirname(csv_file_path), exist_ok=True)

fieldnames = [key for key in get_serializer_keys(ChecklistSerializer) if key != 'id']
Expand All @@ -83,9 +115,88 @@ def generate_checklist(download_request_id):
batch = collection_records[start:start + batch_size]
process_batch(batch, writer, written_taxa_ids)

# Save file path to download_request
download_request.processing = False
download_request.request_file = csv_file_path
download_request.request_category = f'{module_name} Checklist'
download_request.save()

return True


def generate_pdf_checklist(download_request, module_name, collection_records, batch_size):
site_domain_name = get_current_domain()
pdf_file_path = os.path.join(
settings.MEDIA_ROOT,
'checklists',
f'{site_domain_name}_checklist_{module_name}_{download_request.id}.pdf')
os.makedirs(os.path.dirname(pdf_file_path), exist_ok=True)

written_taxa_ids = set()
all_taxa = []

for start in range(0, collection_records.count(), batch_size):
batch = collection_records[start:start + batch_size]
record_taxonomy_ids = batch.values_list('taxonomy_id', flat=True)
unique_taxonomy_ids = set(record_taxonomy_ids) - written_taxa_ids

if unique_taxonomy_ids:
taxa = Taxonomy.objects.filter(
id__in=unique_taxonomy_ids
).filter(
rank__in=[
TaxonomicRank.SPECIES.name,
TaxonomicRank.SUBSPECIES.name]
)
taxon_serializer = ChecklistPDFSerializer(taxa, many=True)
for taxon in taxon_serializer.data:
written_taxa_ids.add(taxon['id'])
del taxon['id']
all_taxa.append([
Paragraph(taxon['scientific_name'], getSampleStyleSheet()['Normal']),
Paragraph(taxon['common_name'], getSampleStyleSheet()['Normal']),
Paragraph(taxon['threat_status'], getSampleStyleSheet()['Normal']),
Paragraph(taxon['sources'], getSampleStyleSheet()['Normal'])
])

# Generate the PDF
doc = SimpleDocTemplate(
pdf_file_path,
pagesize=landscape(A4), topMargin=0.5 * cm, bottomMargin=0.35 * cm)
elements = []

# Define table style
style_table = TableStyle([
('BACKGROUND', (0, 0), (-1, 0), '#0D3511'),
('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
('ALIGN', (0, 0), (-1, -1), 'LEFT'),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('FONTSIZE', (0, 0), (-1, 0), 11),
('BOTTOMPADDING', (0, 0), (-1, 0), 5),
('BACKGROUND', (0, 1), (-1, -1), colors.white),
('GRID', (0, 0), (-1, -1), 1, colors.black),
('LEFTPADDING', (0, 0), (-1, -1), 5),
('RIGHTPADDING', (0, 0), (-1, -1), 5),
('TOPPADDING', (0, 0), (-1, -1), 5),
('BOTTOMPADDING', (0, 0), (-1, -1), 5),
])

data = [
['Accepted Scientific name and authority',
'Common Name',
'Threat Status',
'Sources']] + all_taxa
table_width = doc.width
col_widths = [table_width * 0.35, table_width * 0.30, table_width * 0.15, table_width * 0.30]

table = Table(data, colWidths=col_widths)
table.setStyle(style_table)

elements.append(table)
doc.build(elements)

download_request.processing = False
download_request.request_file = pdf_file_path
download_request.request_category = f'{module_name} Checklist'
download_request.save()

return True
Expand Down
Loading
Loading