Merge branch 'aa-framework-part-2' into 'v4.x'

Alliance Auth Framework (Part 2)

See merge request allianceauth/allianceauth!1558
This commit is contained in:
Ariel Rin 2023-12-25 09:46:57 +00:00
commit b28b51916c
52 changed files with 614 additions and 179 deletions

View File

@ -14,15 +14,13 @@ Needs to be called with a context containing three objects:
{% block page_title %}Evelinks Examples{% endblock page_title %} {% block page_title %}Evelinks Examples{% endblock page_title %}
{% block content %} {% block content %}
<div>
{% include "framework/header/page-header.html" with title="Evelinks templatetags examples" %}
<div class="col-lg-12">
<h1 class="page-header text-center mb-3">Evelinks templatetags examples</h1>
<div class="col-lg-12 container"> <div class="col-lg-12 container">
<h2>profile URLs</h2> <h2>profile URLs</h2>
<div class="rows"> <div class="rows">
<div class="col-md-4"> <div class="col-md-4">
<h3>evewho</h3> <h3>evewho</h3>
<p><a href="{{ my_character|evewho_character_url }}">character from character object</a></p> <p><a href="{{ my_character|evewho_character_url }}">character from character object</a></p>
@ -57,7 +55,6 @@ Needs to be called with a context containing three objects:
<h2>image URLs</h2> <h2>image URLs</h2>
<div class="rows"> <div class="rows">
<div class="col-md-4"> <div class="col-md-4">
<p>character from ID: <img src="{{ my_character.character_id|character_portrait_url:128 }}"></p> <p>character from ID: <img src="{{ my_character.character_id|character_portrait_url:128 }}"></p>
<p>character from character object: <img src="{{ my_character|character_portrait_url:128 }}"></p> <p>character from character object: <img src="{{ my_character|character_portrait_url:128 }}"></p>
@ -77,5 +74,4 @@ Needs to be called with a context containing three objects:
</div> </div>
</div> </div>
</div> </div>
{% endblock content %} {% endblock content %}

View File

@ -0,0 +1,26 @@
"""
Migration to AA Framework API method
"""
from django.conf import settings
from django.db import migrations, models
import allianceauth.framework.api.user
class Migration(migrations.Migration):
dependencies = [
("fleetactivitytracking", "0006_auto_20180803_0430"),
]
operations = [
migrations.AlterField(
model_name="fatlink",
name="creator",
field=models.ForeignKey(
on_delete=models.SET(allianceauth.framework.api.user.get_sentinel_user),
to=settings.AUTH_USER_MODEL
),
),
]

View File

@ -3,10 +3,7 @@ from django.db import models
from django.utils import timezone from django.utils import timezone
from allianceauth.eveonline.models import EveCharacter from allianceauth.eveonline.models import EveCharacter
from allianceauth.framework.api.user import get_sentinel_user
def get_sentinel_user():
return User.objects.get_or_create(username='deleted')[0]
class Fatlink(models.Model): class Fatlink(models.Model):

View File

@ -12,9 +12,8 @@
{% block content %} {% block content %}
<div> <div>
<h1 class="page-header text-center mb-3"> {% translate "Character not found!" as page_header %}
{% translate "Character not found!" %} {% include "framework/header/page-header.html" with title=page_header %}
</h1>
<div class="col-lg-12 container"> <div class="col-lg-12 container">
<div class="row"> <div class="row">

View File

@ -13,9 +13,8 @@
{% block content %} {% block content %}
<div> <div>
<h1 class="page-header text-center mb-3"> {% translate "Create Fatlink" as page_header %}
{% translate "Create Fatlink" %} {% include "framework/header/page-header.html" with title=page_header %}
</h1>
<div> <div>
{% if badrequest %} {% if badrequest %}

View File

@ -14,15 +14,15 @@
<div> <div>
<h1 class="page-header text-center mb-3"> <h1 class="page-header text-center mb-3">
{% translate "Edit fatlink" %} "{{ fatlink }}" {% translate "Edit fatlink" %} "{{ fatlink }}"
</h1>
<div class="text-end"> <div class="text-end mb-3">
<form> <form>
<button type="submit" onclick="return confirm('{% translate "Are you sure?" %}')" class="btn btn-danger" name="deletefat" value="True"> <button type="submit" onclick="return confirm('{% translate "Are you sure?" %}')" class="btn btn-danger" name="deletefat" value="True">
{% translate "Delete fat" %} {% translate "Delete fat" %}
</button> </button>
</form> </form>
</div> </div>
</h1>
<div class="card card-default"> <div class="card card-default">
<div class="card-header"> <div class="card-header">

