Skip to content

Commit

Permalink
[ADD] Doctrine dropdown to forms
Browse files Browse the repository at this point in the history
  • Loading branch information
ppfeufer committed Nov 7, 2024
1 parent 370d27e commit 6c60b02
Show file tree
Hide file tree
Showing 10 changed files with 253 additions and 94 deletions.
32 changes: 32 additions & 0 deletions afat/app_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import unidecode

# Django
from django.apps import apps
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _

Expand Down Expand Up @@ -37,3 +38,34 @@
)

AFAT_BASE_URL = slugify(unidecode.unidecode(AFAT_APP_NAME), allow_unicode=True)


def fittings_installed() -> bool:
"""
Check if the Fittings module is installed
:return:
:rtype:
"""

return apps.is_installed(app_name="fittings")


def use_fittings_module_for_doctrines() -> bool:
"""
Check if the Fittings module is used for doctrines
:return:
:rtype:
"""

# Alliance Auth AFAT
from afat.models import ( # pylint: disable=import-outside-toplevel, cyclic-import
Setting,
)

return (
fittings_installed() is True
and Setting.get_setting(Setting.Field.USE_DOCTRINES_FROM_FITTINGS_MODULE)
is True
)
39 changes: 37 additions & 2 deletions afat/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@

# Alliance Auth AFAT
from afat.app_settings import AFAT_DEFAULT_FATLINK_EXPIRY_TIME
from afat.helper.fatlinks import get_doctrines
from afat.models import Doctrine, FleetType, Setting

# The first line dropdown is blank
# Usage example: dropdown = form_choices_blank + [(o.id, o.name) for o in objects]
form_choices_blank = [("", "---------")]


def get_mandatory_form_label_text(text):
"""
Expand Down Expand Up @@ -48,8 +53,23 @@ class AFatEsiFatForm(forms.Form):
required=False,
label=_("Fleet type (optional)"),
queryset=FleetType.objects.filter(is_enabled=True),
# empty_label=_("Please select a fleet type"),
)
doctrine_esi = forms.ChoiceField(
required=False,
label=_("Doctrine (optional)"),
choices=(),
)

def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request", None)
super().__init__(*args, **kwargs)

# Due to the dynamic nature of this dropdown field, we need to initialize it here.
# This is a workaround to avoid settings being cached and not updated when changed.
# This is also the reason we cannot use a ModelChoiceField here.
self.fields["doctrine_esi"].choices = form_choices_blank + [
(str(o), str(o)) for o in get_doctrines()
]


class AFatManualFatForm(forms.Form):
Expand Down Expand Up @@ -90,7 +110,11 @@ class AFatClickFatForm(forms.Form):
required=False,
label=_("Fleet type (optional)"),
queryset=FleetType.objects.filter(is_enabled=True),
# empty_label=_("Please select a fleet type"),
)
doctrine = forms.ChoiceField(
required=False,
label=_("Doctrine (optional)"),
choices=(),
)
duration = forms.IntegerField(
required=True,
Expand All @@ -100,6 +124,17 @@ class AFatClickFatForm(forms.Form):
widget=forms.TextInput(attrs={"placeholder": _("Expiry time in minutes")}),
)

def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request", None)
super().__init__(*args, **kwargs)

# Due to the dynamic nature of this dropdown field, we need to initialize it here.
# This is a workaround to avoid settings being cached and not updated when changed.
# This is also the reason we cannot use a ModelChoiceField here.
self.fields["doctrine"].choices = form_choices_blank + [
(str(o), str(o)) for o in get_doctrines()
]


class FatLinkEditForm(forms.Form):
"""
Expand Down
48 changes: 48 additions & 0 deletions afat/helper/fatlinks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@
Helper functions for fat links view
"""

# Django
from django.db.models import Prefetch

# Alliance Auth
from allianceauth.authentication.admin import User

# Alliance Auth AFAT
from afat.app_settings import use_fittings_module_for_doctrines
from afat.models import FatLink


Expand Down Expand Up @@ -39,3 +43,47 @@ def get_esi_fleet_information_by_user(
"has_open_esi_fleets": has_open_esi_fleets,
"open_esi_fleets_list": open_esi_fleets_list,
}


def get_doctrines() -> list[dict[int, str]]:
"""
Get all enabled doctrines
:return:
:rtype:
"""

if use_fittings_module_for_doctrines() is True:
# Third Party
from fittings.models import ( # pylint: disable=import-outside-toplevel
Doctrine,
Fitting,
)

cls = Doctrine.objects

doctrines = (
cls.prefetch_related("category")
.prefetch_related(
Prefetch(
lookup="fittings",
queryset=Fitting.objects.select_related("ship_type"),
)
)
.union(
cls.prefetch_related("category").prefetch_related(
Prefetch(
lookup="fittings",
queryset=Fitting.objects.select_related("ship_type"),
)
)
)
.order_by("name")
)
else:
# Alliance Auth AFAT
from afat.models import Doctrine # pylint: disable=import-outside-toplevel

doctrines = Doctrine.objects.filter(is_enabled=True).distinct().order_by("name")

return doctrines
45 changes: 0 additions & 45 deletions afat/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,48 +56,3 @@ def select_related_default(self):
"""

