mirror of
https://github.com/ae-utbm/sith.git
synced 2025-12-20 06:43:21 +00:00
@@ -1,3 +1,4 @@
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Annotated, Any
|
||||
|
||||
@@ -8,12 +9,12 @@ from django.urls import reverse
|
||||
from django.utils.text import slugify
|
||||
from django.utils.translation import gettext as _
|
||||
from haystack.query import SearchQuerySet
|
||||
from ninja import FilterSchema, ModelSchema, Schema, UploadedFile
|
||||
from pydantic import AliasChoices, Field
|
||||
from ninja import FilterLookup, FilterSchema, ModelSchema, Schema, UploadedFile
|
||||
from pydantic import AliasChoices, Field, field_validator
|
||||
from pydantic_core.core_schema import ValidationInfo
|
||||
|
||||
from core.models import Group, QuickUploadImage, SithFile, User
|
||||
from core.utils import is_image
|
||||
from core.utils import get_last_promo, is_image
|
||||
|
||||
NonEmptyStr = Annotated[str, MinLen(1)]
|
||||
|
||||
@@ -109,7 +110,11 @@ class GroupSchema(ModelSchema):
|
||||
|
||||
|
||||
class UserFilterSchema(FilterSchema):
|
||||
search: Annotated[str, MinLen(1)]
|
||||
search: Annotated[str, MinLen(1)] | None = None
|
||||
role: Annotated[str, FilterLookup("role__icontains")] | None = None
|
||||
department: str | None = None
|
||||
promo: int | None = None
|
||||
date_of_birth: datetime | None = None
|
||||
exclude: list[int] | None = Field(
|
||||
None, validation_alias=AliasChoices("exclude", "exclude[]")
|
||||
)
|
||||
@@ -138,6 +143,13 @@ class UserFilterSchema(FilterSchema):
|
||||
return Q()
|
||||
return ~Q(id__in=value)
|
||||
|
||||
@field_validator("promo", mode="after")
|
||||
@classmethod
|
||||
def validate_promo(cls, value: int) -> int:
|
||||
if not 0 < value <= get_last_promo():
|
||||
raise ValueError(f"{value} is not a valid promo")
|
||||
return value
|
||||
|
||||
|
||||
class MarkdownSchema(Schema):
|
||||
text: str
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import htmx from "htmx.org";
|
||||
|
||||
document.body.addEventListener("htmx:beforeRequest", (event) => {
|
||||
event.target.ariaBusy = true;
|
||||
event.detail.target.ariaBusy = true;
|
||||
});
|
||||
|
||||
document.body.addEventListener("htmx:afterRequest", (event) => {
|
||||
event.originalTarget.ariaBusy = null;
|
||||
document.body.addEventListener("htmx:beforeSwap", (event) => {
|
||||
event.detail.target.ariaBusy = null;
|
||||
});
|
||||
|
||||
Object.assign(window, { htmx });
|
||||
|
||||
@@ -143,6 +143,15 @@ form {
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
|
||||
.fields-centered {
|
||||
padding: 10px 10px 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--nf-input-size) 10px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.helptext {
|
||||
margin-top: .25rem;
|
||||
margin-bottom: .25rem;
|
||||
|
||||
@@ -114,15 +114,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-fields {
|
||||
padding: 10px 10px 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--nf-input-size) 10px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&-field {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<details name="navbar" class="menu">
|
||||
<summary class="head">{% trans %}Services{% endtrans %}</summary>
|
||||
<ul class="content">
|
||||
<li><a href="{{ url('matmat:search_clear') }}">{% trans %}Matmatronch{% endtrans %}</a></li>
|
||||
<li><a href="{{ url('matmat:search') }}">{% trans %}Matmatronch{% endtrans %}</a></li>
|
||||
<li><a href="{{ url('core:file_list') }}">{% trans %}Files{% endtrans %}</a></li>
|
||||
<li><a href="{{ url('pedagogy:guide') }}">{% trans %}Pedagogy{% endtrans %}</a></li>
|
||||
</ul>
|
||||
|
||||
@@ -151,12 +151,13 @@
|
||||
{% if current_page.has_previous() %}
|
||||
<a
|
||||
{% if use_htmx -%}
|
||||
hx-get="?page={{ current_page.previous_page_number() }}"
|
||||
hx-get="?{{ querystring(page=current_page.previous_page_number()) }}"
|
||||
hx-swap="innerHTML"
|
||||
hx-target="#content"
|
||||
hx-push-url="true"
|
||||
hx-trigger="click, keyup[key=='ArrowLeft'] from:body"
|
||||
{%- else -%}
|
||||
href="?page={{ current_page.previous_page_number() }}"
|
||||
href="?{{ querystring(page=current_page.previous_page_number()) }}"
|
||||
{%- endif -%}
|
||||
>
|
||||
<button>
|
||||
@@ -174,12 +175,12 @@
|
||||
{% else %}
|
||||
<a
|
||||
{% if use_htmx -%}
|
||||
hx-get="?page={{ i }}"
|
||||
hx-get="?{{ querystring(page=i) }}"
|
||||
hx-swap="innerHTML"
|
||||
hx-target="#content"
|
||||
hx-push-url="true"
|
||||
{%- else -%}
|
||||
href="?page={{ i }}"
|
||||
href="?{{ querystring(page=i) }}"
|
||||
{%- endif -%}
|
||||
>
|
||||
<button>{{ i }}</button>
|
||||
@@ -189,12 +190,13 @@
|
||||
{% if current_page.has_next() %}
|
||||
<a
|
||||
{% if use_htmx -%}
|
||||
hx-get="?page={{ current_page.next_page_number() }}"
|
||||
hx-get="?{{querystring(page=current_page.next_page_number())}}"
|
||||
hx-swap="innerHTML"
|
||||
hx-target="#content"
|
||||
hx-push-url="true"
|
||||
hx-trigger="click, keyup[key=='ArrowRight'] from:body"
|
||||
{%- else -%}
|
||||
href="?page={{ current_page.next_page_number() }}"
|
||||
href="?{{querystring(page=current_page.next_page_number())}}"
|
||||
{%- endif -%}
|
||||
><button>
|
||||
<i class="fa fa-caret-right"></i>
|
||||
@@ -243,3 +245,17 @@
|
||||
}"></div>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
{% macro querystring() %}
|
||||
{%- for key, values in request.GET.lists() -%}
|
||||
{%- if key not in kwargs -%}
|
||||
{%- for value in values -%}
|
||||
{{ key }}={{ value }}&
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- for key, value in kwargs.items() -%}
|
||||
{{ key }}={{ value }}&
|
||||
{%- endfor -%}
|
||||
{% endmacro %}
|
||||
@@ -114,7 +114,7 @@
|
||||
|
||||
|
||||
{# All fields #}
|
||||
<div class="profile-fields">
|
||||
<div class="fields-centered">
|
||||
{%- for field in form -%}
|
||||
{%- if field.name in ["quote","profile_pict","avatar_pict","scrub_pict","is_viewable","forum_signature"] -%}
|
||||
{%- continue -%}
|
||||
@@ -133,7 +133,7 @@
|
||||
</div>
|
||||
|
||||
{# Textareas #}
|
||||
<div class="profile-fields">
|
||||
<div class="fields-centered">
|
||||
{%- for field in [form.quote, form.forum_signature] -%}
|
||||
<div class="profile-field">
|
||||
{{ field.label_tag() }}
|
||||
|
||||
Reference in New Issue
Block a user