View File

@ -14,9 +14,10 @@
<div> <div>
<h1 class="page-header text-center mb-3"> <h1 class="page-header text-center mb-3">
{% blocktranslate %}Participation data statistics for {{ month }}, {{ year }}{% endblocktranslate %} {% blocktranslate %}Participation data statistics for {{ month }}, {{ year }}{% endblocktranslate %}
</h1>
{% if char_id %} {% if char_id %}
<div class="text-end"> <div class="text-end mb-3">
<a href="{% url 'fatlink:user_statistics_month' char_id previous_month|date:'Y' previous_month|date:'m' %}" class="btn btn-info"> <a href="{% url 'fatlink:user_statistics_month' char_id previous_month|date:'Y' previous_month|date:'m' %}" class="btn btn-info">
{% translate "Previous month" %} {% translate "Previous month" %}
</a> </a>
@ -25,9 +26,8 @@
</a> </a>
</div> </div>
{% endif %} {% endif %}
</h1>
<div class="card card-default mb-4"> <div class="card card-default mb-3">
<div class="card-header"> <div class="card-header">
<div class="card-title mb-0"> <div class="card-title mb-0">
{% blocktranslate count links=n_fats trimmed %} {% blocktranslate count links=n_fats trimmed %}

View File

@ -14,15 +14,15 @@
<div> <div>
<h1 class="page-header text-center mb-3"> <h1 class="page-header text-center mb-3">
{% blocktranslate %}Participation data statistics for {{ year }}{% endblocktranslate %} {% blocktranslate %}Participation data statistics for {{ year }}{% endblocktranslate %}
</h1>
<div class="text-end"> <div class="text-end mb-3">
<a href="{% url "fatlink:personal_statistics_year" previous_year %}" class="btn btn-info"><i class="fa-solid fa-chevron-left"></i> {% translate "Previous year" %}</a> <a href="{% url "fatlink:personal_statistics_year" previous_year %}" class="btn btn-info"><i class="fa-solid fa-chevron-left"></i> {% translate "Previous year" %}</a>
{% if next_year %} {% if next_year %}
<a href="{% url "fatlink:personal_statistics_year" next_year %}" class="btn btn-info">{% translate "Next year" %} <i class="fa-solid fa-chevron-right"></i></a> <a href="{% url "fatlink:personal_statistics_year" next_year %}" class="btn btn-info">{% translate "Next year" %} <i class="fa-solid fa-chevron-right"></i></a>
{% endif %} {% endif %}
</div> </div>
</h1>
<div class="col-lg-2 offset-lg-5"> <div class="col-lg-2 offset-lg-5">
<table class="table table-responsive"> <table class="table table-responsive">

View File

@ -11,18 +11,18 @@
{% endblock header_nav_brand %} {% endblock header_nav_brand %}
{% block content %} {% block content %}
<div class="col-lg-12"> <div>
<h1 class="page-header text-center mb-3"> <h1 class="page-header text-center mb-3">
{% blocktranslate %}Participation data statistics for {{ month }}, {{ year }}{% endblocktranslate %} {% blocktranslate %}Participation data statistics for {{ month }}, {{ year }}{% endblocktranslate %}
</h1>
<div class="text-end"> <div class="text-end mb-3">
<a href="{% url "fatlink:statistics_corp_month" corpid previous_month|date:"Y" previous_month|date:"m" %}" class="btn btn-info">{% translate "Previous month" %}</a> <a href="{% url "fatlink:statistics_corp_month" corpid previous_month|date:"Y" previous_month|date:"m" %}" class="btn btn-info">{% translate "Previous month" %}</a>
{% if next_month %} {% if next_month %}
<a href="{% url "fatlink:statistics_corp_month" corpid next_month|date:"Y" next_month|date:"m" %}" class="btn btn-info">{% translate "Next month" %}</a> <a href="{% url "fatlink:statistics_corp_month" corpid next_month|date:"Y" next_month|date:"m" %}" class="btn btn-info">{% translate "Next month" %}</a>
{% endif %} {% endif %}
</div> </div>
</h1>
{% if fatStats %} {% if fatStats %}
<div class="table-responsive"> <div class="table-responsive">