return self.select_related("fatlink", "fatlink__link_type", "character")


class SettingQuerySet(models.QuerySet):
"""
SettingQuerySet
"""

def delete(self):
"""
Delete action
Override: We don't allow deletion here, so we make sure the object
is saved again and not deleted
:return:
"""

return super().update()


class SettingManager(models.Manager):
"""
SettingManager
"""

def get_setting(self, setting_key: str) -> str:
"""
Get a setting
:param setting_key:
:type setting_key:
:return:
:rtype:
"""

return getattr(self.first(), setting_key)

def get_queryset(self):
"""
Get the queryset
:return:
:rtype:
"""

return SettingQuerySet(self.model)
13 changes: 2 additions & 11 deletions afat/migrations/0024_doctrines_and_settings.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 4.2.16 on 2024-11-07 19:43
# Generated by Django 4.2.16 on 2024-11-07 22:30

# Django
from django.db import migrations, models
Expand Down Expand Up @@ -32,20 +32,11 @@ class Migration(migrations.Migration):
verbose_name="Name",
),
),
(
"link",
models.CharField(
blank=True,
help_text="A link to a doctrine page for this doctrine if you have.",
max_length=255,
verbose_name="Doctrine link",
),
),
(
"notes",
models.TextField(
blank=True,
help_text="You can add notes about this doctrine here if you want. (Optional)",
help_text="You can add notes about this doctrine here if you want. (optional)",
null=True,
verbose_name="Notes",
),
Expand Down
52 changes: 16 additions & 36 deletions afat/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@

# Django
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.core.validators import URLValidator
from django.core.exceptions import ObjectDoesNotExist
from django.db import models, transaction
from django.utils import timezone
from django.utils.crypto import get_random_string
Expand All @@ -18,7 +17,7 @@
from allianceauth.eveonline.models import EveCharacter

# Alliance Auth AFAT
from afat.managers import FatLinkManager, FatManager, SettingManager
from afat.managers import FatLinkManager, FatManager


def get_sentinel_user() -> User:
Expand Down Expand Up @@ -389,20 +388,12 @@ class Doctrine(models.Model):
verbose_name=_("Name"),
)

# Link to your doctrine
link = models.CharField(
max_length=255,
blank=True,
help_text=_("A link to a doctrine page for this doctrine if you have."),
verbose_name=_("Doctrine link"),
)

# Doctrine notes
notes = models.TextField(
null=True,
blank=True,
help_text=_(
"You can add notes about this doctrine here if you want. (Optional)"
"You can add notes about this doctrine here if you want. (optional)"
),
verbose_name=_("Notes"),
)
Expand All @@ -415,28 +406,6 @@ class Doctrine(models.Model):
verbose_name=_("Is enabled"),
)

def clean(self):
"""
Check if the doctrine link is valid
:return:
:rtype:
"""

doctrine_link = self.link

if doctrine_link != "":
validate = URLValidator()

try:
validate(doctrine_link)
except ValidationError as exception:
raise ValidationError(
message=_("Your doctrine URL is not valid.")
) from exception

super().clean()

def __str__(self) -> str:
"""
String representation of the object
Expand Down Expand Up @@ -481,8 +450,6 @@ class Field(models.TextChoices):
verbose_name=Field.USE_DOCTRINES_FROM_FITTINGS_MODULE.label, # pylint: disable=no-member
)

objects = SettingManager()

class Meta: # pylint: disable=too-few-public-methods
"""
Setting :: Meta
Expand All @@ -501,3 +468,16 @@ def __str__(self) -> str:
"""

return str(_("AFAT Settings"))

@staticmethod
def get_setting(setting_key: str):
"""
Get the settings
:return:
:rtype:
"""

return Setting.get_solo().__getattribute__( # pylint: disable=unnecessary-dunder-call
setting_key
)
2 changes: 2 additions & 0 deletions afat/templates/afat/partials/fatlinks/add/clickable-link.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
{% bootstrap_field manual_fatlink_form.type %}
{% endif %}

{% bootstrap_field manual_fatlink_form.doctrine %}

{% bootstrap_field manual_fatlink_form.duration %}

{% include "afat/partials/form/required-field-hint.html" %}
Expand Down
2 changes: 2 additions & 0 deletions afat/templates/afat/partials/fatlinks/add/esi-link.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
{% bootstrap_field esi_fatlink_form.type_esi %}
{% endif %}

{% bootstrap_field esi_fatlink_form.doctrine_esi %}

{% include "afat/partials/form/required-field-hint.html" %}

<div class="form-group text-end">
Expand Down
Loading

0 comments on commit 6c60b02

Please sign in to comment.