2024-10-28 17:08:13 +00:00
|
|
|
from collections.abc import Collection
|
|
|
|
from typing import Any
|
|
|
|
|
2024-10-19 23:05:34 +00:00
|
|
|
from django.contrib.staticfiles.storage import staticfiles_storage
|
2024-10-28 17:08:13 +00:00
|
|
|
from django.db.models import Model, QuerySet
|
2024-10-19 23:05:34 +00:00
|
|
|
from django.forms import Select, SelectMultiple
|
2024-10-20 11:33:44 +00:00
|
|
|
from ninja import ModelSchema
|
2024-10-21 15:11:07 +00:00
|
|
|
from pydantic import TypeAdapter
|
2024-10-20 11:33:44 +00:00
|
|
|
|
2024-10-20 21:25:56 +00:00
|
|
|
from core.models import Group, SithFile, User
|
|
|
|
from core.schemas import GroupSchema, SithFileSchema, UserProfileSchema
|
2024-10-19 23:05:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
class AutoCompleteSelectMixin:
|
|
|
|
component_name = "autocomplete-select"
|
|
|
|
template_name = "core/widgets/autocomplete_select.jinja"
|
2024-10-28 17:08:13 +00:00
|
|
|
model: type[Model] | None = None
|
|
|
|
adapter: TypeAdapter[Collection[ModelSchema]] | None = None
|
2024-10-20 11:33:44 +00:00
|
|
|
pk = "id"
|
|
|
|
|
2024-10-20 11:40:59 +00:00
|
|
|
js = [
|
2024-11-18 14:36:05 +00:00
|
|
|
"bundled/core/components/ajax-select-index.ts",
|
2024-10-20 11:40:59 +00:00
|
|
|
]
|
|
|
|
css = [
|
2024-11-19 15:19:13 +00:00
|
|
|
"bundled/core/components/ajax-select-index.css",
|
2024-10-20 11:40:59 +00:00
|
|
|
"core/components/ajax-select.scss",
|
|
|
|
]
|
|
|
|
|
2024-10-28 17:08:13 +00:00
|
|
|
def get_queryset(self, pks: Collection[Any]) -> QuerySet:
|
|
|
|
return self.model.objects.filter(
|
|
|
|
**{
|
|
|
|
f"{self.pk}__in": [
|
|
|
|
pk
|
|
|
|
for pk in pks
|
|
|
|
if str(pk).isdigit() # We filter empty values for create views
|
|
|
|
]
|
|
|
|
}
|
|
|
|
).all()
|
|
|
|
|
2024-10-20 11:33:44 +00:00
|
|
|
def __init__(self, attrs=None, choices=()):
|
|
|
|
if self.is_ajax:
|
|
|
|
choices = () # Avoid computing anything when in ajax mode
|
|
|
|
super().__init__(attrs=attrs, choices=choices)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def is_ajax(self):
|
2024-10-28 17:08:13 +00:00
|
|
|
return self.adapter and self.model
|
2024-10-19 23:05:34 +00:00
|
|
|
|
|
|
|
def optgroups(self, name, value, attrs=None):
|
|
|
|
"""Don't create option groups when doing ajax"""
|
|
|
|
if self.is_ajax:
|
|
|
|
return []
|
|
|
|
return super().optgroups(name, value, attrs=attrs)
|
|
|
|
|
|
|
|
def get_context(self, name, value, attrs):
|
|
|
|
context = super().get_context(name, value, attrs)
|
2024-10-20 15:37:51 +00:00
|
|
|
context["widget"]["attrs"]["autocomplete"] = "off"
|
2024-10-19 23:05:34 +00:00
|
|
|
context["component"] = self.component_name
|
|
|
|
context["statics"] = {
|
2024-10-20 11:40:59 +00:00
|
|
|
"js": [staticfiles_storage.url(file) for file in self.js],
|
|
|
|
"css": [staticfiles_storage.url(file) for file in self.css],
|
2024-10-19 23:05:34 +00:00
|
|
|
}
|
2024-10-20 11:33:44 +00:00
|
|
|
if self.is_ajax:
|
2024-10-28 17:08:13 +00:00
|
|
|
context["initial"] = self.adapter.dump_json(
|
|
|
|
self.adapter.validate_python(
|
|
|
|
self.get_queryset(context["widget"]["value"])
|
2024-10-21 15:11:07 +00:00
|
|
|
)
|
|
|
|
).decode("utf-8")
|
2024-10-19 23:05:34 +00:00
|
|
|
return context
|
|
|
|
|
|
|
|
|
|
|
|
class AutoCompleteSelect(AutoCompleteSelectMixin, Select): ...
|
|
|
|
|
|
|
|
|
|
|
|
class AutoCompleteSelectMultiple(AutoCompleteSelectMixin, SelectMultiple): ...
|
|
|
|
|
|
|
|
|
2024-10-21 14:14:00 +00:00
|
|
|
class AutoCompleteSelectUser(AutoCompleteSelect):
|
2024-10-19 23:05:34 +00:00
|
|
|
component_name = "user-ajax-select"
|
2024-10-20 11:33:44 +00:00
|
|
|
model = User
|
2024-10-28 17:08:13 +00:00
|
|
|
adapter = TypeAdapter(list[UserProfileSchema])
|
2024-10-19 23:05:34 +00:00
|
|
|
|
|
|
|
|
2024-10-21 14:14:00 +00:00
|
|
|
class AutoCompleteSelectMultipleUser(AutoCompleteSelectMultiple):
|
2024-10-19 23:05:34 +00:00
|
|
|
component_name = "user-ajax-select"
|
2024-10-20 11:33:44 +00:00
|
|
|
model = User
|
2024-10-28 17:08:13 +00:00
|
|
|
adapter = TypeAdapter(list[UserProfileSchema])
|
2024-10-20 11:33:44 +00:00
|
|
|
|
|
|
|
|
2024-10-21 14:14:00 +00:00
|
|
|
class AutoCompleteSelectGroup(AutoCompleteSelect):
|
2024-10-20 11:33:44 +00:00
|
|
|
component_name = "group-ajax-select"
|
|
|
|
model = Group
|
2024-10-28 17:08:13 +00:00
|
|
|
adapter = TypeAdapter(list[GroupSchema])
|
2024-10-20 11:33:44 +00:00
|
|
|
|
|
|
|
|
2024-10-21 14:14:00 +00:00
|
|
|
class AutoCompleteSelectMultipleGroup(AutoCompleteSelectMultiple):
|
2024-10-20 11:33:44 +00:00
|
|
|
component_name = "group-ajax-select"
|
|
|
|
model = Group
|
2024-10-28 17:08:13 +00:00
|
|
|
adapter = TypeAdapter(list[GroupSchema])
|
2024-10-20 21:25:56 +00:00
|
|
|
|
|
|
|
|
2024-10-21 14:14:00 +00:00
|
|
|
class AutoCompleteSelectSithFile(AutoCompleteSelect):
|
2024-10-20 21:25:56 +00:00
|
|
|
component_name = "sith-file-ajax-select"
|
|
|
|
model = SithFile
|
2024-10-28 17:08:13 +00:00
|
|
|
adapter = TypeAdapter(list[SithFileSchema])
|
2024-10-20 21:25:56 +00:00
|
|
|
|
|
|
|
|
2024-10-21 14:14:00 +00:00
|
|
|
class AutoCompleteSelectMultipleSithFile(AutoCompleteSelectMultiple):
|
2024-10-20 21:25:56 +00:00
|
|
|
component_name = "sith-file-ajax-select"
|
|
|
|
model = SithFile
|
2024-10-28 17:08:13 +00:00
|
|
|
adapter = TypeAdapter(list[SithFileSchema])
|