feat: Add basic name based search for rescue orgs
This commit is contained in:
@@ -145,10 +145,15 @@ class AnimalGetSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
|
|
||||||
class RescueOrganizationSerializer(serializers.ModelSerializer):
|
class RescueOrganizationSerializer(serializers.ModelSerializer):
|
||||||
|
url = serializers.SerializerMethodField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = RescueOrganization
|
model = RescueOrganization
|
||||||
exclude = ["internal_comment", "allows_using_materials"]
|
exclude = ["internal_comment", "allows_using_materials"]
|
||||||
|
|
||||||
|
def get_url(self, obj):
|
||||||
|
return obj.get_absolute_url()
|
||||||
|
|
||||||
|
|
||||||
class ImageCreateSerializer(serializers.ModelSerializer):
|
class ImageCreateSerializer(serializers.ModelSerializer):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ from django.urls import path
|
|||||||
from .views import (
|
from .views import (
|
||||||
AdoptionNoticeApiView,
|
AdoptionNoticeApiView,
|
||||||
AnimalApiView, RescueOrganizationApiView, AddImageApiView, SpeciesApiView, LocationApiView,
|
AnimalApiView, RescueOrganizationApiView, AddImageApiView, SpeciesApiView, LocationApiView,
|
||||||
AdoptionNoticeGeoJSONView, RescueOrgGeoJSONView, AdoptionNoticePerOrgApiView
|
AdoptionNoticeGeoJSONView, RescueOrgGeoJSONView, AdoptionNoticePerOrgApiView, index
|
||||||
)
|
)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
path("", index, name="api-base-url"),
|
||||||
path("adoption_notice", AdoptionNoticeApiView.as_view(), name="api-adoption-notice-list"),
|
path("adoption_notice", AdoptionNoticeApiView.as_view(), name="api-adoption-notice-list"),
|
||||||
path("adoption_notice.geojson", AdoptionNoticeGeoJSONView.as_view(), name="api-adoption-notice-list-geojson"),
|
path("adoption_notice.geojson", AdoptionNoticeGeoJSONView.as_view(), name="api-adoption-notice-list-geojson"),
|
||||||
path("adoption_notice/<int:id>/", AdoptionNoticeApiView.as_view(), name="api-adoption-notice-detail"),
|
path("adoption_notice/<int:id>/", AdoptionNoticeApiView.as_view(), name="api-adoption-notice-detail"),
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
from django.urls import reverse
|
||||||
from drf_spectacular.types import OpenApiTypes
|
from drf_spectacular.types import OpenApiTypes
|
||||||
from rest_framework.generics import ListAPIView
|
from rest_framework.generics import ListAPIView
|
||||||
|
|
||||||
@@ -450,3 +452,7 @@ class AdoptionNoticePerOrgApiView(APIView):
|
|||||||
adoption_notices = temporary_an_storage
|
adoption_notices = temporary_an_storage
|
||||||
serializer = AdoptionNoticeSerializer(adoption_notices, many=True, context={"request": request})
|
serializer = AdoptionNoticeSerializer(adoption_notices, many=True, context={"request": request})
|
||||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
|
def index(request):
|
||||||
|
return redirect(reverse("swagger-ui"))
|
||||||
|
|||||||
@@ -186,6 +186,11 @@ class RescueOrgSearchForm(forms.Form):
|
|||||||
label=_("Suchradius"))
|
label=_("Suchradius"))
|
||||||
|
|
||||||
|
|
||||||
|
class RescueOrgSearchByNameForm(forms.Form):
|
||||||
|
template_name = "fellchensammlung/forms/form_snippets.html"
|
||||||
|
name = forms.CharField(max_length=100, label=_("Name der Organisation"), required=False)
|
||||||
|
|
||||||
|
|
||||||
class CloseAdoptionNoticeForm(forms.ModelForm):
|
class CloseAdoptionNoticeForm(forms.ModelForm):
|
||||||
template_name = "fellchensammlung/forms/form_snippets.html"
|
template_name = "fellchensammlung/forms/form_snippets.html"
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,11 @@
|
|||||||
<i class="fas fa-search fa-fw"></i> {% trans 'Suchen' %}
|
<i class="fas fa-search fa-fw"></i> {% trans 'Suchen' %}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
<hr>
|
||||||
|
<form method="post" autocomplete="off">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ org_name_search_form }}
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
@@ -69,4 +74,57 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
const $nameInput = $("#id_name");
|
||||||
|
|
||||||
|
$nameInput.wrap("<div class='dropdown' id='location-result-list'></div>");
|
||||||
|
const dropdown = $("#location-result-list");
|
||||||
|
$nameInput.wrap("<div class='dropdown-trigger'></div>");
|
||||||
|
$("<div class='dropdown-content' id='results'></div>").insertAfter($nameInput);
|
||||||
|
const $resultsList = $("#results");
|
||||||
|
$resultsList.wrap("<div class='dropdown-menu'></div>");
|
||||||
|
|
||||||
|
|
||||||
|
$nameInput.on("input", function () {
|
||||||
|
const query = $.trim($nameInput.val());
|
||||||
|
|
||||||
|
if (query.length < 3) {
|
||||||
|
dropdown.removeClass("is-active");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "{% api_base_url %}organizations/",
|
||||||
|
data: {
|
||||||
|
search: query
|
||||||
|
},
|
||||||
|
method: "GET",
|
||||||
|
dataType: "json",
|
||||||
|
success: function (data) {
|
||||||
|
$resultsList.empty();
|
||||||
|
dropdown.addClass("is-active");
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
const orgs = data.slice(0, 5);
|
||||||
|
|
||||||
|
$.each(orgs, function (index, org) {
|
||||||
|
const $listItem = $("<a>")
|
||||||
|
.addClass("dropdown-item")
|
||||||
|
.addClass("result-item")
|
||||||
|
.attr('href', org.url)
|
||||||
|
.text(org.name);
|
||||||
|
|
||||||
|
$resultsList.append($listItem);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function () {
|
||||||
|
$resultsList.html('<li class="result-item">{% trans 'Error fetching data. Please try again.' %}</li>');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from django.template.defaultfilters import stringfilter
|
|||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
from fellchensammlung.tools.misc import time_since_as_hr_string
|
from fellchensammlung.tools.misc import time_since_as_hr_string
|
||||||
from notfellchen import settings
|
from notfellchen import settings
|
||||||
@@ -54,6 +55,11 @@ def get_oxitraffic_script_if_enabled():
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag
|
||||||
|
def api_base_url():
|
||||||
|
return reverse("api-base-url")
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
@stringfilter
|
@stringfilter
|
||||||
def pointdecimal(value):
|
def pointdecimal(value):
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ class AdoptionNoticeSearch:
|
|||||||
|
|
||||||
class RescueOrgSearch:
|
class RescueOrgSearch:
|
||||||
def __init__(self, request):
|
def __init__(self, request):
|
||||||
|
self.name = None
|
||||||
self.area_search = None
|
self.area_search = None
|
||||||
self.max_distance = None
|
self.max_distance = None
|
||||||
self.location = None # Can either be Location (DjangoModel) or LocationProxy
|
self.location = None # Can either be Location (DjangoModel) or LocationProxy
|
||||||
@@ -229,6 +230,7 @@ class RescueOrgSearch:
|
|||||||
return fitting_rescue_orgs
|
return fitting_rescue_orgs
|
||||||
|
|
||||||
def rescue_org_search_from_request(self, request):
|
def rescue_org_search_from_request(self, request):
|
||||||
|
# Only search if request method is get with action search
|
||||||
if request.method == 'GET' and request.GET.get("action", False) == "search":
|
if request.method == 'GET' and request.GET.get("action", False) == "search":
|
||||||
self.search_form = RescueOrgSearchForm(request.GET)
|
self.search_form = RescueOrgSearchForm(request.GET)
|
||||||
self.search_form.is_valid()
|
self.search_form.is_valid()
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ from .models import AdoptionNotice, Text, Animal, Rule, Image, Report, Moderatio
|
|||||||
ImportantLocation, SpeciesSpecificURL, NotificationTypeChoices, SocialMediaPost
|
ImportantLocation, SpeciesSpecificURL, NotificationTypeChoices, SocialMediaPost
|
||||||
from .forms import AdoptionNoticeForm, ImageForm, ReportAdoptionNoticeForm, \
|
from .forms import AdoptionNoticeForm, ImageForm, ReportAdoptionNoticeForm, \
|
||||||
CommentForm, ReportCommentForm, AnimalForm, AdoptionNoticeFormAutoAnimal, SpeciesURLForm, RescueOrgInternalComment, \
|
CommentForm, ReportCommentForm, AnimalForm, AdoptionNoticeFormAutoAnimal, SpeciesURLForm, RescueOrgInternalComment, \
|
||||||
UpdateRescueOrgRegularCheckStatus, UserModCommentForm, CloseAdoptionNoticeForm
|
UpdateRescueOrgRegularCheckStatus, UserModCommentForm, CloseAdoptionNoticeForm, RescueOrgSearchByNameForm
|
||||||
from .models import Language, Announcement
|
from .models import Language, Announcement
|
||||||
from .tools import i18n, img
|
from .tools import i18n, img
|
||||||
from .tools.fedi import post_an_to_fedi
|
from .tools.fedi import post_an_to_fedi
|
||||||
@@ -851,6 +851,7 @@ def list_rescue_organizations(request, species=None, template='fellchensammlung/
|
|||||||
context = {"rescue_organizations_to_list": rescue_organizations_to_list,
|
context = {"rescue_organizations_to_list": rescue_organizations_to_list,
|
||||||
"show_rescue_orgs": True,
|
"show_rescue_orgs": True,
|
||||||
"elided_page_range": paginator.get_elided_page_range(page_number, on_each_side=2, on_ends=1),
|
"elided_page_range": paginator.get_elided_page_range(page_number, on_each_side=2, on_ends=1),
|
||||||
|
"org_name_search_form": RescueOrgSearchByNameForm(),
|
||||||
}
|
}
|
||||||
if org_search:
|
if org_search:
|
||||||
additional_context = {
|
additional_context = {
|
||||||
|
|||||||
Reference in New Issue
Block a user