mirror of
https://github.com/ae-utbm/sith.git
synced 2024-12-23 00:01:16 +00:00
331 lines
12 KiB
Django/Jinja
331 lines
12 KiB
Django/Jinja
{% macro user_profile_link(user) -%}
|
|
<a href="{{ url("core:user_profile", user_id=user.id) }}">{{ user.get_display_name() }}</a>
|
|
{%- endmacro %}
|
|
|
|
{% macro user_profile_link_short_name(user) -%}
|
|
<a href="{{ url("core:user_profile", user_id=user.id) }}">{{ user.get_short_name() }}</a>
|
|
{%- endmacro %}
|
|
|
|
{% macro user_link_with_pict(user) -%}
|
|
<a href="{{ url("core:user_profile", user_id=user.id) }}" class="mini_profile_link" >
|
|
{{ user.get_mini_item()|safe }}
|
|
</a>
|
|
{%- endmacro %}
|
|
|
|
{% macro link_news_logo(news) -%}
|
|
{% if news.club.logo -%}
|
|
{{ news.club.logo.url }}
|
|
{% else -%}
|
|
{{ static("com/img/news.png") }}
|
|
{% endif %}
|
|
{%- endmacro %}
|
|
|
|
{% macro gen_news_metatags(news) -%}
|
|
<meta name="twitter:card" content="summary" />
|
|
<meta name="twitter:site" content="{{ settings.SITH_TWITTER }}" />
|
|
<meta name="twitter:creator" content= "{{ settings.SITH_TWITTER }}" />
|
|
<meta property="og:url" content="{{ news.get_full_url() }}" />
|
|
<meta property="og:type" content="article" />
|
|
<meta property="og:title" content="{{ news.title }}" />
|
|
<meta property="og:description" content="{{ news.summary }}" />
|
|
<meta property="og:image" content="{{ "https://%s%s" % (settings.SITH_URL, link_news_logo(news)) }}" />
|
|
{%- endmacro %}
|
|
|
|
{% macro facebook_share(news) -%}
|
|
<a rel="nofollow" target="#" class="share_button facebook" href="https://www.facebook.com/sharer/sharer.php?u={{ news.get_full_url() }}">{% trans %}Share on Facebook{% endtrans %}</a>
|
|
{%- endmacro %}
|
|
|
|
{% macro tweet(news) -%}
|
|
<a rel="nofollow" target="#" class="share_button twitter" href="https://twitter.com/intent/tweet?text={{ news.get_full_url() }}">{% trans %}Tweet{% endtrans %}</a>
|
|
{%- endmacro %}
|
|
|
|
{% macro fb_quick(news) -%}
|
|
<a rel="nofollow" target="#" href="https://www.facebook.com/sharer/sharer.php?u={{ news.get_full_url() }}" class="fb fa-brands fa-facebook fa-2x"></a>
|
|
{%- endmacro %}
|
|
|
|
{% macro tweet_quick(news) -%}
|
|
<a rel="nofollow" target="#" href="https://twitter.com/intent/tweet?text={{ news.get_full_url() }}" class="twitter fa-brands fa-twitter-square fa-2x"></a>
|
|
{%- endmacro %}
|
|
|
|
{% macro user_mini_profile(user) %}
|
|
<div class="user_mini_profile">
|
|
<div class="user_mini_profile_infos">
|
|
<div class="user_mini_profile_infos_text">
|
|
<div class="user_mini_profile_name">{{ user.get_full_name() }}</div>
|
|
{% if user.nick_name %}
|
|
<div class="user_mini_profile_nick">« {{ user.nick_name }} »</div>
|
|
{% endif %}
|
|
{% if user.pronouns %}
|
|
<div class="user_mini_profile_pronouns">{{ user.pronouns }}</div>
|
|
{% endif %}
|
|
{% if user.date_of_birth %}
|
|
<div class="user_mini_profile_dob">
|
|
{{ user.date_of_birth|date("d/m/Y") }} ({{ user.get_age() }})
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% if user.promo and user.promo_has_logo() %}
|
|
<div class="user_mini_profile_promo">
|
|
<img
|
|
src="{{ static('core/img/promo_%02d.png' % user.promo) }}"
|
|
title="Promo {{ user.promo }}"
|
|
alt="Promo {{ user.promo }}"
|
|
class="promo_pict"
|
|
/>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="user_mini_profile_picture">
|
|
{% if user.profile_pict %}
|
|
<img src="{{ user.profile_pict.get_download_url() }}" alt="{% trans %}Profile{% endtrans %}" />
|
|
{% else %}
|
|
<img
|
|
src="{{ static('core/img/unknown.jpg') }}"
|
|
alt="{% trans %}Profile{% endtrans %}"
|
|
title="{% trans %}Profile{% endtrans %}"
|
|
/>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{%- endmacro %}
|
|
|
|
{% macro user_subscription(user) %}
|
|
{% trans subscription_end=user.subscriptions.order_by('subscription_end').last().subscription_end %}Subscribed until {{ subscription_end }}{% endtrans %}<br/>
|
|
{% trans %}Account number: {% endtrans %}{{ user.customer.account_id }}<br/>
|
|
{%- endmacro %}
|
|
|
|
{% macro show_slots(user) %}
|
|
{% if user.slots.filter(start_date__gte=timezone.now()).exists() %}
|
|
<h5>{% trans %}Slot{% endtrans %}</h5>
|
|
<ul>
|
|
{% for i in user.slots.filter(start_date__gte=timezone.now().replace(tzinfo=None)).all() %}
|
|
<li>{{ i.get_type_display() }} - {{i.machine.launderette }}, {{ i.start_date|date("l j") }} :
|
|
{{ i.start_date|time(DATETIME_FORMAT) }} |
|
|
<a href="{{ url('launderette:delete_slot', slot_id=i.id) }}">{% trans %}Delete{% endtrans %}</a></li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% endif %}
|
|
{% endmacro %}
|
|
|
|
{% macro show_tokens(user) %}
|
|
{% if user.tokens.exists() %}
|
|
<h5>{% trans %}Tokens{% endtrans %}</h5>
|
|
<ul>
|
|
{% for i in user.tokens.all() %}
|
|
<li>{{ i }}</li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% endif %}
|
|
{% endmacro %}
|
|
|
|
{% macro delete_godfather(user, profile, godfather, is_father) %}
|
|
{% if user == profile or user.is_root or user.is_board_member %}
|
|
<a class="delete" href="{{ url("core:user_godfathers_delete", user_id=profile.id, godfather_id=godfather.id, is_father=is_father) }}">{% trans %}Delete{% endtrans %}</a>
|
|
{% endif %}
|
|
{% endmacro %}
|
|
|
|
{% macro paginate_alpine(page, nb_pages) %}
|
|
{# Add pagination buttons for ajax based content with alpine
|
|
|
|
Notes:
|
|
This can only be used in the scope of your alpine datastore
|
|
|
|
Notes:
|
|
You might need to listen to the "popstate" event in your code
|
|
to update the current page you are on when the user goes back in
|
|
it's browser history with the back arrow
|
|
|
|
Parameters:
|
|
page (str): name of the alpine page variable in your datastore
|
|
nb_page (str): call to a javascript function or variable returning
|
|
the maximum number of pages to paginate
|
|
#}
|
|
<nav class="pagination" x-show="{{ nb_pages }} > 1">
|
|
{# Adding the prevent here is important, because otherwise,
|
|
clicking on the pagination buttons could submit the picture management form
|
|
and reload the page #}
|
|
<button
|
|
@click.prevent="{{ page }}--"
|
|
:disabled="{{ page }} <= 1"
|
|
@keyup.right.window="{{ page }} = Math.min({{ nb_pages }}, {{ page }} + 1)"
|
|
>
|
|
<i class="fa fa-caret-left"></i>
|
|
</button>
|
|
<template x-for="i in {{ nb_pages }}">
|
|
<button x-text="i" @click.prevent="{{ page }} = i" :class="{active: {{ page }} === i}"></button>
|
|
</template>
|
|
<button
|
|
@click.prevent="{{ page }}++"
|
|
:disabled="{{ page }} >= {{ nb_pages }}"
|
|
@keyup.left.window="{{ page }} = Math.max(1, {{ page }} - 1)"
|
|
>
|
|
<i class="fa fa-caret-right"></i>
|
|
</button>
|
|
</nav>
|
|
{% endmacro %}
|
|
|
|
{% macro paginate_jinja(current_page, paginator) %}
|
|
{# Add pagination buttons for pages without Alpine.
|
|
|
|
This must be coupled with a view that handles pagination
|
|
with the Django Paginator object.
|
|
|
|
Parameters:
|
|
current_page (django.core.paginator.Page): the current page object
|
|
paginator (django.core.paginator.Paginator): the paginator object
|
|
#}
|
|
{{ paginate_server_side(current_page, paginator, False) }}
|
|
{% endmacro %}
|
|
|
|
{% macro paginate_htmx(current_page, paginator) %}
|
|
{# Add pagination buttons for pages without Alpine but supporting fragments.
|
|
|
|
This must be coupled with a view that handles pagination
|
|
with the Django Paginator object and supports fragments.
|
|
|
|
The replaced fragment will be #content so make sure you are calling this macro inside your content block.
|
|
|
|
Parameters:
|
|
current_page (django.core.paginator.Page): the current page object
|
|
paginator (django.core.paginator.Paginator): the paginator object
|
|
#}
|
|
{{ paginate_server_side(current_page, paginator, True) }}
|
|
{% endmacro %}
|
|
|
|
{% macro paginate_server_side(current_page, paginator, use_htmx) %}
|
|
<nav class="pagination">
|
|
{% if current_page.has_previous() %}
|
|
<a
|
|
{% if use_htmx -%}
|
|
hx-get="?page={{ current_page.previous_page_number() }}"
|
|
hx-swap="innerHTML"
|
|
hx-target="#content"
|
|
hx-push-url="true"
|
|
{%- else -%}
|
|
href="?page={{ current_page.previous_page_number() }}"
|
|
{%- endif -%}
|
|
>
|
|
<button>
|
|
<i class="fa fa-caret-left"></i>
|
|
</button>
|
|
</a>
|
|
{% else %}
|
|
<button disabled="disabled"><i class="fa fa-caret-left"></i></button>
|
|
{% endif %}
|
|
{% for i in paginator.get_elided_page_range(current_page.number) %}
|
|
{% if i == current_page.number %}
|
|
<button class="active">{{ i }}</button>
|
|
{% elif i == paginator.ELLIPSIS %}
|
|
<strong>{{ paginator.ELLIPSIS }}</strong>
|
|
{% else %}
|
|
<a
|
|
{% if use_htmx -%}
|
|
hx-get="?page={{ i }}"
|
|
hx-swap="innerHTML"
|
|
hx-target="#content"
|
|
hx-push-url="true"
|
|
{%- else -%}
|
|
href="?page={{ i }}"
|
|
{%- endif -%}
|
|
>
|
|
<button>{{ i }}</button>
|
|
</a>
|
|
{% endif %}
|
|
{% endfor %}
|
|
{% if current_page.has_next() %}
|
|
<a
|
|
{% if use_htmx -%}
|
|
hx-get="?page={{ current_page.next_page_number() }}"
|
|
hx-swap="innerHTML"
|
|
hx-target="#content"
|
|
hx-push-url="true"
|
|
{%- else -%}
|
|
href="?page={{ current_page.next_page_number() }}"
|
|
{%- endif -%}
|
|
><button>
|
|
<i class="fa fa-caret-right"></i>
|
|
</button>
|
|
</a>
|
|
{% else %}
|
|
<button disabled="disabled"><i class="fa fa-caret-right"></i></button>
|
|
{% endif %}
|
|
</nav>
|
|
{% endmacro %}
|
|
|
|
{% macro select_all_checkbox(form_id) %}
|
|
<script type="text/javascript">
|
|
function checkbox_{{form_id}}(value) {
|
|
const inputs = document.getElementById("{{ form_id }}").getElementsByTagName("input");
|
|
for (let element of inputs){
|
|
if (element.type === "checkbox"){
|
|
element.checked = value;
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<button type="button" onclick="checkbox_{{form_id}}(true);">{% trans %}Select All{% endtrans %}</button>
|
|
<button type="button" onclick="checkbox_{{form_id}}(false);">{% trans %}Unselect All{% endtrans %}</button>
|
|
{% endmacro %}
|
|
|
|
{% macro tabs(tab_list, attrs = "") %}
|
|
{# Tab component
|
|
|
|
Parameters:
|
|
tab_list: list[tuple[str, str]] The list of tabs to display.
|
|
Each element of the list is a tuple which first element
|
|
is the title of the tab and the second element its content
|
|
attrs: str Additional attributes to put on the enclosing div
|
|
|
|
Example:
|
|
A basic usage would be as follow :
|
|
|
|
{{ tabs([("title 1", "content 1"), ("title 2", "content 2")]) }}
|
|
|
|
If you want to display more complex logic, you can define macros
|
|
and use those macros in parameters :
|
|
|
|
{{ tabs([("title", my_macro())]) }}
|
|
|
|
It's also possible to get and set the currently selected tab using Alpine.
|
|
Here, the title of the currently selected tab will be displayed.
|
|
Moreover, on page load, the tab will be opened on "tab 2".
|
|
|
|
<div x-data="{current_tab: 'tab 2'}">
|
|
<p x-text="current_tab"></p>
|
|
{{ tabs([("tab 1", "Hello"), ("tab 2", "World")], "x-model=current_tab") }}
|
|
</div>
|
|
|
|
If you want to have translated tab titles, you can enclose the macro call
|
|
in a with block :
|
|
|
|
{% with title=_("title"), content=_("Content") %}
|
|
{{ tabs([(tab1, content)]) }}
|
|
{% endwith %}
|
|
#}
|
|
<div
|
|
class="tabs shadow"
|
|
x-data="{selected: '{{ tab_list[0][0] }}'}"
|
|
x-modelable="selected"
|
|
{{ attrs }}
|
|
>
|
|
<div class="tab-headers">
|
|
{% for title, _ in tab_list %}
|
|
<button
|
|
class="tab-header clickable"
|
|
:class="{active: selected === '{{ title }}'}"
|
|
@click="selected = '{{ title }}'"
|
|
>
|
|
{{ title }}
|
|
</button>
|
|
{% endfor %}
|
|
</div>
|
|
<div class="tab-content">
|
|
{% for title, content in tab_list %}
|
|
<section x-show="selected === '{{ title }}'">
|
|
{{ content }}
|
|
</section>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endmacro %}
|