View File

@ -14,15 +14,15 @@
<div> <div>
<h1 class="page-header text-center mb-3"> <h1 class="page-header text-center mb-3">
{% blocktranslate %}Participation data statistics for {{ month }}, {{ year }}{% endblocktranslate %} {% blocktranslate %}Participation data statistics for {{ month }}, {{ year }}{% endblocktranslate %}
</h1>
<div class="text-end"> <div class="text-end mb-3">
<a href="{% url "fatlink:statistics_month" previous_month|date:"Y" previous_month|date:"m" %}" class="btn btn-info">{% translate "Previous month" %}</a> <a href="{% url "fatlink:statistics_month" previous_month|date:"Y" previous_month|date:"m" %}" class="btn btn-info">{% translate "Previous month" %}</a>
{% if next_month %} {% if next_month %}
<a href="{% url 'fatlink:statistics_month' next_month|date:"Y" next_month|date:"m" %}" class="btn btn-info">{% translate "Next month" %}</a> <a href="{% url 'fatlink:statistics_month' next_month|date:"Y" next_month|date:"m" %}" class="btn btn-info">{% translate "Next month" %}</a>
{% endif %} {% endif %}
</div> </div>
</h1>
{% if fatStats %} {% if fatStats %}
<div class="table-responsive"> <div class="table-responsive">

View File

@ -11,10 +11,9 @@
{% endblock header_nav_brand %} {% endblock header_nav_brand %}
{% block content %} {% block content %}
<div class="col-lg-12"> <div>
<h1 class="page-header text-center mb-3"> {% translate "Participation data" as page_header %}
{% translate "Participation data" %} {% include "framework/header/page-header.html" with title=page_header %}
</h1>
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-striped"> <table class="table table-striped">

View File

@ -0,0 +1,3 @@
"""
Alliance Auth Framework
"""

View File

@ -0,0 +1,64 @@
"""
Alliance Auth User API
"""
from typing import Optional
from django.contrib.auth.models import User
from allianceauth.eveonline.models import EveCharacter
def get_sentinel_user() -> User:
"""
Get the sentinel user or create one
:return:
"""
return User.objects.get_or_create(username="deleted")[0]
def get_main_character_from_user(user: User) -> Optional[EveCharacter]:
"""
Get the main character from a user
:param user:
:type user:
:return:
:rtype:
"""
if user is None:
return None
try:
main_character = user.profile.main_character
except AttributeError:
return None
return main_character
def get_main_character_name_from_user(user: User) -> str:
"""
Get the main character name from a user
:param user:
:type user:
:return:
:rtype:
"""
if user is None:
sentinel_user = get_sentinel_user()
return sentinel_user.username
main_character = get_main_character_from_user(user=user)
try:
username = main_character.character_name
except AttributeError:
return str(user)
return username

View File

@ -0,0 +1,14 @@
"""
Framework App Config
"""
from django.apps import AppConfig
class FrameworkConfig(AppConfig):
"""
Framework App Config
"""
name = "allianceauth.framework"
label = "framework"

View File

