diff --git a/core/admin.py b/core/admin.py index 9a71aace..0df72886 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,4 +1,3 @@ - from contextlib import suppress from constance.admin import Config @@ -12,7 +11,6 @@ from modeltranslation.translator import NotRegistered, translator from modeltranslation.utils import get_translation_fields from mptt.admin import DraggableMPTTAdmin -from core.filters import AutocompleteFieldListFilter from core.forms import OrderForm, OrderProductForm, VendorForm from core.models import ( Address, @@ -249,8 +247,6 @@ class ProductAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): "stocks__vendor", "created", "modified", - ("brand", AutocompleteFieldListFilter), - ("category", AutocompleteFieldListFilter), ) search_fields = ( "name", diff --git a/core/filters.py b/core/filters.py index 8fb72b8d..609aee41 100644 --- a/core/filters.py +++ b/core/filters.py @@ -2,8 +2,7 @@ import json import logging import uuid -from django.contrib.admin import FieldListFilter -from django.core.exceptions import BadRequest, ValidationError +from django.core.exceptions import BadRequest from django.db.models import ( Avg, Case, @@ -17,7 +16,6 @@ from django.db.models import ( When, ) from django.db.models.functions import Coalesce -from django.forms import Media from django.utils.http import urlsafe_base64_decode from django.utils.translation import gettext_lazy as _ from django_filters import ( @@ -505,78 +503,3 @@ class AddressFilter(FilterSet): class Meta: model = Address fields = ["uuid", "user_uuid", "user_email", "order_by"] - - -class AutocompleteFieldListFilter(FieldListFilter): - - template = "admin/autocomplete_filter.html" - - def __init__(self, field, request, params, model, model_admin, field_path): - self.lookup_kwarg = f"{field_path}__exact" - self.lookup_val = request.GET.get(self.lookup_kwarg) - self.field = field - self.field_path = field_path - self.model = model - self.related_model = field.related_model - super().__init__(field, request, params, model, model_admin, field_path) - - def has_output(self): - return True - - def choices(self, changelist): - choices = [] - if self.lookup_val: - try: - obj = self.related_model.objects.get(pk=self.lookup_val) - choices.append( - { - "selected": True, - "query_string": changelist.get_query_string(remove=[self.lookup_kwarg]), - "display": str(obj), - "value": obj.pk, - } - ) - except (self.related_model.DoesNotExist, ValidationError): - pass - return choices - - def queryset(self, request, queryset): - if self.lookup_val: - try: - return queryset.filter(**{self.lookup_kwarg: self.lookup_val}) - except (ValueError, ValidationError): - pass - return queryset - - def expected_parameters(self): - return [self.lookup_kwarg] - - @property - def media(self): - extra = "" if self.used_parameters else ".min" - js = [ - f"admin/js/vendor/jquery/jquery{extra}.js", - f"admin/js/vendor/select2/select2.full{extra}.js", - "admin/js/autocomplete_filter.js", - ] - css = { - "screen": [ - f"admin/css/vendor/select2/select2{extra}.css", - "admin/css/autocomplete_filter.css", - ] - } - return Media(js=js, css=css) - - def get_context_data(self): - field_name = self.field_path.replace("__", "_") - related_url = f'/admin/{self.related_model._meta.app_label}/{self.related_model._meta.model_name}/autocomplete/' - - return { - 'field_name': field_name, - 'lookup_kwarg': self.lookup_kwarg, - 'lookup_val': self.lookup_val or '', - 'related_url': related_url, - 'placeholder': _('Search %s...') % self.related_model._meta.verbose_name, - 'clear_text': _('Clear'), - 'field_verbose_name': self.field.verbose_name or self.field.name.replace('_', ' ').title(), - } diff --git a/core/static/admin/css/autocomplete_list_filter.css b/core/static/admin/css/autocomplete_list_filter.css deleted file mode 100644 index 058e529a..00000000 --- a/core/static/admin/css/autocomplete_list_filter.css +++ /dev/null @@ -1,61 +0,0 @@ -.autocomplete-filter-widget { - margin-bottom: 10px; - padding: 8px; - border: 1px solid #ddd; - background: #f9f9f9; - border-radius: 4px; -} - -.autocomplete-filter-widget h3 { - margin: 0 0 8px 0; - font-size: 11px; - text-transform: uppercase; - font-weight: bold; - color: #666; -} - -.autocomplete-filter-controls { - display: flex; - align-items: center; - gap: 8px; -} - -.autocomplete-input { - flex: 1; -} - -.autocomplete-clear { - background: #ba2121; - color: white; - border: none; - padding: 4px 8px; - border-radius: 3px; - cursor: pointer; - font-size: 11px; - text-decoration: none; - display: inline-block; -} - -.autocomplete-clear:hover { - background: #a41e1e; - color: white; -} - -.select2-container { - font-size: 12px; -} - -.select2-container .select2-selection--single { - height: 28px; - border: 1px solid #ccc; -} - -.select2-container .select2-selection--single .select2-selection__rendered { - line-height: 26px; - padding-left: 8px; -} - -.select2-container .select2-selection--single .select2-selection__arrow { - height: 26px; - right: 4px; -} \ No newline at end of file diff --git a/core/static/admin/js/autocomplete_list_filter.js b/core/static/admin/js/autocomplete_list_filter.js deleted file mode 100644 index a7976b6d..00000000 --- a/core/static/admin/js/autocomplete_list_filter.js +++ /dev/null @@ -1,86 +0,0 @@ -(function ($) { - 'use strict'; - - $(document).ready(function () { - $('.autocomplete-filter-widget').each(function () { - let $widget = $(this); - let $input = $widget.find('.autocomplete-input'); - let $hiddenInput = $widget.find('.autocomplete-hidden'); - let $clearBtn = $widget.find('.autocomplete-clear'); - let relatedUrl = $input.data('related-url'); - let placeholder = $input.attr('placeholder'); - - // Initialize Select2 - $input.select2({ - ajax: { - url: relatedUrl, - dataType: 'json', - delay: 250, - data: function (params) { - return { - term: params.term, - page: params.page || 1 - }; - }, - processResults: function (data, params) { - params.page = params.page || 1; - return { - results: data.results.map(function (item) { - return { - id: item.id, - text: item.text - }; - }), - pagination: { - more: data.pagination && data.pagination.more - } - }; - }, - cache: true - }, - placeholder: placeholder, - allowClear: true, - minimumInputLength: 1, - width: '250px' - }); - - // Handle selection - $input.on('select2:select', function (e) { - let data = e.params.data; - $hiddenInput.val(data.id); - updateUrl(); - }); - - // Handle clearing - $input.on('select2:clear', function (e) { - $hiddenInput.val(''); - updateUrl(); - }); - - // Clear button functionality - $clearBtn.on('click', function (e) { - e.preventDefault(); - $input.val(null).trigger('change'); - $hiddenInput.val(''); - updateUrl(); - }); - - function updateUrl() { - let currentUrl = new URL(window.location); - let lookupKwarg = $hiddenInput.data('lookup-kwarg'); - let value = $hiddenInput.val(); - - if (value) { - currentUrl.searchParams.set(lookupKwarg, value); - } else { - currentUrl.searchParams.delete(lookupKwarg); - } - - // Reset to first page when filtering - currentUrl.searchParams.delete('p'); - - window.location.href = currentUrl.toString(); - } - }); - }); -})(django.jQuery); diff --git a/core/templates/admin/autocomplete_filter.html b/core/templates/admin/autocomplete_filter.html deleted file mode 100644 index 780cdb5b..00000000 --- a/core/templates/admin/autocomplete_filter.html +++ /dev/null @@ -1,24 +0,0 @@ -{% load i18n %} -
-

{% trans "By" %} {{ field_verbose_name }}

-
- - - {% if lookup_val %} - {{ clear_text }} - {% endif %} -
-
\ No newline at end of file