mirror of
				https://github.com/ae-utbm/sith.git
				synced 2025-11-04 02:53:06 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			112 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			112 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from collections.abc import Collection
 | 
						|
from typing import Any
 | 
						|
 | 
						|
from django.contrib.staticfiles.storage import staticfiles_storage
 | 
						|
from django.db.models import Model, QuerySet
 | 
						|
from django.forms import Select, SelectMultiple
 | 
						|
from ninja import ModelSchema
 | 
						|
from pydantic import TypeAdapter
 | 
						|
 | 
						|
from core.models import Group, SithFile, User
 | 
						|
from core.schemas import GroupSchema, SithFileSchema, UserProfileSchema
 | 
						|
 | 
						|
 | 
						|
class AutoCompleteSelectMixin:
 | 
						|
    component_name = "autocomplete-select"
 | 
						|
    template_name = "core/widgets/autocomplete_select.jinja"
 | 
						|
    model: type[Model] | None = None
 | 
						|
    adapter: TypeAdapter[Collection[ModelSchema]] | None = None
 | 
						|
    pk = "id"
 | 
						|
 | 
						|
    js = [
 | 
						|
        "bundled/core/components/ajax-select-index.ts",
 | 
						|
    ]
 | 
						|
    css = [
 | 
						|
        "bundled/core/components/ajax-select-index.css",
 | 
						|
        "core/components/ajax-select.scss",
 | 
						|
    ]
 | 
						|
 | 
						|
    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()
 | 
						|
 | 
						|
    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):
 | 
						|
        return self.adapter and self.model
 | 
						|
 | 
						|
    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)
 | 
						|
        context["widget"]["attrs"]["autocomplete"] = "off"
 | 
						|
        context["component"] = self.component_name
 | 
						|
        context["statics"] = {
 | 
						|
            "js": [staticfiles_storage.url(file) for file in self.js],
 | 
						|
            "css": [staticfiles_storage.url(file) for file in self.css],
 | 
						|
        }
 | 
						|
        if self.is_ajax:
 | 
						|
            context["initial"] = self.adapter.dump_json(
 | 
						|
                self.adapter.validate_python(
 | 
						|
                    self.get_queryset(context["widget"]["value"])
 | 
						|
                )
 | 
						|
            ).decode("utf-8")
 | 
						|
        return context
 | 
						|
 | 
						|
 | 
						|
class AutoCompleteSelect(AutoCompleteSelectMixin, Select): ...
 | 
						|
 | 
						|
 | 
						|
class AutoCompleteSelectMultiple(AutoCompleteSelectMixin, SelectMultiple): ...
 | 
						|
 | 
						|
 | 
						|
class AutoCompleteSelectUser(AutoCompleteSelect):
 | 
						|
    component_name = "user-ajax-select"
 | 
						|
    model = User
 | 
						|
    adapter = TypeAdapter(list[UserProfileSchema])
 | 
						|
 | 
						|
 | 
						|
class AutoCompleteSelectMultipleUser(AutoCompleteSelectMultiple):
 | 
						|
    component_name = "user-ajax-select"
 | 
						|
    model = User
 | 
						|
    adapter = TypeAdapter(list[UserProfileSchema])
 | 
						|
 | 
						|
 | 
						|
class AutoCompleteSelectGroup(AutoCompleteSelect):
 | 
						|
    component_name = "group-ajax-select"
 | 
						|
    model = Group
 | 
						|
    adapter = TypeAdapter(list[GroupSchema])
 | 
						|
 | 
						|
 | 
						|
class AutoCompleteSelectMultipleGroup(AutoCompleteSelectMultiple):
 | 
						|
    component_name = "group-ajax-select"
 | 
						|
    model = Group
 | 
						|
    adapter = TypeAdapter(list[GroupSchema])
 | 
						|
 | 
						|
 | 
						|
class AutoCompleteSelectSithFile(AutoCompleteSelect):
 | 
						|
    component_name = "sith-file-ajax-select"
 | 
						|
    model = SithFile
 | 
						|
    adapter = TypeAdapter(list[SithFileSchema])
 | 
						|
 | 
						|
 | 
						|
class AutoCompleteSelectMultipleSithFile(AutoCompleteSelectMultiple):
 | 
						|
    component_name = "sith-file-ajax-select"
 | 
						|
    model = SithFile
 | 
						|
    adapter = TypeAdapter(list[SithFileSchema])
 |