@ -0,0 +1,13 @@
{#Usage:#}
{# {% include "framework/header/page-header.html" with title="Foobar" subtitle="Barfoo" %}#}
{% if title %}
<h1 class="page-header text-center mb-3">
{{ title }}
{% if subtitle %}
<br>
<small>{{ subtitle }}</small>
{% endif %}
</h1>
{% endif %}

View File

@ -0,0 +1,3 @@
"""
Initializing our tests
"""

View File

@ -0,0 +1,179 @@
"""
Test sentinel user
"""
import re
# Django
from django.contrib.auth.models import User
from django.test import TestCase
# Alliance Auth
from allianceauth.framework.api.user import (
get_sentinel_user,
get_main_character_from_user,
get_main_character_name_from_user
)
from allianceauth.tests.auth_utils import AuthUtils
class TestSentinelUser(TestCase):
"""
Tests for the sentinel user
"""
def test_should_create_user_when_it_does_not_exist(self) -> None:
"""
Test should create a sentinel user when it doesn't exist
:return:
:rtype:
"""
# when
user = get_sentinel_user()
# then
self.assertEqual(first=user.username, second="deleted")
def test_should_return_user_when_it_does(self) -> None:
"""
Test should return sentinel user when it exists
:return:
:rtype:
"""
# given
User.objects.create_user(username="deleted")
# when
user = get_sentinel_user()
# then
self.assertEqual(first=user.username, second="deleted")
class TestGetMainForUser(TestCase):
"""
Tests for get_main_character_from_user
"""
@classmethod
def setUpClass(cls) -> None:
"""
Set up groups and users
"""
super().setUpClass()
cls.character_name = "William T. Riker"
cls.character_name_2 = "Christopher Pike"
cls.username = re.sub(pattern=r"[^\w\d@\.\+-]", repl="_", string=cls.character_name)
cls.username_2 = re.sub(
pattern=r"[^\w\d@\.\+-]", repl="_", string=cls.character_name_2
)
cls.user = AuthUtils.create_user(username=cls.username)
cls.user_without_main = AuthUtils.create_user(
username=cls.username_2, disconnect_signals=True
)
cls.character = AuthUtils.add_main_character_2(
user=cls.user, name=cls.character_name, character_id=1001
)
def test_get_main_character_from_user_should_return_character_name(self):
"""
Test should return the main character name for a regular user
:return:
:rtype:
"""
character = get_main_character_from_user(user=self.user)
self.assertEqual(first=character, second=self.character)
def test_get_main_character_from_user_should_return_none_for_no_main_character(self):
"""
Test should return None for User without a main character
:return:
:rtype:
"""
character = get_main_character_from_user(user=self.user_without_main)
self.assertIsNone(obj=character)
def test_get_main_character_from_user_should_none(self):
"""
Test should return None when user is None
:return:
:rtype:
"""
user = None
character = get_main_character_from_user(user=user)
self.assertIsNone(obj=character)
def test_get_main_character_name_from_user_should_return_character_name(self):
"""
Test should return the main character name for a regular user
:return:
:rtype:
"""
character_name = get_main_character_name_from_user(user=self.user)
self.assertEqual(first=character_name, second=self.character_name)
def test_get_main_character_name_from_user_should_return_user_name(self):
"""
Test should return just the username for a user without a main character
:return:
:rtype:
"""
character_name = get_main_character_name_from_user(user=self.user_without_main)
self.assertEqual(first=character_name, second=self.username_2)
def test_get_main_character_name_from_user_should_return_sentinel_user(self):
"""
Test should return "deleted" as username (Sentinel User)
:return:
:rtype:
"""
user = get_sentinel_user()
character_name = get_main_character_name_from_user(user=user)
self.assertEqual(first=character_name, second="deleted")
def test_get_main_character_name_from_user_should_return_sentinel_user_for_none(self):
"""
Test should return "deleted" (Sentinel User) if user is None
:return:
:rtype:
"""
user = None
character_name = get_main_character_name_from_user(user=user)
self.assertEqual(first=character_name, second="deleted")

View File

@ -12,9 +12,8 @@
{% block content %} {% block content %}
<div> <div>
<h1 class="page-header text-center mb-3"> {% translate "Choose a Corp" as page_header %}
{% translate "Choose a Corp" %} {% include "framework/header/page-header.html" with title=page_header %}
</h1>
{% if choices %} {% if choices %}
<div class="card card-primary"> <div class="card card-primary">

View File

@ -13,8 +13,10 @@
{% block content %} {% block content %}
<div> <div>
<h1 class="page-header text-center mb-3">{% translate "Personal Applications" %} {% translate "Personal Applications" as page_header %}
<div class="text-end"> {% include "framework/header/page-header.html" with title=page_header %}
<div class="text-end mb-3">
{% if create %} {% if create %}
<a href="{% url 'hrapplications:create_view' %}"> <a href="{% url 'hrapplications:create_view' %}">
<button type="button" class="btn btn-success">{% translate "Create Application" %}</button> <button type="button" class="btn btn-success">{% translate "Create Application" %}</button>
@ -23,7 +25,6 @@
<button type="button" class="btn btn-success" disabled>{% translate "Create Application" %}</button> <button type="button" class="btn btn-success" disabled>{% translate "Create Application" %}</button>
{% endif %} {% endif %}
</div> </div>
</h1>
{% if personal_apps %} {% if personal_apps %}
<div class="card card-default mb-3"> <div class="card card-default mb-3">
@ -68,16 +69,17 @@
{% endif %} {% endif %}
{% if perms.auth.human_resources %} {% if perms.auth.human_resources %}
<h1 class="page-header text-center mb-3">{% translate "Application Management" %} {% translate "Application Management" as page_header %}
<div class="text-end"> {% include "framework/header/page-header.html" with title=page_header %}
<div class="text-end mb-3">
<!-- Button trigger modal --> <!-- Button trigger modal -->
<button type="button" class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#modal-hr-search"> <button type="button" class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#modal-hr-search">
{% translate "Search Applications" %} {% translate "Search Applications" %}
</button> </button>
</div> </div>
</h1>
<div class="card card-default mt-4"> <div class="card card-default">
<div class="card-body clearfix"> <div class="card-body clearfix">
<ul class="nav nav-tabs" id="application-list" role="tablist"> <ul class="nav nav-tabs" id="application-list" role="tablist">
<li class="nav-item" role="presentation"> <li class="nav-item" role="presentation">

View File

@ -14,9 +14,8 @@
{% block content %} {% block content %}
<div> <div>
{% if perms.auth.human_resources %} {% if perms.auth.human_resources %}
<h1 class="page-header text-center mb-3"> {% translate "Application Search Results" as page_header %}
{% translate "Application Search Results" %} {% include "framework/header/page-header.html" with title=page_header %}
</h1>
<div class="text-end mb-3"> <div class="text-end mb-3">
<!-- Button trigger modal --> <!-- Button trigger modal -->

View File

@ -13,7 +13,8 @@
{% block content %} {% block content %}
<div> <div>
<h1 class="page-header text-center mb-3">{% translate "View Application" %}</h1> {% translate "View Application" as page_header %}
{% include "framework/header/page-header.html" with title=page_header %}
<div> <div>
{% if app.approved %} {% if app.approved %}

View File

@ -18,9 +18,8 @@
{% block content %} {% block content %}
<div> <div>
<h1 class="page-header text-center mb-3"> {% translate "Create Fleet Operation" as page_header %}
{% translate "Create Fleet Operation" %} {% include "framework/header/page-header.html" with title=page_header %}
</h1>
<div class="card card-primary border-0"> <div class="card card-primary border-0">
<div class="card-header"> <div class="card-header">

View File

@ -18,9 +18,8 @@
{% block content %} {% block content %}
<div> <div>
<h1 class="page-header text-center mb-3"> {% translate "Update Fleet Operation" as page_header %}
{% translate "Update Fleet Operation" %} {% include "framework/header/page-header.html" with title=page_header %}
</h1>
<div class="card card-primary border-0"> <div class="card card-primary border-0">
<div class="card-header"> <div class="card-header">

View File

@ -25,6 +25,7 @@ INSTALLED_APPS = [
'django_bootstrap5', # https://github.com/zostera/django-bootstrap5 'django_bootstrap5', # https://github.com/zostera/django-bootstrap5
'sortedm2m', 'sortedm2m',
'esi', 'esi',
'allianceauth.framework',
'allianceauth.authentication', 'allianceauth.authentication',
'allianceauth.services', 'allianceauth.services',
'allianceauth.eveonline', 'allianceauth.eveonline',

View File

@ -7,9 +7,8 @@
{% block content %} {% block content %}
<div class="col-lg-12"> <div class="col-lg-12">
<h1 class="page-header text-center mb-3"> {% translate "Verify TeamSpeak3 Identity" as page_header %}
{% translate "Verify TeamSpeak3 Identity" %} {% include "framework/header/page-header.html" with title=page_header %}
</h1>
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-4"> <div class="col-md-4">

View File

@ -11,7 +11,7 @@
{% endblock header_nav_brand %} {% endblock header_nav_brand %}
{% block content %} {% block content %}
<div class="col-lg-12"> <div>
<h1 class="page-header text-center mb-3"> <h1 class="page-header text-center mb-3">
{% blocktranslate with service_name=view.service_name|title %}{{ service_name }} Credentials{% endblocktranslate %} {% blocktranslate with service_name=view.service_name|title %}{{ service_name }} Credentials{% endblocktranslate %}
</h1> </h1>

View File

@ -17,9 +17,8 @@
{% block content %} {% block content %}
<div> <div>
<h1 class="page-header text-center mb-3"> {% translate "Create SRP Fleet" as page_header %}
{% translate "Create SRP Fleet" %} {% include "framework/header/page-header.html" with title=page_header %}
</h1>
<div class="card card-primary border-0"> <div class="card card-primary border-0">
<div class="card-header"> <div class="card-header">

View File

@ -13,10 +13,10 @@
{% block content %} {% block content %}
<div> <div>
<h1 class="page-header text-center mb-3"> {% translate "SRP Fleet Data" as page_header %}
{% translate "SRP Fleet Data" %} {% include "framework/header/page-header.html" with title=page_header %}
<div class="text-end"> <div class="text-end mb-3">
{% if perms.auth.srp_management %} {% if perms.auth.srp_management %}
{% if fleet_status == "Completed" %} {% if fleet_status == "Completed" %}
<a href="{% url 'srp:mark_uncompleted' fleet_id %}" class="btn btn-warning"> <a href="{% url 'srp:mark_uncompleted' fleet_id %}" class="btn btn-warning">
@ -29,7 +29,6 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
</div> </div>
</h1>
{% if srpfleetrequests %} {% if srpfleetrequests %}
<form method="POST"> <form method="POST">

View File

@ -13,9 +13,8 @@
{% block content %} {% block content %}
<div> <div>
<h1 class="page-header text-center mb-3"> {% translate "Create SRP Request" as page_header %}
{% translate "Create SRP Request" %} {% include "framework/header/page-header.html" with title=page_header %}
</h1>
<div class="card card-primary border-0"> <div class="card card-primary border-0">
<div class="card-header"> <div class="card-header">

View File

@ -13,9 +13,8 @@
{% block content %} {% block content %}
<div> <div>
<h1 class="page-header text-center mb-3"> {% translate "Update AAR Link" as page_header %}
{% translate "Update AAR Link" %} {% include "framework/header/page-header.html" with title=page_header %}
</h1>
<div class="card card-primary border-0"> <div class="card card-primary border-0">
<div class="card-header"> <div class="card-header">

View File

@ -5,8 +5,8 @@
{% endblock page_title %} {% endblock page_title %}
{% block content %} {% block content %}
<div class="col-lg-12"> <div>
<h1 class="page-header text-center mb-3">{{ error_title }}</h1> {% include "framework/header/page-header.html" with title=error_title %}
<div class="text-center"> <div class="text-center">
<svg <svg

View File

@ -1,3 +1,3 @@
{% load static %} {% load static %}
<link href="{% static 'allianceauth/css/auth-framework.css' %}" rel="stylesheet"> <link href="{% static 'allianceauth/framework/css/auth-framework.css' %}" rel="stylesheet">

View File

@ -15,9 +15,10 @@
<h1 class="page-header text-center mb-3"> <h1 class="page-header text-center mb-3">
{% block page_header %} {% block page_header %}
{% endblock page_header %} {% endblock page_header %}
{% include "timerboard/index_button.html" %}
</h1> </h1>
{% include "timerboard/index_button.html" %}
<div class="card card-primary border-0"> <div class="card card-primary border-0">
<div class="card-header"> <div class="card-header">
<div class="card-title mb-0"> <div class="card-title mb-0">

View File

@ -1,5 +1,5 @@
{% load i18n %} {% load i18n %}
<div class="text-end"> <div class="text-end mb-3">
<a href="{% url 'timerboard:view' %}" class="btn btn-secondary">{% translate "Back" %}</a> <a href="{% url 'timerboard:view' %}" class="btn btn-secondary">{% translate "Back" %}</a>
</div> </div>

View File

@ -12,13 +12,13 @@
{% block content %} {% block content %}
<div> <div>
<h1 class="page-header text-center mb-3"> {% translate "Delete Timer" as page_header %}
{% translate "Delete Timer" %} {% include "framework/header/page-header.html" with title=page_header %}
{% include "timerboard/index_button.html" %} {% include "timerboard/index_button.html" %}
</h1>
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-2"> <div class="col-md-4">
<div class="row"> <div class="row">
<form action="" method="post"> <form action="" method="post">
{% csrf_token %} {% csrf_token %}

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -0,0 +1,12 @@
# AA Framework
To establish a unified style language throughout Alliance Auth and Community Apps,
Alliance Auth is providing its own CSS framework with a couple of CSS classes.
:::{toctree}
:maxdepth: 1
framework/api
framework/css
framework/templates
:::

View File

@ -1,42 +0,0 @@
# CSS Framework
To establish a unified style language throughout Alliance Auth and Community Apps,
Alliance Auth is providing its own CSS framework with a couple of CSS classes.
## Callout-Boxes
These are similar to the Bootstrap alert/notification boxes, but not as "loud".
Callout-boxes need a base-class (`.aa-callout`) and a modifier-class (e.g.:
`.aa-callout-info` for an info-box). Modifier classes are available for the usual
Bootstrap alert levels "Success", "Info", "Warning" and "Danger".
![Alliance Auth Framework: Callout Boxes](/_static/images/development/css-framework/callout-boxes.png "Alliance Auth Framework: Callout Boxes")
### HTML
```html
<div class="aa-callout aa-callout-success">
<p>
This is a success callout-box.
</p>
</div>
<div class="aa-callout aa-callout-info">
<p>
This is an info callout-box.
</p>
</div>
<div class="aa-callout aa-callout-warning">
<p>
This is a warning callout-box.
</p>
</div>
<div class="aa-callout aa-callout-danger">
<p>
This is a danger callout-box.
</p>
</div>
```

View File

@ -0,0 +1,58 @@
# Alliance Auth Helper-Functions API
## User API
### get_main_character_from_user
This is to get the main character object (`EveCharacter`) of a user.
Given we have a `User` object called `my_user` and we want to get the main character:
```python
# Alliance Auth
from allianceauth.framework.api.user import get_main_character_from_user
main_character = get_main_character_from_user(user=my_user)
```
Now, `main_character` is an `EveCharacter` object, or `None` if the user has no main
character or the user is `None`.
### get_main_character_name_from_user
This is to get the name of the main character of a user.
Given we have a `User` object called `my_user` and we want to get the main character name:
```python
# Alliance Auth
from allianceauth.framework.api.user import get_main_character_name_from_user
main_character = get_main_character_name_from_user(user=my_user)
```
Now, `main_character` is a `string` containing the user's main character name.
If the user has no main character, the username will be returned. If the user is `None`,
the sentinel username (see [get_sentinel_user](#get-sentinel-user)) will be returned.
### get_sentinel_user
This function is useful in models when using `User` model-objects as foreign keys.
Django needs to know what should happen to those relations when the user is being
deleted. To keep the data, you can have Django map this to the sentinel user.
Import:
```python
# Alliance Auth
from allianceauth.framework.api.user import get_sentinel_user
```
And later in your model:
```python
creator = models.ForeignKey(
to=User,
on_delete=models.SET(get_sentinel_user),
)
```

View File

@ -0,0 +1,73 @@
# CSS Framework
To establish a unified style language throughout Alliance Auth and Community Apps,
Alliance Auth is providing its own CSS framework with a couple of CSS classes.
## Cursors
Our CSS framework provides different classes to manipulate the cursor, which are
missing in Bootstrap.
```{eval-rst}
+----------------------+--------------------------------------------------------+--------------------------------------------------------------------------------+
| CSS Class | Effect | Example |
+======================+========================================================+================================================================================+
| `cursor-default` | System default curser | .. image:: /_static/images/development/aa-framework/css/cursor-default.png |
+----------------------+--------------------------------------------------------+--------------------------------------------------------------------------------+
| `cursor-pointer` | Pointer, like it looks like for links and form buttons | .. image:: /_static/images/development/aa-framework/css/cursor-pointer.png |
+----------------------+--------------------------------------------------------+--------------------------------------------------------------------------------+
| `cursor-wait` | Wait animation | .. image:: /_static/images/development/aa-framework/css/cursor-wait.png |
+----------------------+--------------------------------------------------------+--------------------------------------------------------------------------------+
| `cursor-text` | Text selection cursor | .. image:: /_static/images/development/aa-framework/css/cursor-text.png |
+----------------------+--------------------------------------------------------+--------------------------------------------------------------------------------+
| `cursor-move` | 4-arrow-shaped cursor | .. image:: /_static/images/development/aa-framework/css/cursor-move.png |
+----------------------+--------------------------------------------------------+--------------------------------------------------------------------------------+
| `cursor-help` | Cursor with a little question mark | .. image:: /_static/images/development/aa-framework/css/cursor-help.png |
+----------------------+--------------------------------------------------------+--------------------------------------------------------------------------------+
| `cursor-not-allowed` | Not Allowed sign | .. image:: /_static/images/development/aa-framework/css/cursor-not-allowed.png |
+----------------------+--------------------------------------------------------+--------------------------------------------------------------------------------+
| `cursor-inherit` | Inherited from its parent element | |
+----------------------+--------------------------------------------------------+--------------------------------------------------------------------------------+
| `cursor-zoom-in` | Zoom in symbol | .. image:: /_static/images/development/aa-framework/css/cursor-zoom-in.png |
+----------------------+--------------------------------------------------------+--------------------------------------------------------------------------------+
| `cursor-zoom-out` | Zoom out symbol | .. image:: /_static/images/development/aa-framework/css/cursor-zoom-out.png |
+----------------------+--------------------------------------------------------+--------------------------------------------------------------------------------+
```
## Callout-Boxes
These are similar to the Bootstrap alert/notification boxes, but not as "loud".
Callout-boxes need a base-class (`.aa-callout`) and a modifier-class (e.g.:
`.aa-callout-info` for an info-box). Modifier classes are available for the usual
Bootstrap alert levels "Success", "Info", "Warning" and "Danger".
![Alliance Auth Framework: Callout Boxes](/_static/images/development/aa-framework/css/callout-boxes.png "Alliance Auth Framework: Callout Boxes")
### HTML
```html
<div class="aa-callout aa-callout-success">
<p>
This is a success callout-box.
</p>
</div>
<div class="aa-callout aa-callout-info">
<p>
This is an info callout-box.
</p>
</div>
<div class="aa-callout aa-callout-warning">
<p>
This is a warning callout-box.
</p>
</div>
<div class="aa-callout aa-callout-danger">
<p>
This is a danger callout-box.
</p>
</div>
```

View File

@ -0,0 +1,46 @@
# Templates
## Bundles
As bundles, we see templates that load essential CSS and JavaScript and are used
throughout Alliance Auth. These bundles can also be used in your own apps, so you don't
have to load specific CSS or JavaScript yourself.
These bundles include DataTables CSS and JS, jQuery Datepicker CSS and JS, jQueryUI CSS and JS, and more.
A full list of bundles we provide can be found here: https://gitlab.com/allianceauth/allianceauth/-/tree/master/allianceauth/templates/bundles
To use a bundle, you can use the following code in your template (Example for jQueryUI):
```django
{% block extra_css %}
{% include "bundles/jquery-ui-css.html" %}
{% endblock %}
{% block extra_javascript %}
{% include "bundles/jquery-ui-js.html" %}
{% endblock %}
```
## Template Partials
To ensure a unified style language throughout Alliance Auth and Community Apps,
we also provide a couple of template partials. This collection is bound to grow over
time, so best have an eye on this page.
### Page Header
On some pages you want to have a page header. To make this easier, we provide a template partial for this.
To use it, you can use the following code in your template:
```django
{% block content %}
<div>
{% translate "My Page Header" as page_header %}
{% include "framework/header/page-header.html" with title=page_header %}
<p>My page content</p>
</div>
{% endblock %}
```

View File

@ -9,5 +9,5 @@ integrating-services
menu-hooks menu-hooks
url-hooks url-hooks
logging logging
css-framework aa-framework
::: :::