mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2026-02-04 14:16:21 +01:00
Compare commits
151 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42ee06470c | ||
|
|
69aaa9652f | ||
|
|
1ccfff50e5 | ||
|
|
57a39557fd | ||
|
|
c36dea08e3 | ||
|
|
d3acd821b7 | ||
|
|
0a17427169 | ||
|
|
ce8935e621 | ||
|
|
efff946a56 | ||
|
|
bd17b95cac | ||
|
|
4ed1c5b7c4 | ||
|
|
271fd8e8c4 | ||
|
|
9b4321281a | ||
|
|
052c35c8e5 | ||
|
|
0fcb517b0b | ||
|
|
dcfddf0add | ||
|
|
4a4258d0e6 | ||
|
|
dd15a221aa | ||
|
|
737e02293a | ||
|
|
c34efebacf | ||
|
|
4602097399 | ||
|
|
7051e06564 | ||
|
|
9767ce79d8 | ||
|
|
0c090f1486 | ||
|
|
618ee81f9b | ||
|
|
98efb9f887 | ||
|
|
cbe6c821cc | ||
|
|
de9d2b39a6 | ||
|
|
0d5f22288b | ||
|
|
e0d76dc268 | ||
|
|
ecc9e68330 | ||
|
|
710149ec21 | ||
|
|
3c2c137dad | ||
|
|
a8271c4189 | ||
|
|
3315ae7778 | ||
|
|
d2f048f8fe | ||
|
|
0fe2855faa | ||
|
|
79a1fa3d7c | ||
|
|
96fe88d5c7 | ||
|
|
59391ad3c5 | ||
|
|
94e9c08422 | ||
|
|
acff3695bc | ||
|
|
43ec8514aa | ||
|
|
4c629b193f | ||
|
|
c651da4011 | ||
|
|
da382cffd1 | ||
|
|
4ecfc3afd8 | ||
|
|
4eb7dbbe62 | ||
|
|
c96ba65296 | ||
|
|
ff2f60f7f3 | ||
|
|
3000545c98 | ||
|
|
f3ad092ef2 | ||
|
|
a012e7df2f | ||
|
|
1fa77412c0 | ||
|
|
e56caeb22b | ||
|
|
ceb07ebc67 | ||
|
|
237075d45c | ||
|
|
7099b1946d | ||
|
|
e416ab8ff2 | ||
|
|
2802ed03a5 | ||
|
|
4af73c76fe | ||
|
|
b6149979aa | ||
|
|
cb20288427 | ||
|
|
db6f4c91dc | ||
|
|
57ac7a5277 | ||
|
|
136438f9c2 | ||
|
|
e2be8b3440 | ||
|
|
04f3473ef3 | ||
|
|
255cb0da8d | ||
|
|
069352fb0f | ||
|
|
66e8ddb684 | ||
|
|
179c26975c | ||
|
|
e17f6e799b | ||
|
|
7cd8294104 | ||
|
|
ede5540335 | ||
|
|
747279b773 | ||
|
|
44f8b1c477 | ||
|
|
7c6ebd9bf6 | ||
|
|
430469b708 | ||
|
|
efbb3cee31 | ||
|
|
21094ed4dd | ||
|
|
5f326efc7e | ||
|
|
b6e34ace35 | ||
|
|
fe4a8965e3 | ||
|
|
23371c233d | ||
|
|
7a3bbf0d7f | ||
|
|
89a1bec9c1 | ||
|
|
1c1e70619a | ||
|
|
0ff4374efa | ||
|
|
18d0e58a48 | ||
|
|
84f44338dc | ||
|
|
2ba0412890 | ||
|
|
2326522b29 | ||
|
|
a7cb6ee434 | ||
|
|
2aeef63565 | ||
|
|
3c9e7335ef | ||
|
|
49067de325 | ||
|
|
471e7e29ae | ||
|
|
3ec5775406 | ||
|
|
e804d2b60d | ||
|
|
742438a95d | ||
|
|
5c60086baa | ||
|
|
e49041bb14 | ||
|
|
f3cbe91883 | ||
|
|
ea439a2176 | ||
|
|
56e1e76f11 | ||
|
|
634e7357be | ||
|
|
08dc88da1a | ||
|
|
3d206e445c | ||
|
|
64686cdad1 | ||
|
|
d7fe09bdf1 | ||
|
|
6da50da92f | ||
|
|
51e4dd986f | ||
|
|
bee6522182 | ||
|
|
1711a9dd33 | ||
|
|
3914626379 | ||
|
|
df276cb32d | ||
|
|
daad7d8b10 | ||
|
|
3bf5bc0fe3 | ||
|
|
96abae553a | ||
|
|
f9cbfb1562 | ||
|
|
8eaa94e179 | ||
|
|
4f876b648b | ||
|
|
cd738137c0 | ||
|
|
5605eb129d | ||
|
|
87ef0f21a3 | ||
|
|
a1c7ce827e | ||
|
|
97466bcdfb | ||
|
|
ff3096b106 | ||
|
|
98f0d77f3f | ||
|
|
92548ba402 | ||
|
|
c46741d311 | ||
|
|
7c7c1abf7c | ||
|
|
fc303b1b0a | ||
|
|
4e220a9679 | ||
|
|
b17b1f7504 | ||
|
|
7081fc0e76 | ||
|
|
68e4574f19 | ||
|
|
e6e0a70012 | ||
|
|
13e38da942 | ||
|
|
468c1de26b | ||
|
|
22ef5ac0e5 | ||
|
|
ef2dc08958 | ||
|
|
6b84ffa16c | ||
|
|
d7a1096413 | ||
|
|
93b94a8bc2 | ||
|
|
9a95716105 | ||
|
|
dbfcf5d87a | ||
|
|
105d7d53b3 | ||
|
|
01cefe1457 | ||
|
|
7fe3db8017 |
@@ -25,7 +25,7 @@ before_script:
|
||||
pre-commit-check:
|
||||
<<: *only-default
|
||||
stage: pre-commit
|
||||
image: python:3.11-bullseye
|
||||
image: python:3.11-bookworm
|
||||
# variables:
|
||||
# PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit
|
||||
# cache:
|
||||
@@ -53,7 +53,7 @@ secret_detection:
|
||||
|
||||
test-3.8-core:
|
||||
<<: *only-default
|
||||
image: python:3.8-bullseye
|
||||
image: python:3.8-bookworm
|
||||
script:
|
||||
- tox -e py38-core
|
||||
artifacts:
|
||||
@@ -65,7 +65,7 @@ test-3.8-core:
|
||||
|
||||
test-3.9-core:
|
||||
<<: *only-default
|
||||
image: python:3.9-bullseye
|
||||
image: python:3.9-bookworm
|
||||
script:
|
||||
- tox -e py39-core
|
||||
artifacts:
|
||||
@@ -77,7 +77,7 @@ test-3.9-core:
|
||||
|
||||
test-3.10-core:
|
||||
<<: *only-default
|
||||
image: python:3.10-bullseye
|
||||
image: python:3.10-bookworm
|
||||
script:
|
||||
- tox -e py310-core
|
||||
artifacts:
|
||||
@@ -89,7 +89,7 @@ test-3.10-core:
|
||||
|
||||
test-3.11-core:
|
||||
<<: *only-default
|
||||
image: python:3.11-bullseye
|
||||
image: python:3.11-bookworm
|
||||
script:
|
||||
- tox -e py311-core
|
||||
artifacts:
|
||||
@@ -101,7 +101,7 @@ test-3.11-core:
|
||||
|
||||
test-3.12-core:
|
||||
<<: *only-default
|
||||
image: python:3.12-rc-bullseye
|
||||
image: python:3.12-bookworm
|
||||
script:
|
||||
- tox -e py312-core
|
||||
artifacts:
|
||||
@@ -113,7 +113,7 @@ test-3.12-core:
|
||||
|
||||
test-3.8-all:
|
||||
<<: *only-default
|
||||
image: python:3.8-bullseye
|
||||
image: python:3.8-bookworm
|
||||
script:
|
||||
- tox -e py38-all
|
||||
artifacts:
|
||||
@@ -125,7 +125,7 @@ test-3.8-all:
|
||||
|
||||
test-3.9-all:
|
||||
<<: *only-default
|
||||
image: python:3.9-bullseye
|
||||
image: python:3.9-bookworm
|
||||
script:
|
||||
- tox -e py39-all
|
||||
artifacts:
|
||||
@@ -137,7 +137,7 @@ test-3.9-all:
|
||||
|
||||
test-3.10-all:
|
||||
<<: *only-default
|
||||
image: python:3.10-bullseye
|
||||
image: python:3.10-bookworm
|
||||
script:
|
||||
- tox -e py310-all
|
||||
artifacts:
|
||||
@@ -149,7 +149,7 @@ test-3.10-all:
|
||||
|
||||
test-3.11-all:
|
||||
<<: *only-default
|
||||
image: python:3.11-bullseye
|
||||
image: python:3.11-bookworm
|
||||
script:
|
||||
- tox -e py311-all
|
||||
artifacts:
|
||||
@@ -162,7 +162,7 @@ test-3.11-all:
|
||||
|
||||
test-3.12-all:
|
||||
<<: *only-default
|
||||
image: python:3.12-rc-bullseye
|
||||
image: python:3.12-bookworm
|
||||
script:
|
||||
- tox -e py312-all
|
||||
artifacts:
|
||||
@@ -174,7 +174,7 @@ test-3.12-all:
|
||||
|
||||
build-test:
|
||||
stage: test
|
||||
image: python:3.11-bullseye
|
||||
image: python:3.11-bookworm
|
||||
|
||||
before_script:
|
||||
- python -m pip install --upgrade pip
|
||||
@@ -193,13 +193,13 @@ build-test:
|
||||
|
||||
test-docs:
|
||||
<<: *only-default
|
||||
image: python:3.11-bullseye
|
||||
image: python:3.11-bookworm
|
||||
script:
|
||||
- tox -e docs
|
||||
|
||||
deploy_production:
|
||||
stage: deploy
|
||||
image: python:3.11-bullseye
|
||||
image: python:3.11-bookworm
|
||||
|
||||
before_script:
|
||||
- python -m pip install --upgrade pip
|
||||
|
||||
@@ -4,8 +4,21 @@
|
||||
# pre-commit autoupdate
|
||||
|
||||
repos:
|
||||
# Code Upgrades
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v3.15.2
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py38-plus]
|
||||
- repo: https://github.com/adamchainz/django-upgrade
|
||||
rev: 1.17.0
|
||||
hooks:
|
||||
- id: django-upgrade
|
||||
args: [--target-version=4.2]
|
||||
|
||||
# Formatting
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.4.0
|
||||
rev: v4.6.0
|
||||
hooks:
|
||||
# Identify invalid files
|
||||
- id: check-ast
|
||||
@@ -13,27 +26,24 @@ repos:
|
||||
- id: check-json
|
||||
- id: check-toml
|
||||
- id: check-xml
|
||||
|
||||
# git checks
|
||||
- id: check-merge-conflict
|
||||
- id: check-added-large-files
|
||||
args: [ --maxkb=1000 ]
|
||||
args: [--maxkb=1000]
|
||||
- id: detect-private-key
|
||||
- id: check-case-conflict
|
||||
|
||||
# Python checks
|
||||
# - id: check-docstring-first
|
||||
# - id: check-docstring-first
|
||||
- id: debug-statements
|
||||
# - id: requirements-txt-fixer
|
||||
# - id: requirements-txt-fixer
|
||||
- id: fix-encoding-pragma
|
||||
args: [ --remove ]
|
||||
args: [--remove]
|
||||
- id: fix-byte-order-marker
|
||||
|
||||
# General quality checks
|
||||
- id: mixed-line-ending
|
||||
args: [ --fix=lf ]
|
||||
args: [--fix=lf]
|
||||
- id: trailing-whitespace
|
||||
args: [ --markdown-linebreak-ext=md ]
|
||||
args: [--markdown-linebreak-ext=md]
|
||||
exclude: |
|
||||
(?x)(
|
||||
\.min\.css|
|
||||
@@ -52,9 +62,8 @@ repos:
|
||||
\.mo|
|
||||
swagger\.json
|
||||
)
|
||||
|
||||
- repo: https://github.com/editorconfig-checker/editorconfig-checker.python
|
||||
rev: 2.7.2
|
||||
rev: 2.7.3
|
||||
hooks:
|
||||
- id: editorconfig-checker
|
||||
exclude: |
|
||||
@@ -65,21 +74,26 @@ repos:
|
||||
\.mo|
|
||||
swagger\.json
|
||||
)
|
||||
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v3.10.1
|
||||
- repo: https://github.com/igorshubovych/markdownlint-cli
|
||||
rev: v0.41.0
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [ --py38-plus ]
|
||||
|
||||
- repo: https://github.com/adamchainz/django-upgrade
|
||||
rev: 1.14.0
|
||||
- id: markdownlint
|
||||
args:
|
||||
- --disable=MD013
|
||||
# Infrastructure
|
||||
- repo: https://github.com/tox-dev/pyproject-fmt
|
||||
rev: 2.1.3
|
||||
hooks:
|
||||
- id: django-upgrade
|
||||
args: [--target-version=4.2]
|
||||
|
||||
- repo: https://github.com/asottile/setup-cfg-fmt
|
||||
rev: v2.3.0
|
||||
- id: pyproject-fmt
|
||||
name: pyproject.toml formatter
|
||||
description: "Format the pyproject.toml file."
|
||||
args:
|
||||
- --indent=4
|
||||
additional_dependencies:
|
||||
- tox==4.15.0 # https://github.com/tox-dev/tox/releases/latest
|
||||
- repo: https://github.com/abravalheri/validate-pyproject
|
||||
rev: v0.18
|
||||
hooks:
|
||||
- id: setup-cfg-fmt
|
||||
args: [ --include-version-classifiers ]
|
||||
- id: validate-pyproject
|
||||
name: Validate pyproject.toml
|
||||
description: "Validate the pyproject.toml file."
|
||||
|
||||
10
.tx/config
10
.tx/config
@@ -1,10 +0,0 @@
|
||||
[main]
|
||||
host = https://app.transifex.com
|
||||
lang_map = zh-Hans: zh_Hans
|
||||
|
||||
[o:alliance-auth:p:alliance-auth:r:django-po]
|
||||
file_filter = allianceauth/locale/<lang>/LC_MESSAGES/django.po
|
||||
source_file = allianceauth/locale/en/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
type = PO
|
||||
minimum_perc = 0
|
||||
@@ -5,7 +5,7 @@ manage online service access.
|
||||
# This will make sure the app is always imported when
|
||||
# Django starts so that shared_task will use this app.
|
||||
|
||||
__version__ = '4.0.0rc1'
|
||||
__version__ = '4.3.1'
|
||||
__title__ = 'Alliance Auth'
|
||||
__url__ = 'https://gitlab.com/allianceauth/allianceauth'
|
||||
NAME = f'{__title__} v{__version__}'
|
||||
|
||||
@@ -9,6 +9,8 @@ from .utils import (
|
||||
install_stat_tokens,
|
||||
install_stat_users)
|
||||
|
||||
from allianceauth import __version__
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
BASE_URL = "https://www.google-analytics.com"
|
||||
@@ -99,11 +101,38 @@ def analytics_daily_stats():
|
||||
event_type='Stats')
|
||||
|
||||
for appconfig in apps.get_app_configs():
|
||||
analytics_event(namespace='allianceauth.analytics',
|
||||
task='send_extension_stats',
|
||||
label=appconfig.label,
|
||||
value=1,
|
||||
event_type='Stats')
|
||||
if appconfig.label in [
|
||||
"django_celery_beat",
|
||||
"bootstrapform",
|
||||
"messages",
|
||||
"sessions",
|
||||
"auth",
|
||||
"staticfiles",
|
||||
"users",
|
||||
"addons",
|
||||
"admin",
|
||||
"humanize",
|
||||
"contenttypes",
|
||||
"sortedm2m",
|
||||
"django_bootstrap5",
|
||||
"tokens",
|
||||
"authentication",
|
||||
"services",
|
||||
"framework",
|
||||
"notifications"
|
||||
"eveonline",
|
||||
"navhelper",
|
||||
"analytics",
|
||||
"menu",
|
||||
"theme"
|
||||
]:
|
||||
pass
|
||||
else:
|
||||
analytics_event(namespace='allianceauth.analytics',
|
||||
task='send_extension_stats',
|
||||
label=appconfig.label,
|
||||
value=1,
|
||||
event_type='Stats')
|
||||
|
||||
|
||||
@shared_task()
|
||||
@@ -139,7 +168,7 @@ def send_ga_tracking_celery_event(
|
||||
'client_id': AnalyticsIdentifier.objects.get(id=1).identifier.hex,
|
||||
"user_properties": {
|
||||
"allianceauth_version": {
|
||||
"value": "allianceauth_version"
|
||||
"value": __version__
|
||||
}
|
||||
},
|
||||
'non_personalized_ads': True,
|
||||
|
||||
@@ -5,26 +5,5 @@ from django.core.checks import Warning, Error, register
|
||||
class AllianceAuthConfig(AppConfig):
|
||||
name = 'allianceauth'
|
||||
|
||||
|
||||
@register()
|
||||
def check_settings(app_configs, **kwargs):
|
||||
from django.conf import settings
|
||||
|
||||
errors = []
|
||||
if hasattr(settings, "SITE_URL"):
|
||||
if settings.SITE_URL[-1] == "/":
|
||||
errors.append(Warning(
|
||||
"'SITE_URL' Has a trailing slash. This may lead to incorrect links being generated by Auth."))
|
||||
else:
|
||||
errors.append(Error(
|
||||
"No 'SITE_URL' found is settings. This may lead to incorrect links being generated by Auth or Errors in 3rd party modules."))
|
||||
if hasattr(settings, "CSRF_TRUSTED_ORIGINS"):
|
||||
if hasattr(settings, "SITE_URL"):
|
||||
if settings.SITE_URL not in settings.CSRF_TRUSTED_ORIGINS:
|
||||
errors.append(Warning(
|
||||
"'SITE_URL' not found in 'CSRF_TRUSTED_ORIGINS'. Auth may not load pages correctly until this is rectified."))
|
||||
else:
|
||||
errors.append(Error(
|
||||
"No 'CSRF_TRUSTED_ORIGINS' found is settings, Auth may not load pages correctly until this is rectified"))
|
||||
|
||||
return errors
|
||||
def ready(self) -> None:
|
||||
import allianceauth.checks # noqa
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.13 on 2024-05-12 09:44
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0022_userprofile_theme'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='userprofile',
|
||||
name='language',
|
||||
field=models.CharField(blank=True, choices=[('en', 'English'), ('de', 'German'), ('es', 'Spanish'), ('zh-hans', 'Chinese Simplified'), ('ru', 'Russian'), ('ko', 'Korean'), ('fr', 'French'), ('ja', 'Japanese'), ('it', 'Italian'), ('uk', 'Ukrainian'), ('pl', 'Polish')], default='', max_length=10, verbose_name='Language'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2 on 2024-09-13 09:46
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0023_alter_userprofile_language'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='userprofile',
|
||||
name='language',
|
||||
field=models.CharField(blank=True, choices=[('en', 'English'), ('cs-cz', 'Czech'), ('de', 'German'), ('es', 'Spanish'), ('it-it', 'Italian'), ('ja', 'Japanese'), ('ko-kr', 'Korean'), ('fr-fr', 'French'), ('ru', 'Russian'), ('nl-nl', 'Dutch'), ('pl-pl', 'Polish'), ('uk', 'Ukrainian'), ('zh-hans', 'Simplified Chinese')], default='', max_length=10, verbose_name='Language'),
|
||||
),
|
||||
]
|
||||
@@ -67,17 +67,20 @@ class UserProfile(models.Model):
|
||||
"""
|
||||
Choices for UserProfile.language
|
||||
"""
|
||||
|
||||
# Sorted by Language Code alphabetical order + English at top
|
||||
ENGLISH = 'en', _('English')
|
||||
CZECH = 'cs-cz', _("Czech") # Not yet at 50% translated
|
||||
GERMAN = 'de', _('German')
|
||||
SPANISH = 'es', _('Spanish')
|
||||
CHINESE = 'zh-hans', _('Chinese Simplified')
|
||||
RUSSIAN = 'ru', _('Russian')
|
||||
KOREAN = 'ko', _('Korean')
|
||||
FRENCH = 'fr', _('French')
|
||||
ITALIAN = 'it-it', _('Italian')
|
||||
JAPANESE = 'ja', _('Japanese')
|
||||
ITALIAN = 'it', _('Italian')
|
||||
KOREAN = 'ko-kr', _('Korean')
|
||||
FRENCH = 'fr-fr', _('French')
|
||||
RUSSIAN = 'ru', _('Russian')
|
||||
DUTCH = 'nl-nl', _("Dutch")
|
||||
POLISH = 'pl-pl', _("Polish")
|
||||
UKRAINIAN = 'uk', _('Ukrainian')
|
||||
CHINESE = 'zh-hans', _('Simplified Chinese')
|
||||
|
||||
user = models.OneToOneField(
|
||||
User,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
{% translate "Dashboard" %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="d-flex justify-content-around align-self-center flex-wrap">
|
||||
<div class="row">
|
||||
{% for dash in views %}
|
||||
{{ dash | safe }}
|
||||
{% endfor %}
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
{% load i18n %}
|
||||
<div id="aa-dashboard-panel-characters" class="col-12 col-xl-8 align-self-stretch p-2 ps-0 pe-0 ps-xl-0 pe-xl-2">
|
||||
<div class="card">
|
||||
<div id="aa-dashboard-panel-characters" class="col-12 col-xl-8 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center">
|
||||
<h4 class="ms-auto me-auto">
|
||||
{% translate "Characters" %}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% translate "Characters" as widget_title %}
|
||||
{% include "framework/dashboard/widget-title.html" with title=widget_title %}
|
||||
|
||||
<div>
|
||||
<div style="height: 300px; overflow-y:auto;">
|
||||
<div class="d-flex">
|
||||
<a href="{% url 'authentication:add_character' %}" class="btn btn-primary flex-fill m-1" title="{% translate 'Add Character' %}">
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
{% load i18n %}
|
||||
<div id="aa-dashboard-panel-membership" class="col-12 col-xl-4 align-self-stretch py-2 ps-xl-2">
|
||||
<div id="aa-dashboard-panel-membership" class="col-12 col-xl-4 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title text-center">{% translate "Membership" %}</h4>
|
||||
<div class="card-body">
|
||||
{% translate "Membership" as widget_title %}
|
||||
{% include "framework/dashboard/widget-title.html" with title=widget_title %}
|
||||
|
||||
<div>
|
||||
<div style="height: 300px; overflow-y:auto;">
|
||||
<h5 class="text-center">{% translate "State:" %} {{ request.user.profile.state }}</h5>
|
||||
<table class="table">
|
||||
|
||||
187
allianceauth/checks.py
Normal file
187
allianceauth/checks.py
Normal file
@@ -0,0 +1,187 @@
|
||||
from typing import List
|
||||
from django import db
|
||||
from django.core.checks import CheckMessage, Error, register, Warning
|
||||
from allianceauth.utils.cache import get_redis_client
|
||||
from django.utils import timezone
|
||||
from packaging.version import InvalidVersion, Version as Pep440Version
|
||||
from celery import current_app
|
||||
from django.conf import settings
|
||||
from sqlite3.dbapi2 import sqlite_version_info
|
||||
|
||||
"""
|
||||
A = System Packages
|
||||
B = Configuration
|
||||
"""
|
||||
|
||||
|
||||
@register()
|
||||
def django_settings(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: List[CheckMessage] = []
|
||||
if hasattr(settings, "SITE_URL"):
|
||||
if settings.SITE_URL[-1] == "/":
|
||||
errors.append(Warning("'SITE_URL' Has a trailing slash. This may lead to incorrect links being generated by Auth.", hint="", id="allianceauth.checks.B005"))
|
||||
else:
|
||||
errors.append(Error("No 'SITE_URL' found is settings. This may lead to incorrect links being generated by Auth or Errors in 3rd party modules.", hint="", id="allianceauth.checks.B006"))
|
||||
|
||||
if hasattr(settings, "CSRF_TRUSTED_ORIGINS") and hasattr(settings, "SITE_URL"):
|
||||
if settings.SITE_URL not in settings.CSRF_TRUSTED_ORIGINS:
|
||||
errors.append(Warning("'SITE_URL' not found in 'CSRF_TRUSTED_ORIGINS'. Auth may not load pages correctly until this is rectified.", hint="", id="allianceauth.checks.B007"))
|
||||
else:
|
||||
errors.append(Error("No 'CSRF_TRUSTED_ORIGINS' found is settings, Auth may not load pages correctly until this is rectified", hint="", id="allianceauth.checks.B008"))
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
@register()
|
||||
def system_package_redis(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: List[CheckMessage] = []
|
||||
try:
|
||||
redis_version = Pep440Version(get_redis_client().info()['redis_version'])
|
||||
except InvalidVersion:
|
||||
errors.append(Warning("Unable to confirm Redis Version"))
|
||||
return errors
|
||||
|
||||
if redis_version.major == 7 and redis_version.minor == 2 and timezone.now() > timezone.datetime(year=2025, month=8, day=31, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"Redis {redis_version.public} in Security Support only, Updating Suggested", hint="https://allianceauth.readthedocs.io/en/latest/installation/allianceauth.html#redis-and-other-tools", id="allianceauth.checks.A001"))
|
||||
elif redis_version.major == 7 and redis_version.minor == 0:
|
||||
errors.append(Warning(f"Redis {redis_version.public} in Security Support only, Updating Suggested", hint="https://allianceauth.readthedocs.io/en/latest/installation/allianceauth.html#redis-and-other-tools", id="allianceauth.checks.A002"))
|
||||
elif redis_version.major == 6 and redis_version.minor == 2:
|
||||
errors.append(Warning(f"Redis {redis_version.public} in Security Support only, Updating Suggested", hint="https://allianceauth.readthedocs.io/en/latest/installation/allianceauth.html#redis-and-other-tools", id="allianceauth.checks.A018"))
|
||||
elif redis_version.major in [6, 5]:
|
||||
errors.append(Error(f"Redis {redis_version.public} EOL", hint="https://allianceauth.readthedocs.io/en/latest/installation/allianceauth.html#redis-and-other-tools", id="allianceauth.checks.A003"))
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
@register()
|
||||
def system_package_mysql(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: List[CheckMessage] = []
|
||||
|
||||
for connection in db.connections.all():
|
||||
if connection.vendor == "mysql":
|
||||
try:
|
||||
mysql_version = Pep440Version(".".join(str(i) for i in connection.mysql_version))
|
||||
except InvalidVersion:
|
||||
errors.append(Warning("Unable to confirm MySQL Version"))
|
||||
return errors
|
||||
|
||||
# MySQL 8
|
||||
if mysql_version.major == 8 and mysql_version.minor == 4 and timezone.now() > timezone.datetime(year=2032, month=4, day=30, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"MySQL {mysql_version.public} EOL", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A004"))
|
||||
elif mysql_version.major == 8 and mysql_version.minor == 3:
|
||||
errors.append(Warning(f"MySQL {mysql_version.public} Non LTS", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A005"))
|
||||
elif mysql_version.major == 8 and mysql_version.minor == 2:
|
||||
errors.append(Warning(f"MySQL {mysql_version.public} Non LTS", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A006"))
|
||||
elif mysql_version.major == 8 and mysql_version.minor == 1:
|
||||
errors.append(Error(f"MySQL {mysql_version.public} EOL", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A007"))
|
||||
elif mysql_version.major == 8 and mysql_version.minor == 0 and timezone.now() > timezone.datetime(year=2026, month=4, day=30, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"MySQL {mysql_version.public} EOL", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A008"))
|
||||
elif mysql_version.major < 8: # This will also catch Mariadb 5.x
|
||||
errors.append(Error(f"MySQL or MariaDB {mysql_version.public} EOL", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A009"))
|
||||
return errors
|
||||
|
||||
|
||||
@register()
|
||||
def system_package_mariadb(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: List[CheckMessage] = []
|
||||
|
||||
for connection in db.connections.all():
|
||||
if connection.vendor == "mysql": # Still to find a way to determine MySQL vs MariaDB
|
||||
try:
|
||||
mariadb_version = Pep440Version(".".join(str(i) for i in connection.mysql_version))
|
||||
except InvalidVersion:
|
||||
errors.append(Warning("Unable to confirm MariaDB Version"))
|
||||
return errors
|
||||
|
||||
# MariaDB 11
|
||||
if mariadb_version.major == 11 and mariadb_version.minor == 4 and timezone.now() > timezone.datetime(year=2029, month=5, day=19, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A010"))
|
||||
elif mariadb_version.major == 11 and mariadb_version.minor == 2:
|
||||
errors.append(Warning(f"MariaDB {mariadb_version.public} Non LTS", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A018"))
|
||||
if timezone.now() > timezone.datetime(year=2024, month=11, day=21, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A011"))
|
||||
elif mariadb_version.major == 11 and mariadb_version.minor == 1:
|
||||
errors.append(Warning(f"MariaDB {mariadb_version.public} Non LTS", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A019"))
|
||||
if timezone.now() > timezone.datetime(year=2024, month=8, day=21, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A012"))
|
||||
elif mariadb_version.major == 11 and mariadb_version.minor in [0, 3]: # Demote versions down here once EOL
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config.", id="allianceauth.checks.A013"))
|
||||
|
||||
# MariaDB 10
|
||||
elif mariadb_version.major == 10 and mariadb_version.minor == 11 and timezone.now() > timezone.datetime(year=2028, month=2, day=10, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config.", id="allianceauth.checks.A014"))
|
||||
elif mariadb_version.major == 10 and mariadb_version.minor == 6 and timezone.now() > timezone.datetime(year=2026, month=7, day=6, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A0015"))
|
||||
elif mariadb_version.major == 10 and mariadb_version.minor == 5 and timezone.now() > timezone.datetime(year=2025, month=6, day=24, tzinfo=timezone.utc):
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A016"))
|
||||
elif mariadb_version.major == 10 and mariadb_version.minor in [0, 1, 2, 3, 4, 7, 9, 10]: # Demote versions down here once EOL
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A017"))
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
@register()
|
||||
def system_package_sqlite(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: List[CheckMessage] = []
|
||||
for connection in db.connections.all():
|
||||
if connection.vendor == "sqlite":
|
||||
try:
|
||||
sqlite_version = Pep440Version(".".join(str(i) for i in sqlite_version_info))
|
||||
except InvalidVersion:
|
||||
errors.append(Warning("Unable to confirm SQLite Version"))
|
||||
return errors
|
||||
if sqlite_version.major == 3 and sqlite_version.minor < 27:
|
||||
errors.append(Error(f"SQLite {sqlite_version.public} Unsupported by Django", hint="https://pkgs.org/download/sqlite3", id="allianceauth.checks.A020"))
|
||||
return errors
|
||||
|
||||
|
||||
@register()
|
||||
def sql_settings(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: List[CheckMessage] = []
|
||||
for connection in db.connections.all():
|
||||
if connection.vendor == "mysql":
|
||||
try:
|
||||
if connection.settings_dict["OPTIONS"]["charset"] != "utf8mb4":
|
||||
errors.append(Error(f"SQL Charset is not set to utf8mb4 DB:{connection.alias}", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/89be2456fb2d741b86417e889da9b6129525bec8", id="allianceauth.checks.B001"))
|
||||
except KeyError:
|
||||
errors.append(Error(f"SQL Charset is not set to utf8mb4 DB:{connection.alias}", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/89be2456fb2d741b86417e889da9b6129525bec8", id="allianceauth.checks.B001"))
|
||||
|
||||
# This hasn't actually been set on AA yet
|
||||
# try:
|
||||
# if connection.settings_dict["OPTIONS"]["collation"] != "utf8mb4_unicode_ci":
|
||||
# errors.append(Error(f"SQL Collation is not set to utf8mb4_unicode_ci DB:{connection.alias}", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/89be2456fb2d741b86417e889da9b6129525bec8", id="allianceauth.checks.B001"))
|
||||
# except KeyError:
|
||||
# errors.append(Error(f"SQL Collation is not set to utf8mb4_unicode_ci DB:{connection.alias}", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/89be2456fb2d741b86417e889da9b6129525bec8", id="allianceauth.checks.B001"))
|
||||
|
||||
# if connection.vendor == "sqlite":
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
@register()
|
||||
def celery_settings(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: List[CheckMessage] = []
|
||||
|
||||
try:
|
||||
if current_app.conf.broker_transport_options != {'priority_steps': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 'queue_order_strategy': 'priority'}:
|
||||
errors.append(Error("Celery Priorities are not set correctly", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/8861ec0a61790eca0261f1adc1cc04ca5f243cbc", id="allianceauth.checks.B003"))
|
||||
except KeyError:
|
||||
errors.append(Error("Celery Priorities are not set", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/8861ec0a61790eca0261f1adc1cc04ca5f243cbc", id="allianceauth.checks.B003"))
|
||||
|
||||
try:
|
||||
if current_app.conf.broker_connection_retry_on_startup != True:
|
||||
errors.append(Error("Celery broker_connection_retry_on_startup not set correctly", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/380c41400b535447839e5552df2410af35a75280", id="allianceauth.checks.B004"))
|
||||
except KeyError:
|
||||
errors.append(Error("Celery broker_connection_retry_on_startup not set", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/380c41400b535447839e5552df2410af35a75280", id="allianceauth.checks.B004"))
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
# IDEAS
|
||||
|
||||
# Any other celery things weve manually changed over the years
|
||||
# I'd be happy to add Community App checks, old versions the owners dont want to support etc.
|
||||
|
||||
|
||||
# Check Default Collation on DB
|
||||
# Check Charset Collation on all tables
|
||||
3
allianceauth/custom_css/__init__.py
Normal file
3
allianceauth/custom_css/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Initializes the custom_css module.
|
||||
"""
|
||||
25
allianceauth/custom_css/admin.py
Normal file
25
allianceauth/custom_css/admin.py
Normal file
@@ -0,0 +1,25 @@
|
||||
"""
|
||||
Admin classes for custom_css app
|
||||
"""
|
||||
|
||||
# Django
|
||||
from django.contrib import admin
|
||||
|
||||
# Django Solos
|
||||
from solo.admin import SingletonModelAdmin
|
||||
|
||||
# Alliance Auth Custom CSS
|
||||
from allianceauth.custom_css.models import CustomCSS
|
||||
from allianceauth.custom_css.forms import CustomCSSAdminForm
|
||||
|
||||
|
||||
@admin.register(CustomCSS)
|
||||
class CustomCSSAdmin(SingletonModelAdmin):
|
||||
"""
|
||||
Custom CSS Admin
|
||||
"""
|
||||
|
||||
form = CustomCSSAdminForm
|
||||
|
||||
# Leave this here for when we decide to add syntax highlighting to the CSS editor
|
||||
# change_form_template = 'custom_css/admin/change_form.html'
|
||||
13
allianceauth/custom_css/apps.py
Normal file
13
allianceauth/custom_css/apps.py
Normal file
@@ -0,0 +1,13 @@
|
||||
"""
|
||||
Django app configuration for custom_css
|
||||
"""
|
||||
|
||||
# Django
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class CustomCSSConfig(AppConfig):
|
||||
name = "allianceauth.custom_css"
|
||||
label = "custom_css"
|
||||
verbose_name = _("Custom CSS")
|
||||
29
allianceauth/custom_css/forms.py
Normal file
29
allianceauth/custom_css/forms.py
Normal file
@@ -0,0 +1,29 @@
|
||||
"""
|
||||
Forms for custom_css app
|
||||
"""
|
||||
|
||||
# Alliance Auth Custom CSS
|
||||
from allianceauth.custom_css.models import CustomCSS
|
||||
from allianceauth.custom_css.widgets import CssEditorWidget
|
||||
|
||||
# Django
|
||||
from django import forms
|
||||
|
||||
|
||||
class CustomCSSAdminForm(forms.ModelForm):
|
||||
"""
|
||||
Form for editing custom CSS
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = CustomCSS
|
||||
fields = ("css",)
|
||||
widgets = {
|
||||
"css": CssEditorWidget(
|
||||
attrs={
|
||||
"style": "width: 90%; height: 100%;",
|
||||
"data-editor": "code-highlight",
|
||||
"data-language": "css",
|
||||
}
|
||||
)
|
||||
}
|
||||
42
allianceauth/custom_css/migrations/0001_initial.py
Normal file
42
allianceauth/custom_css/migrations/0001_initial.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# Generated by Django 4.2.15 on 2024-08-14 11:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="CustomCSS",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"css",
|
||||
models.TextField(
|
||||
blank=True,
|
||||
help_text="This CSS will be added to the site after the default CSS.",
|
||||
null=True,
|
||||
verbose_name="Your custom CSS",
|
||||
),
|
||||
),
|
||||
("timestamp", models.DateTimeField(auto_now=True)),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Custom CSS",
|
||||
"verbose_name_plural": "Custom CSS",
|
||||
"default_permissions": (),
|
||||
},
|
||||
),
|
||||
]
|
||||
0
allianceauth/custom_css/migrations/__init__.py
Normal file
0
allianceauth/custom_css/migrations/__init__.py
Normal file
143
allianceauth/custom_css/models.py
Normal file
143
allianceauth/custom_css/models.py
Normal file
@@ -0,0 +1,143 @@
|
||||
"""
|
||||
Models for the custom_css app
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
# Django Solo
|
||||
from solo.models import SingletonModel
|
||||
|
||||
# Django
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class CustomCSS(SingletonModel):
|
||||
"""
|
||||
Model for storing custom CSS for the site
|
||||
"""
|
||||
|
||||
css = models.TextField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_("Your custom CSS"),
|
||||
help_text=_("This CSS will be added to the site after the default CSS."),
|
||||
)
|
||||
timestamp = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
Meta for CustomCSS
|
||||
"""
|
||||
|
||||
default_permissions = ()
|
||||
verbose_name = _("Custom CSS")
|
||||
verbose_name_plural = _("Custom CSS")
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""
|
||||
String representation of CustomCSS
|
||||
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
|
||||
return str(_("Custom CSS"))
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
"""
|
||||
Save method for CustomCSS
|
||||
|
||||
:param args:
|
||||
:type args:
|
||||
:param kwargs:
|
||||
:type kwargs:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
|
||||
self.pk = 1
|
||||
|
||||
if self.css and len(self.css.replace(" ", "")) > 0:
|
||||
# Write the custom CSS to a file
|
||||
custom_css_file = open(
|
||||
f"{settings.STATIC_ROOT}allianceauth/custom-styles.css", "w+"
|
||||
)
|
||||
custom_css_file.write(self.compress_css())
|
||||
custom_css_file.close()
|
||||
else:
|
||||
# Remove the custom CSS file
|
||||
try:
|
||||
os.remove(f"{settings.STATIC_ROOT}allianceauth/custom-styles.css")
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def compress_css(self) -> str:
|
||||
"""
|
||||
Compress CSS
|
||||
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
|
||||
css = self.css
|
||||
new_css = ""
|
||||
|
||||
# Remove comments
|
||||
css = re.sub(pattern=r"\s*/\*\s*\*/", repl="$$HACK1$$", string=css)
|
||||
css = re.sub(pattern=r"/\*[\s\S]*?\*/", repl="", string=css)
|
||||
css = css.replace("$$HACK1$$", "/**/")
|
||||
|
||||
# url() doesn't need quotes
|
||||
css = re.sub(pattern=r'url\((["\'])([^)]*)\1\)', repl=r"url(\2)", string=css)
|
||||
|
||||
# Spaces may be safely collapsed as generated content will collapse them anyway.
|
||||
css = re.sub(pattern=r"\s+", repl=" ", string=css)
|
||||
|
||||
# Shorten collapsable colors: #aabbcc to #abc
|
||||
css = re.sub(
|
||||
pattern=r"#([0-9a-f])\1([0-9a-f])\2([0-9a-f])\3(\s|;)",
|
||||
repl=r"#\1\2\3\4",
|
||||
string=css,
|
||||
)
|
||||
|
||||
# Fragment values can loose zeros
|
||||
css = re.sub(
|
||||
pattern=r":\s*0(\.\d+([cm]m|e[mx]|in|p[ctx]))\s*;", repl=r":\1;", string=css
|
||||
)
|
||||
|
||||
for rule in re.findall(pattern=r"([^{]+){([^}]*)}", string=css):
|
||||
# We don't need spaces around operators
|
||||
selectors = [
|
||||
re.sub(
|
||||
pattern=r"(?<=[\[\(>+=])\s+|\s+(?=[=~^$*|>+\]\)])",
|
||||
repl=r"",
|
||||
string=selector.strip(),
|
||||
)
|
||||
for selector in rule[0].split(",")
|
||||
]
|
||||
|
||||
# Order is important, but we still want to discard repetitions
|
||||
properties = {}
|
||||
porder = []
|
||||
|
||||
for prop in re.findall(pattern="(.*?):(.*?)(;|$)", string=rule[1]):
|
||||
key = prop[0].strip().lower()
|
||||
|
||||
if key not in porder:
|
||||
porder.append(key)
|
||||
|
||||
properties[key] = prop[1].strip()
|
||||
|
||||
# output rule if it contains any declarations
|
||||
if properties:
|
||||
new_css += "{}{{{}}}".format(
|
||||
",".join(selectors),
|
||||
"".join([f"{key}:{properties[key]};" for key in porder])[:-1],
|
||||
)
|
||||
|
||||
return new_css
|
||||
@@ -0,0 +1,48 @@
|
||||
{% extends "admin/change_form.html" %}
|
||||
|
||||
{% block field_sets %}
|
||||
{% for fieldset in adminform %}
|
||||
<fieldset class="module aligned {{ fieldset.classes }}">
|
||||
{% if fieldset.name %}<h2>{{ fieldset.name }}</h2>{% endif %}
|
||||
|
||||
{% if fieldset.description %}
|
||||
<div class="description">{{ fieldset.description|safe }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% for line in fieldset %}
|
||||
<div class="form-row{% if line.fields|length == 1 and line.errors %} errors{% endif %}{% if not line.has_visible_field %} hidden{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}">
|
||||
{% if line.fields|length == 1 %}{{ line.errors }}{% else %}<div class="flex-container form-multiline">{% endif %}
|
||||
|
||||
{% for field in line %}
|
||||
<div>
|
||||
{% if not line.fields|length == 1 and not field.is_readonly %}{{ field.errors }}{% endif %}
|
||||
|
||||
<div class="flex-container{% if not line.fields|length == 1 %} fieldBox{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% if not field.is_readonly and field.errors %} errors{% endif %}{% if field.field.is_hidden %} hidden{% endif %}{% elif field.is_checkbox %} checkbox-row{% endif %}">
|
||||
{% if field.is_checkbox %}
|
||||
{{ field.field }}{{ field.label_tag }}
|
||||
{% else %}
|
||||
{{ field.label_tag }}
|
||||
{% if field.is_readonly %}
|
||||
<div class="readonly">{{ field.contents }}</div>
|
||||
{% else %}
|
||||
{{ field.field }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if field.field.help_text %}
|
||||
<div class="help"{% if field.field.id_for_label %} id="{{ field.field.id_for_label }}_helptext"{% endif %}>
|
||||
<div>{{ field.field.help_text|safe }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% if not line.fields|length == 1 %}</div>{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</fieldset>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block after_field_sets %}{% endblock %}
|
||||
@@ -0,0 +1,3 @@
|
||||
{% load custom_css %}
|
||||
|
||||
{% custom_css_static 'allianceauth/custom-styles.css' %}
|
||||
3
allianceauth/custom_css/templatetags/__init__.py
Normal file
3
allianceauth/custom_css/templatetags/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Init file for custom_css templatetags
|
||||
"""
|
||||
48
allianceauth/custom_css/templatetags/custom_css.py
Normal file
48
allianceauth/custom_css/templatetags/custom_css.py
Normal file
@@ -0,0 +1,48 @@
|
||||
"""
|
||||
Custom template tags for custom_css app
|
||||
"""
|
||||
|
||||
# Alliance Auth Custom CSS
|
||||
from allianceauth.custom_css.models import CustomCSS
|
||||
|
||||
# Django
|
||||
from django.conf import settings
|
||||
from django.template.defaulttags import register
|
||||
from django.templatetags.static import static
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def custom_css_static(path: str) -> str:
|
||||
"""
|
||||
Versioned static URL
|
||||
This is to make sure to break the browser cache on CSS updates.
|
||||
|
||||
Example: /static/allianceauth/custom-styles.css?v=1234567890
|
||||
|
||||
:param path:
|
||||
:type path:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
|
||||
try:
|
||||
Path(f"{settings.STATIC_ROOT}{path}").resolve(strict=True)
|
||||
except FileNotFoundError:
|
||||
return ""
|
||||
else:
|
||||
try:
|
||||
custom_css = CustomCSS.objects.get(pk=1)
|
||||
except CustomCSS.DoesNotExist:
|
||||
return ""
|
||||
else:
|
||||
custom_css_changed = custom_css.timestamp.timestamp()
|
||||
custom_css_version = (
|
||||
str(custom_css_changed).replace(" ", "").replace(":", "").replace("-", "")
|
||||
) # remove spaces, colons, and dashes
|
||||
static_url = static(path)
|
||||
versioned_url = static_url + "?v=" + custom_css_version
|
||||
|
||||
return mark_safe(f'<link rel="stylesheet" href="{versioned_url}">')
|
||||
38
allianceauth/custom_css/widgets.py
Normal file
38
allianceauth/custom_css/widgets.py
Normal file
@@ -0,0 +1,38 @@
|
||||
"""
|
||||
Form widgets for custom_css app
|
||||
"""
|
||||
|
||||
# Django
|
||||
from django import forms
|
||||
|
||||
# Alliance Auth
|
||||
from allianceauth.custom_css.models import CustomCSS
|
||||
|
||||
|
||||
class CssEditorWidget(forms.Textarea):
|
||||
"""
|
||||
Widget for editing CSS
|
||||
"""
|
||||
|
||||
def __init__(self, attrs=None):
|
||||
default_attrs = {"class": "custom-css-editor"}
|
||||
|
||||
if attrs:
|
||||
default_attrs.update(attrs)
|
||||
|
||||
super().__init__(default_attrs)
|
||||
|
||||
# For when we want to add some sort of syntax highlight to it, which is not that
|
||||
# easy to do on a textarea field though.
|
||||
# `highlight.js` is just used as an example here, and doesn't work on a textarea field.
|
||||
# class Media:
|
||||
# css = {
|
||||
# "all": (
|
||||
# "/static/custom_css/libs/highlight.js/11.10.0/styles/github.min.css",
|
||||
# )
|
||||
# }
|
||||
# js = (
|
||||
# "/static/custom_css/libs/highlight.js/11.10.0/highlight.min.js",
|
||||
# "/static/custom_css/libs/highlight.js/11.10.0/languages/css.min.js",
|
||||
# "/static/custom_css/javascript/custom-css.min.js",
|
||||
# )
|
||||
@@ -0,0 +1,8 @@
|
||||
{#Usage:#}
|
||||
{# {% include "framework/dashboard/widget-title.html" with title="Foobar" %}#}
|
||||
|
||||
<div class="text-center">
|
||||
<h4 class="ms-auto me-auto mb-3">
|
||||
{{ title }}
|
||||
</h4>
|
||||
</div>
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
{% if subtitle %}
|
||||
<br>
|
||||
<small>{{ subtitle }}</small>
|
||||
<small class="text-muted">{{ subtitle }}</small>
|
||||
{% endif %}
|
||||
</h1>
|
||||
{% endif %}
|
||||
|
||||
BIN
allianceauth/locale/cs_CZ/LC_MESSAGES/django.mo
Normal file
BIN
allianceauth/locale/cs_CZ/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
2851
allianceauth/locale/cs_CZ/LC_MESSAGES/django.po
Normal file
2851
allianceauth/locale/cs_CZ/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-03-13 19:10+1000\n"
|
||||
"POT-Creation-Date: 2024-09-13 19:57+1000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -49,66 +49,90 @@ msgid "You are not allowed to add or remove these restricted groups: %s"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:71
|
||||
#: allianceauth/project_template/project_name/settings/base.py:99
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:72
|
||||
msgid "German"
|
||||
msgid "Czech"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:73
|
||||
msgid "Spanish"
|
||||
#: allianceauth/project_template/project_name/settings/base.py:101
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:74
|
||||
msgid "Chinese Simplified"
|
||||
#: allianceauth/project_template/project_name/settings/base.py:102
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:75
|
||||
msgid "Russian"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:76
|
||||
msgid "Korean"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:77
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:78
|
||||
msgid "Japanese"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:79
|
||||
#: allianceauth/project_template/project_name/settings/base.py:103
|
||||
msgid "Italian"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:76
|
||||
#: allianceauth/project_template/project_name/settings/base.py:104
|
||||
msgid "Japanese"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:77
|
||||
#: allianceauth/project_template/project_name/settings/base.py:105
|
||||
msgid "Korean"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:78
|
||||
#: allianceauth/project_template/project_name/settings/base.py:106
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:79
|
||||
#: allianceauth/project_template/project_name/settings/base.py:109
|
||||
msgid "Russian"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:80
|
||||
#: allianceauth/project_template/project_name/settings/base.py:107
|
||||
msgid "Dutch"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:81
|
||||
#: allianceauth/project_template/project_name/settings/base.py:108
|
||||
msgid "Polish"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:82
|
||||
#: allianceauth/project_template/project_name/settings/base.py:110
|
||||
msgid "Ukrainian"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:96
|
||||
#: allianceauth/authentication/models.py:83
|
||||
#: allianceauth/project_template/project_name/settings/base.py:111
|
||||
msgid "Simplified Chinese"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:99
|
||||
#: allianceauth/menu/templates/menu/menu-user.html:42
|
||||
msgid "Language"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:101
|
||||
#: allianceauth/authentication/models.py:104
|
||||
#: allianceauth/templates/allianceauth/night-toggle.html:6
|
||||
msgid "Night Mode"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:105
|
||||
#: allianceauth/authentication/models.py:108
|
||||
#: allianceauth/menu/templates/menu/menu-user.html:46
|
||||
msgid "Theme"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:122
|
||||
#: allianceauth/authentication/models.py:125
|
||||
#, python-format
|
||||
msgid "State changed to: %s"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:123
|
||||
#: allianceauth/authentication/models.py:126
|
||||
#, python-format
|
||||
msgid "Your user's state is now: %(state)s"
|
||||
msgstr ""
|
||||
@@ -120,27 +144,27 @@ msgstr ""
|
||||
msgid "Dashboard"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_characters.html:7
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_characters.html:5
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:33
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:54
|
||||
msgid "Characters"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_characters.html:13
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_characters.html:14
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_characters.html:11
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_characters.html:12
|
||||
#: allianceauth/templates/allianceauth/top-menu-rh-default.html:4
|
||||
#: allianceauth/templates/allianceauth/top-menu-rh-default.html:6
|
||||
msgid "Add Character"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_characters.html:16
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_characters.html:17
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_characters.html:14
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_characters.html:15
|
||||
#: allianceauth/templates/allianceauth/top-menu-rh-default.html:10
|
||||
#: allianceauth/templates/allianceauth/top-menu-rh-default.html:12
|
||||
msgid "Change Main"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_characters.html:24
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_characters.html:22
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:89
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:23
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:31
|
||||
@@ -149,12 +173,12 @@ msgstr ""
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_characters.html:25
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_characters.html:23
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:33
|
||||
msgid "Corp"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_characters.html:26
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_characters.html:24
|
||||
#: allianceauth/corputils/templates/corputils/corpstats.html:125
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:63
|
||||
msgid "Alliance"
|
||||
@@ -164,7 +188,7 @@ msgstr ""
|
||||
msgid "Membership"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_groups.html:8
|
||||
#: allianceauth/authentication/templates/authentication/dashboard_groups.html:10
|
||||
msgid "State:"
|
||||
msgstr ""
|
||||
|
||||
@@ -395,6 +419,19 @@ msgstr ""
|
||||
msgid "Failed to gather corporation statistics with selected token."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/custom_css/apps.py:13 allianceauth/custom_css/models.py:36
|
||||
#: allianceauth/custom_css/models.py:37 allianceauth/custom_css/models.py:47
|
||||
msgid "Custom CSS"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/custom_css/models.py:25
|
||||
msgid "Your custom CSS"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/custom_css/models.py:26
|
||||
msgid "This CSS will be added to the site after the default CSS."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/fleetactivitytracking/auth_hooks.py:10
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/characternotexisting.html:10
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkcreate.html:11
|
||||
@@ -487,8 +524,8 @@ msgstr ""
|
||||
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:37
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:42
|
||||
#: allianceauth/optimer/form.py:13 allianceauth/timerboard/form.py:59
|
||||
#: allianceauth/timerboard/templates/timerboard/dashboard.timers.html:16
|
||||
#: allianceauth/optimer/form.py:13 allianceauth/timerboard/form.py:37
|
||||
#: allianceauth/timerboard/templates/timerboard/dashboard.timers.html:17
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:9
|
||||
msgid "System"
|
||||
msgstr ""
|
||||
@@ -807,7 +844,7 @@ msgstr ""
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31
|
||||
#: allianceauth/optimer/templates/optimer/dashboard.ops.html:15
|
||||
#: allianceauth/timerboard/templates/timerboard/dashboard.timers.html:15
|
||||
#: allianceauth/timerboard/templates/timerboard/dashboard.timers.html:16
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
@@ -899,7 +936,7 @@ msgid "Hidden"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:45
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:19
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:16
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
|
||||
@@ -1375,16 +1412,18 @@ msgstr ""
|
||||
msgid "Super User"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/menu/templates/menu/menu-user.html:68
|
||||
#: allianceauth/menu/templates/menu/menu-user.html:70
|
||||
#: allianceauth/templates/allianceauth/top-menu-admin.html:9
|
||||
msgid "Admin"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/menu/templates/menu/menu-user.html:80
|
||||
#: allianceauth/menu/templates/menu/menu-user.html:82
|
||||
msgid "Sign Out"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/menu/templates/menu/menu-user.html:84
|
||||
#: allianceauth/menu/templates/menu/menu-user.html:86
|
||||
#: allianceauth/templates/allianceauth/top-menu-rh-default.html:17
|
||||
#: allianceauth/templates/allianceauth/top-menu-rh-default.html:18
|
||||
msgid "Sign In"
|
||||
msgstr ""
|
||||
|
||||
@@ -1532,7 +1571,7 @@ msgid "Form Up System"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/optimer/templates/optimer/dashboard.ops.html:17
|
||||
#: allianceauth/timerboard/templates/timerboard/dashboard.timers.html:17
|
||||
#: allianceauth/timerboard/templates/timerboard/dashboard.timers.html:18
|
||||
msgid "EVE Time"
|
||||
msgstr ""
|
||||
|
||||
@@ -1727,17 +1766,17 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:26
|
||||
#: allianceauth/services/modules/mumble/templates/services/mumble/mumble_service_ctrl.html:20
|
||||
#: allianceauth/services/modules/mumble/templates/services/mumble/mumble_service_ctrl.html:22
|
||||
msgid "Activate"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:32
|
||||
#: allianceauth/services/modules/mumble/templates/services/mumble/mumble_service_ctrl.html:32
|
||||
#: allianceauth/services/modules/mumble/templates/services/mumble/mumble_service_ctrl.html:34
|
||||
msgid "Reset Password"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:38
|
||||
#: allianceauth/services/modules/mumble/templates/services/mumble/mumble_service_ctrl.html:38
|
||||
#: allianceauth/services/modules/mumble/templates/services/mumble/mumble_service_ctrl.html:40
|
||||
msgid "Deactivate"
|
||||
msgstr ""
|
||||
|
||||
@@ -1817,12 +1856,12 @@ msgstr ""
|
||||
msgid "Deactivated IPSuite4 account."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/services/modules/mumble/templates/services/mumble/mumble_service_ctrl.html:26
|
||||
#: allianceauth/services/modules/mumble/templates/services/mumble/mumble_service_ctrl.html:28
|
||||
#: allianceauth/services/templates/services/service_password.html:26
|
||||
msgid "Set Password"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/services/modules/mumble/templates/services/mumble/mumble_service_ctrl.html:44
|
||||
#: allianceauth/services/modules/mumble/templates/services/mumble/mumble_service_ctrl.html:46
|
||||
msgid "Connect"
|
||||
msgstr ""
|
||||
|
||||
@@ -2384,56 +2423,56 @@ msgstr ""
|
||||
msgid "Your Server received an ESI error response code of "
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:11
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:8
|
||||
msgid "Alliance Auth Notifications"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:21
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:18
|
||||
msgid "Closed"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:27
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:24
|
||||
msgid "No notifications at this time"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:36
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:33
|
||||
msgid "Powered by GitLab"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:42
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:39
|
||||
msgid "Support Discord"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:59
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:63
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:53
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:57
|
||||
msgid "Software Version"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:66
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:60
|
||||
msgid "Current"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:73
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:67
|
||||
msgid "Latest Stable"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:78
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:72
|
||||
msgid "Update available"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:86
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:80
|
||||
msgid "Latest Pre-Release"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:91
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:85
|
||||
msgid "Pre-Release available"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:102
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:95
|
||||
msgid "Task Queue"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:107
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:100
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
@@ -2442,11 +2481,11 @@ msgid ""
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:123
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:116
|
||||
msgid "running"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:124
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:117
|
||||
msgid "queued"
|
||||
msgstr ""
|
||||
|
||||
@@ -2475,114 +2514,216 @@ msgstr ""
|
||||
msgid "Select Theme"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/form.py:53
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:172
|
||||
msgid "Other"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/form.py:54
|
||||
#: allianceauth/timerboard/templates/timerboard/dashboard.timers.html:38
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:44
|
||||
msgid "Friendly"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/form.py:55
|
||||
#: allianceauth/timerboard/templates/timerboard/dashboard.timers.html:33
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:38
|
||||
msgid "Hostile"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/form.py:56
|
||||
#: allianceauth/timerboard/templates/timerboard/dashboard.timers.html:43
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:50
|
||||
msgid "Neutral"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/form.py:58
|
||||
#: allianceauth/timerboard/templates/timerboard/dashboard.timers.html:13
|
||||
#: allianceauth/timerboard/form.py:36
|
||||
#: allianceauth/timerboard/templates/timerboard/dashboard.timers.html:14
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:7
|
||||
msgid "Details"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/form.py:60
|
||||
#: allianceauth/timerboard/form.py:38
|
||||
msgid "Planet/Moon"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/form.py:61
|
||||
#: allianceauth/timerboard/form.py:39
|
||||
msgid "Structure Type"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/form.py:62
|
||||
#: allianceauth/timerboard/form.py:40
|
||||
msgid "Timer Type"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/form.py:63
|
||||
#: allianceauth/timerboard/form.py:41
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:8
|
||||
msgid "Objective"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/form.py:64
|
||||
#: allianceauth/timerboard/form.py:42
|
||||
msgid "Absolute Timer"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/form.py:65
|
||||
#: allianceauth/timerboard/form.py:43
|
||||
msgid "Date and Time"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/form.py:66
|
||||
#: allianceauth/timerboard/form.py:44
|
||||
msgid "Days Remaining"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/form.py:67
|
||||
#: allianceauth/timerboard/form.py:45
|
||||
msgid "Hours Remaining"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/form.py:69
|
||||
#: allianceauth/timerboard/form.py:47
|
||||
msgid "Minutes Remaining"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/form.py:71
|
||||
#: allianceauth/timerboard/form.py:48
|
||||
msgid "Important"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/form.py:72
|
||||
#: allianceauth/timerboard/form.py:49
|
||||
msgid "Corp-Restricted"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:14
|
||||
msgid "Not Specified"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:15
|
||||
msgid "Shield"
|
||||
#: allianceauth/timerboard/templates/timerboard/dashboard.timers.html:39
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:36
|
||||
msgid "Friendly"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:16
|
||||
msgid "Armor"
|
||||
#: allianceauth/timerboard/templates/timerboard/dashboard.timers.html:34
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:34
|
||||
msgid "Hostile"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:17
|
||||
#: allianceauth/timerboard/templates/timerboard/dashboard.timers.html:44
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:38
|
||||
msgid "Neutral"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:24
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:48
|
||||
msgid "POCO"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:25
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:50
|
||||
msgid "Orbital Skyhook"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:26
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:52
|
||||
msgid "I-HUB"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:27
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:55
|
||||
msgid "TCU"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:28
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:57
|
||||
msgid "POS [S]"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:29
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:59
|
||||
msgid "POS [M]"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:30
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:61
|
||||
msgid "POS [L]"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:31
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:63
|
||||
msgid "Astrahus"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:32
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:65
|
||||
msgid "Fortizar"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:33
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:67
|
||||
msgid "Keepstar"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:34
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:69
|
||||
msgid "Raitaru"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:35
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:71
|
||||
msgid "Azbel"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:36
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:73
|
||||
msgid "Sotiyo"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:37
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:75
|
||||
msgid "Athanor"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:38
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:77
|
||||
msgid "Tatara"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:39
|
||||
msgid "Pharolux Cyno Beacon"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:40
|
||||
msgid "Tenebrex Cyno Jammer"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:41
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:83
|
||||
msgid "Ansiblex Jump Gate"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:42
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:85
|
||||
msgid "Moon Mining Cycle"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:43
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:87
|
||||
msgid "Metenox Moon Drill"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:44
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:89
|
||||
msgid "Other"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:51
|
||||
msgid "Not Specified"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:52
|
||||
msgid "Shield"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:53
|
||||
msgid "Armor"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:54
|
||||
msgid "Hull"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:18
|
||||
#: allianceauth/timerboard/models.py:55
|
||||
msgid "Final"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:19
|
||||
#: allianceauth/timerboard/models.py:56
|
||||
msgid "Anchoring"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:20
|
||||
#: allianceauth/timerboard/models.py:57
|
||||
msgid "Unanchoring"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/models.py:58
|
||||
msgid "Abandoned"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/dashboard.timers.html:7
|
||||
#: allianceauth/timerboard/templates/timerboard/view.html:53
|
||||
msgid "Upcoming Timers"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/dashboard.timers.html:14
|
||||
#: allianceauth/timerboard/templates/timerboard/dashboard.timers.html:15
|
||||
msgid "Timer"
|
||||
msgstr ""
|
||||
|
||||
@@ -2626,78 +2767,14 @@ msgstr ""
|
||||
msgid "Structure"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:64
|
||||
msgid "POCO"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:70
|
||||
msgid "I-HUB"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:76
|
||||
msgid "TCU"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:82
|
||||
msgid "POS [S]"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:88
|
||||
msgid "POS [M]"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:94
|
||||
msgid "POS [L]"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:100
|
||||
msgid "Astrahus"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:106
|
||||
msgid "Fortizar"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:112
|
||||
msgid "Keepstar"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:118
|
||||
msgid "Raitaru"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:124
|
||||
msgid "Azbel"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:130
|
||||
msgid "Sotiyo"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:136
|
||||
msgid "Athanor"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:142
|
||||
msgid "Tatara"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:148
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:79
|
||||
msgid "Cyno Beacon"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:154
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:81
|
||||
msgid "Cyno Jammer"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:160
|
||||
msgid "Ansiblex Jump Gate"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/timertable.html:166
|
||||
msgid "Moon Mining Cycle"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/timerboard/templates/timerboard/view.html:9
|
||||
msgid "Structure Timer Management"
|
||||
msgstr ""
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
allianceauth/locale/nl_NL/LC_MESSAGES/django.mo
Normal file
BIN
allianceauth/locale/nl_NL/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
2864
allianceauth/locale/nl_NL/LC_MESSAGES/django.po
Normal file
2864
allianceauth/locale/nl_NL/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
allianceauth/locale/pl_PL/LC_MESSAGES/django.mo
Normal file
BIN
allianceauth/locale/pl_PL/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
2923
allianceauth/locale/pl_PL/LC_MESSAGES/django.po
Normal file
2923
allianceauth/locale/pl_PL/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,7 @@
|
||||
{% endif %}>
|
||||
</i>
|
||||
<a
|
||||
class="nav-link flex-fill align-self-center me-auto"
|
||||
class="nav-link flex-fill align-self-center me-auto {% if item.navactive %}{% navactive request item.navactive|join:' ' %}{% endif %}"
|
||||
{% if item.is_folder %}
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
|
||||
@@ -60,15 +60,17 @@
|
||||
<li>
|
||||
<a class="dropdown-item" href="https://discord.gg/fjnHAmk" title="Alliance Auth Discord"><i class="fa-brands fa-discord fa-fw"></i> Alliance Auth Discord</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="https://gitlab.com/allianceauth/allianceauth" title="Alliance Auth Git"><i class="fa-brands fa-gitlab fa-fw"></i> Alliance Auth Git</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="{% url 'admin:index' %}">
|
||||
<i class="fa-solid fa-gear fa-fw"></i> {% translate "Admin" %}
|
||||
</a>
|
||||
<a class="dropdown-item" href="https://gitlab.com/allianceauth/allianceauth" title="Alliance Auth Git"><i class="fa-brands fa-gitlab fa-fw"></i> Alliance Auth Git</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if user.is_staff %}
|
||||
<li>
|
||||
<a class="dropdown-item" href="{% url 'admin:index' %}">
|
||||
<i class="fa-solid fa-gear fa-fw"></i> {% translate "Admin" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
{% if user.is_authenticated %}
|
||||
<li>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<ul id="sidebar-menu" class="navbar-nav flex-column mb-auto overflow-auto pt-2">
|
||||
<li class="d-flex flex-wrap m-2 p-2 pt-0 pb-0 mt-0 mb-0 me-0 pe-0">
|
||||
<i class="nav-link fas fa-tachometer-alt fa-fw align-self-center me-3 {% navactive request 'authentication:dashboard' %}"></i>
|
||||
<a class="nav-link flex-fill align-self-center" href="{% url 'authentication:dashboard' %}">
|
||||
<a class="nav-link flex-fill align-self-center {% navactive request 'authentication:dashboard' %}" href="{% url 'authentication:dashboard' %}">
|
||||
{% translate "Dashboard" %}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -98,6 +98,10 @@ def render_menu(request: HttpRequest) -> List[RenderedMenuItem]:
|
||||
|
||||
if item.is_app_item:
|
||||
rendered_item = _render_app_item(request, hook_items, item, bs5_template)
|
||||
if rendered_item.html == "":
|
||||
# If there is no content dont render it.
|
||||
# This item has probably been hidden by permissions
|
||||
continue
|
||||
elif item.is_link_item:
|
||||
rendered_item = _render_link_item(request, item, bs5_template)
|
||||
elif item.is_folder:
|
||||
|
||||
@@ -19,6 +19,11 @@ def create_user(permissions=None, **kwargs) -> User:
|
||||
return user
|
||||
|
||||
|
||||
def create_menu_item_hook_class(**kwargs) -> MenuItemHook:
|
||||
num = next(counter_menu_item_hook)
|
||||
return type(f"GeneratedMenuItem{num}", (MenuItemHook,), {})
|
||||
|
||||
|
||||
def create_menu_item_hook(**kwargs) -> MenuItemHook:
|
||||
num = next(counter_menu_item_hook)
|
||||
new_class = type(f"GeneratedMenuItem{num}", (MenuItemHook,), {})
|
||||
|
||||
@@ -14,6 +14,7 @@ from allianceauth.menu.tests.factories import (
|
||||
create_folder_menu_item,
|
||||
create_link_menu_item,
|
||||
create_menu_item_from_hook,
|
||||
create_menu_item_hook_class,
|
||||
create_menu_item_hook_function,
|
||||
create_rendered_menu_item,
|
||||
)
|
||||
@@ -177,6 +178,44 @@ class TestRenderDefaultMenu(TestCase):
|
||||
self.assertEqual(menu[0].menu_item.text, "Alpha")
|
||||
self.assertEqual(menu[1].menu_item.text, "Bravo")
|
||||
|
||||
def test_should_remove_empty_folders_with_items_hidden(self, mock_get_hooks):
|
||||
# given
|
||||
|
||||
class TestHook(create_menu_item_hook_class()):
|
||||
text = "Dummy App No Data"
|
||||
classes = "fa-solid fa-users-gear"
|
||||
url_name = "groupmanagement:management"
|
||||
|
||||
def render(Self, request):
|
||||
# simulate no perms
|
||||
return ""
|
||||
|
||||
params = {
|
||||
"text": "Alpha",
|
||||
"classes": "fa-solid fa-users-gear",
|
||||
"url_name": "groupmanagement:management",
|
||||
}
|
||||
|
||||
alpha = TestHook(**params)
|
||||
|
||||
hooks = [lambda: alpha]
|
||||
|
||||
mock_get_hooks.return_value = hooks
|
||||
|
||||
folder = create_folder_menu_item(text="Folder", order=2)
|
||||
create_menu_item_from_hook(hooks[0], parent=folder)
|
||||
create_link_menu_item(text="Bravo", order=3) # this is all that should show
|
||||
|
||||
request = self.factory.get("/")
|
||||
|
||||
# when
|
||||
result = render_menu(request)
|
||||
|
||||
# then
|
||||
menu = list(result)
|
||||
self.assertEqual(len(menu), 1)
|
||||
self.assertEqual(menu[0].menu_item.text, "Bravo")
|
||||
|
||||
def test_should_not_include_hidden_items(self, mock_get_hooks):
|
||||
# given
|
||||
mock_get_hooks.return_value = []
|
||||
@@ -196,7 +235,6 @@ class TestRenderDefaultMenu(TestCase):
|
||||
self.assertEqual(menu[1].menu_item.text, "Charlie")
|
||||
|
||||
def test_should_not_render_hidden_folders(self, mock_get_hooks):
|
||||
# given
|
||||
# given
|
||||
menu = [
|
||||
create_menu_item_hook_function(text="Charlie", count=42),
|
||||
|
||||
@@ -1,41 +1,40 @@
|
||||
{% load i18n %}
|
||||
{% load evelinks %}
|
||||
|
||||
<div class="col-12 align-self-stretch py-2">
|
||||
<div class="col-12 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title text-center">{% translate "Upcoming Fleets" %}</h4>
|
||||
{% translate "Upcoming Fleets" as widget_title %}
|
||||
{% include "framework/dashboard/widget-title.html" with title=widget_title %}
|
||||
|
||||
<div class="card-body">
|
||||
<div>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<div>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">{% translate "Operation" %}</th>
|
||||
<th class="text-center">{% translate "Type" %}</th>
|
||||
<th class="text-center">{% translate "Form Up System" %}</th>
|
||||
<th class="text-center">{% translate "EVE Time" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for ops in timers %}
|
||||
<tr>
|
||||
<th class="text-center">{% translate "Operation" %}</th>
|
||||
<th class="text-center">{% translate "Type" %}</th>
|
||||
<th class="text-center">{% translate "Form Up System" %}</th>
|
||||
<th class="text-center">{% translate "EVE Time" %}</th>
|
||||
<td class="text-center">
|
||||
{{ ops.operation_name }}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
{{ ops.type }}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<a href="{{ ops.system|dotlan_solar_system_url }}">{{ ops.system }}</a>
|
||||
</td>
|
||||
<td class="text-center" nowrap>{{ ops.start | date:"Y-m-d H:i" }}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for ops in timers %}
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
{{ ops.operation_name }}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
{{ ops.type }}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<a href="{{ ops.system|dotlan_solar_system_url }}">{{ ops.system }}</a>
|
||||
</td>
|
||||
<td class="text-center" nowrap>{{ ops.start | date:"Y-m-d H:i" }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,6 +12,8 @@ from celery.schedules import crontab
|
||||
|
||||
from django.contrib import messages
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'allianceauth', # needs to be on top of this list to support favicons in Django admin (see https://gitlab.com/allianceauth/allianceauth/-/issues/1301)
|
||||
'django.contrib.admin',
|
||||
@@ -22,6 +24,7 @@ INSTALLED_APPS = [
|
||||
'django.contrib.staticfiles',
|
||||
'django.contrib.humanize',
|
||||
'django_celery_beat',
|
||||
'solo',
|
||||
'bootstrapform',
|
||||
'django_bootstrap5', # https://github.com/zostera/django-bootstrap5
|
||||
'sortedm2m',
|
||||
@@ -39,6 +42,7 @@ INSTALLED_APPS = [
|
||||
'allianceauth.theme.darkly',
|
||||
'allianceauth.theme.flatly',
|
||||
'allianceauth.theme.materia',
|
||||
"allianceauth.custom_css",
|
||||
]
|
||||
|
||||
SECRET_KEY = "wow I'm a really bad default secret key"
|
||||
@@ -91,17 +95,20 @@ LOCALE_PATHS = (
|
||||
os.path.join(BASE_DIR, 'locale/'),
|
||||
)
|
||||
|
||||
LANGUAGES = (
|
||||
("en", "English"),
|
||||
("de", "German"),
|
||||
("es", "Spanish"),
|
||||
("zh-hans", "Chinese Simplified"),
|
||||
("ru", "Russian"),
|
||||
("ko", "Korean"),
|
||||
("fr", "French"),
|
||||
("ja", "Japanese"),
|
||||
("it", "Italian"),
|
||||
("uk", "Ukrainian"),
|
||||
LANGUAGES = ( # Sorted by Language Code alphabetical order + English at top
|
||||
("en", _("English")),
|
||||
# ("cs-cz", _("Czech")), #Not yet at 50% translated
|
||||
("de", _("German")),
|
||||
("es", _("Spanish")),
|
||||
("it-it", _("Italian")),
|
||||
("ja", _("Japanese")),
|
||||
("ko-kr", _("Korean")),
|
||||
("fr-fr", _("French")),
|
||||
("nl-nl", _("Dutch")),
|
||||
("pl-pl", _("Polish")),
|
||||
("ru", _("Russian")),
|
||||
("uk", _("Ukrainian")),
|
||||
("zh-hans", _("Simplified Chinese")),
|
||||
)
|
||||
|
||||
TEMPLATES = [
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block url %}
|
||||
<a href="{{ service_url }}">{{ service_url }}</a>
|
||||
{% if username != '' %}
|
||||
<a href="mumble://{{ connect_url }}">{{ service_url }}</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block user %}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% load i18n %}
|
||||
<div id="esi-alert" class="col-12 align-self-stretch py-2 collapse">
|
||||
<div id="esi-alert" class="col-12 collapse">
|
||||
<div class="alert alert-warning">
|
||||
<p class="text-center ">{% translate 'Your Server received an ESI error response code of ' %}<b id="esi-code">?</b></p>
|
||||
<hr>
|
||||
@@ -23,7 +23,7 @@
|
||||
console.log("ESI Check: ", JSON.stringify(responseJson, null, 2));
|
||||
|
||||
const status = responseJson.status;
|
||||
if (status != 200) {
|
||||
if (status !== 200) {
|
||||
elemCode.textContent = status
|
||||
elemMessage.textContent = responseJson.data.error;
|
||||
new bootstrap.Collapse(elemCard, {
|
||||
|
||||
@@ -2,48 +2,43 @@
|
||||
{% load humanize %}
|
||||
|
||||
{% if notifications %}
|
||||
<div id="aa-dashboard-panel-admin-notifications" class="col-12 align-self-stretch pb-2">
|
||||
<div id="aa-dashboard-panel-admin-notifications" class="col-12 mb-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="w-100 align-self-stretch">
|
||||
<h4 class="ms-auto me-auto text-center">
|
||||
{% translate "Alliance Auth Notifications" %}
|
||||
</h4>
|
||||
{% translate "Alliance Auth Notifications" as widget_title %}
|
||||
{% include "framework/dashboard/widget-title.html" with title=widget_title %}
|
||||
|
||||
<div class="card-body">
|
||||
<ul class="list-group">
|
||||
{% for notif in notifications %}
|
||||
<li class="list-group-item">
|
||||
{% if notif.state == 'opened' %}
|
||||
<span class="badge bg-success">{% translate "Open" %}</span>
|
||||
{% else %}
|
||||
<span class="badge bg-danger">{% translate "Closed" %}</span>
|
||||
{% endif %}
|
||||
<a href="{{ notif.web_url }}" target="_blank">#{{ notif.iid }} {{ notif.title }}</a>
|
||||
</li>
|
||||
{% empty %}
|
||||
<div class="alert alert-primary" role="alert">
|
||||
{% translate "No notifications at this time" %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<div class="text-end">
|
||||
<a href="https://gitlab.com/allianceauth/allianceauth/issues" target="_blank" class="me-1">
|
||||
<span class="badge" style="background-color: rgb(230 83 40);">
|
||||
<i class="fab fa-gitlab" aria-hidden="true"></i>
|
||||
{% translate 'Powered by GitLab' %}
|
||||
</span>
|
||||
</a>
|
||||
<a href="https://discord.com/invite/fjnHAmk" target="_blank">
|
||||
<span class="badge" style="background-color: rgb(110 133 211);">
|
||||
<i class="fab fa-discord" aria-hidden="true"></i>
|
||||
{% translate 'Support Discord' %}
|
||||
</span>
|
||||
</a>
|
||||
<div>
|
||||
<ul class="list-group">
|
||||
{% for notif in notifications %}
|
||||
<li class="list-group-item">
|
||||
{% if notif.state == 'opened' %}
|
||||
<span class="badge bg-success me-2">{% translate "Open" %}</span>
|
||||
{% else %}
|
||||
<span class="badge bg-danger me-2">{% translate "Closed" %}</span>
|
||||
{% endif %}
|
||||
<a href="{{ notif.web_url }}" target="_blank">#{{ notif.iid }} {{ notif.title }}</a>
|
||||
</li>
|
||||
{% empty %}
|
||||
<div class="alert alert-primary" role="alert">
|
||||
{% translate "No notifications at this time" %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<div class="text-end pt-3">
|
||||
<a href="https://gitlab.com/allianceauth/allianceauth/issues" target="_blank" class="me-1 text-decoration-none">
|
||||
<span class="badge" style="background-color: rgb(230 83 40);">
|
||||
<i class="fab fa-gitlab" aria-hidden="true"></i>
|
||||
{% translate 'Powered by GitLab' %}
|
||||
</span>
|
||||
</a>
|
||||
<a href="https://discord.com/invite/fjnHAmk" target="_blank" class="text-decoration-none">
|
||||
<span class="badge" style="background-color: rgb(110 133 211);">
|
||||
<i class="fab fa-discord" aria-hidden="true"></i>
|
||||
{% translate 'Support Discord' %}
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -51,15 +46,14 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="col-12 align-self-stretch pb-2">
|
||||
<div class="col-12 mb-3">
|
||||
<div class="card">
|
||||
<div class="card-body d-flex flex-row flex-wrap">
|
||||
<div class="card-body row">
|
||||
<div id="aa-dashboard-panel-software-version" class="col-xl-6 col-lg-12 col-md-12 col-sm-12">
|
||||
<h4 class="ms-auto me-auto text-center">
|
||||
{% translate "Software Version" %}
|
||||
</h4>
|
||||
{% translate "Software Version" as widget_title %}
|
||||
{% include "framework/dashboard/widget-title.html" with title=widget_title %}
|
||||
|
||||
<div class="card-body">
|
||||
<div>
|
||||
<ul class="list-group list-group-horizontal w-100" role="group" aria-label="{% translate 'Software Version' %}">
|
||||
<li class="list-group-item w-100">
|
||||
<div class="btn h-100 w-100 cursor-default">
|
||||
@@ -98,11 +92,10 @@
|
||||
</div>
|
||||
|
||||
<div id="aa-dashboard-panel-task-queue" class="col-xl-6 col-lg-12 col-md-12 col-sm-12">
|
||||
<h4 class="ms-auto me-auto text-center">
|
||||
{% translate "Task Queue" %}
|
||||
</h4>
|
||||
{% translate "Task Queue" as widget_title %}
|
||||
{% include "framework/dashboard/widget-title.html" with title=widget_title %}
|
||||
|
||||
<div class="card-body">
|
||||
<div>
|
||||
<p>
|
||||
{% blocktranslate with total=tasks_total|intcomma latest=earliest_task|timesince|default:"?" %}
|
||||
Status of {{ total }} processed tasks • last {{ latest }}
|
||||
|
||||
@@ -29,56 +29,55 @@
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
{% if user.is_authenticated %}
|
||||
.nav-padding {
|
||||
padding-top: {% header_padding_size %} !important;
|
||||
}
|
||||
{% endif %}
|
||||
.nav-padding {
|
||||
padding-top: {% header_padding_size %} !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
{% block extra_css %}{% endblock extra_css %}
|
||||
|
||||
{% include 'custom_css/bundles/custom-css.html' %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{% if user.is_authenticated %}
|
||||
<!-- Top Menu, Blocks don't work in "include" tagged views -->
|
||||
<nav class="navbar navbar-expand-lg navbar-dark fixed-top bg-primary">
|
||||
<div class="container-fluid justify-content-start">
|
||||
{% if user.is_authenticated %}
|
||||
<a class="navbar-brand" data-bs-toggle="collapse" data-bs-target="#sidebar" role="button">
|
||||
<i class="fa-solid fa-bars ms-2 me-2"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
<!-- Top Menu, Blocks don't work in "include" tagged views -->
|
||||
<nav class="navbar navbar-expand-lg navbar-dark fixed-top bg-primary">
|
||||
<div class="container-fluid justify-content-start">
|
||||
<a class="navbar-brand" data-bs-toggle="collapse" data-bs-target="#sidebar" role="button">
|
||||
<i class="fa-solid fa-bars ms-2 me-2"></i>
|
||||
</a>
|
||||
|
||||
<div class="navbar-brand">
|
||||
{% block header_nav_brand %}{{ SITE_NAME }}{% endblock %}
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse ms-2 px-2" id="navbarexpand">
|
||||
<ul id="nav-left" class="nav navbar-nav me-auto">
|
||||
{% block header_nav_collapse_left %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
|
||||
<ul id="nav-right" class="nav navbar-nav">
|
||||
{% block header_nav_collapse_right %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
|
||||
<ul id="nav-right-character-control" class="nav navbar-nav">
|
||||
{% block header_nav_user_character_control %} <!-- Default to add char and swap main -->
|
||||
{% include 'allianceauth/top-menu-rh-default.html' %}
|
||||
{% endblock %}
|
||||
|
||||
{% include 'menu/menu-notification-block.html' %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<a class="navbar-toggler navbar-brand border-0 collapsed" data-bs-toggle="collapse" data-bs-target="#navbarexpand" aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation" style="margin-left: auto;">
|
||||
<i class="fa-solid fa-chevron-up"></i>
|
||||
</a>
|
||||
<div class="navbar-brand">
|
||||
{% block header_nav_brand %}{{ SITE_NAME }}{% endblock %}
|
||||
</div>
|
||||
</nav>
|
||||
{% endif %}
|
||||
|
||||
<div class="collapse navbar-collapse ms-2 px-2" id="navbarexpand">
|
||||
<ul id="nav-left" class="nav navbar-nav me-auto">
|
||||
{% block header_nav_collapse_left %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
|
||||
<ul id="nav-right" class="nav navbar-nav">
|
||||
{% block header_nav_collapse_right %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
|
||||
<ul id="nav-right-character-control" class="nav navbar-nav">
|
||||
{% block header_nav_user_character_control %} <!-- Default to add char and swap main -->
|
||||
{% include 'allianceauth/top-menu-rh-default.html' %}
|
||||
{% endblock %}
|
||||
|
||||
{% if user.is_authenticated %}
|
||||
{% include 'menu/menu-notification-block.html' %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<a class="navbar-toggler navbar-brand border-0 collapsed" data-bs-toggle="collapse" data-bs-target="#navbarexpand" aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation" style="margin-left: auto;">
|
||||
<i class="fa-solid fa-chevron-up"></i>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- End Top Menu -->
|
||||
|
||||
<!-- Body -->
|
||||
@@ -98,23 +97,27 @@
|
||||
|
||||
<script>
|
||||
(() => {
|
||||
// TODO Extend this to the groups in the sidebar too.
|
||||
// TODO Move to own JS file
|
||||
const sidebar = document.getElementById('sidebar');
|
||||
|
||||
sidebar.addEventListener("shown.bs.collapse", () => {
|
||||
localStorage.removeItem("sidebar_" + sidebar.id);
|
||||
sidebar.addEventListener('shown.bs.collapse', () => {
|
||||
localStorage.removeItem('sidebar_' + sidebar.id);
|
||||
});
|
||||
|
||||
sidebar.addEventListener("hidden.bs.collapse", () => {
|
||||
localStorage.setItem("sidebar_" + sidebar.id, true);
|
||||
sidebar.addEventListener('hidden.bs.collapse', () => {
|
||||
localStorage.setItem('sidebar_' + sidebar.id, 'closed');
|
||||
});
|
||||
|
||||
if (localStorage.getItem("sidebar_" + sidebar.id) === "true") {
|
||||
sidebar.classList.remove("show")
|
||||
if (localStorage.getItem('sidebar_' + sidebar.id) === 'closed') {
|
||||
sidebar.classList.remove('show')
|
||||
} else {
|
||||
sidebar.classList.add("show")
|
||||
}
|
||||
|
||||
const activeChildMenuItem = document.querySelector('#sidebar-menu li ul li a.active');
|
||||
if (activeChildMenuItem) {
|
||||
activeChildMenuItem.parentElement.parentElement.classList.add('show');
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,31 +1,37 @@
|
||||
{% extends "allianceauth/base-bs5.html" %}
|
||||
|
||||
{% load theme_tags %}
|
||||
|
||||
{% block page_title %}
|
||||
{{ error_title }}
|
||||
{% endblock page_title %}
|
||||
|
||||
{% block content %}
|
||||
<div>
|
||||
{% include "framework/header/page-header.html" with title=error_title %}
|
||||
<div class="d-flex flex-column" style="height: calc(100vh - {% header_padding_size %}); margin-top: -1rem; margin-bottom: -1rem;">
|
||||
<div class="d-flex flex-grow-1 justify-content-center align-items-center">
|
||||
<div>
|
||||
{% include "framework/header/page-header.html" with title=error_title %}
|
||||
|
||||
<div class="text-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="150"
|
||||
height="150"
|
||||
fill="currentColor"
|
||||
class="bi bi-exclamation-triangle"
|
||||
viewBox="0 0 16 16"
|
||||
>
|
||||
<path
|
||||
d="M7.938 2.016A.13.13 0 0 1 8.002 2a.13.13 0 0 1 .063.016.146.146 0 0 1 .054.057l6.857 11.667c.036.06.035.124.002.183a.163.163 0 0 1-.054.06.116.116 0 0 1-.066.017H1.146a.115.115 0 0 1-.066-.017.163.163 0 0 1-.054-.06.176.176 0 0 1 .002-.183L7.884 2.073a.147.147 0 0 1 .054-.057zm1.044-.45a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566z"
|
||||
/>
|
||||
<path
|
||||
d="M7.002 12a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 5.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995z"
|
||||
/>
|
||||
</svg>
|
||||
<div class="text-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="150"
|
||||
height="150"
|
||||
fill="currentColor"
|
||||
class="bi bi-exclamation-triangle"
|
||||
viewBox="0 0 16 16"
|
||||
>
|
||||
<path
|
||||
d="M7.938 2.016A.13.13 0 0 1 8.002 2a.13.13 0 0 1 .063.016.146.146 0 0 1 .054.057l6.857 11.667c.036.06.035.124.002.183a.163.163 0 0 1-.054.06.116.116 0 0 1-.066.017H1.146a.115.115 0 0 1-.066-.017.163.163 0 0 1-.054-.06.176.176 0 0 1 .002-.183L7.884 2.073a.147.147 0 0 1 .054-.057zm1.044-.45a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566z"
|
||||
/>
|
||||
<path
|
||||
d="M7.002 12a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 5.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<p class="text-center">{{ error_message }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-center">{{ error_message }}</p>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% load i18n %}
|
||||
|
||||
{% if user.is_authenticated %}
|
||||
<li class="nav-item">
|
||||
<a href="{% url 'authentication:add_character' %}" class="nav-link" title="{% translate 'Add Character' %}">
|
||||
<i class="fa-solid fa-plus"></i>
|
||||
@@ -12,3 +12,10 @@
|
||||
<span class="d-lg-none d-md-inline m-2">{% translate "Change Main" %}</span>
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item">
|
||||
<a href="{% url 'authentication:login' %}" class="nav-link" title="{% translate 'Sign In' %}">
|
||||
<i class="fa-solid fa-right-to-bracket fa-fw "></i> {% translate "Sign In" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
@@ -27,6 +27,7 @@ class BootstrapThemeHook(ThemeHook):
|
||||
self,
|
||||
"Bootstrap",
|
||||
"Powerful, extensible, and feature-packed frontend toolkit.",
|
||||
html_tags={"data-theme": "bootstrap"},
|
||||
css=CSS_STATICS,
|
||||
js=JS_STATICS,
|
||||
header_padding="3.5em"
|
||||
@@ -44,9 +45,9 @@ class BootstrapDarkThemeHook(ThemeHook):
|
||||
self,
|
||||
"Bootstrap Dark",
|
||||
"Powerful, extensible, and feature-packed frontend toolkit.",
|
||||
html_tags={"data-theme": "bootstrap-dark"},
|
||||
css=CSS_STATICS,
|
||||
js=JS_STATICS,
|
||||
html_tags="data-bs-theme=dark",
|
||||
header_padding="3.5em"
|
||||
)
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ class DarklyThemeHook(ThemeHook):
|
||||
self,
|
||||
"Darkly",
|
||||
"Flatly in night mode!",
|
||||
html_tags={"data-theme": "darkly"},
|
||||
css=[{
|
||||
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.3/darkly/bootstrap.min.css",
|
||||
"integrity": "sha512-HDszXqSUU0om4Yj5dZOUNmtwXGWDa5ppESlX98yzbBS+z+3HQ8a/7kcdI1dv+jKq+1V5b01eYurE7+yFjw6Rdg=="
|
||||
|
||||
@@ -13,6 +13,7 @@ class FlatlyThemeHook(ThemeHook):
|
||||
self,
|
||||
"Flatly",
|
||||
"Flat and modern!",
|
||||
html_tags={"data-theme": "flatly"},
|
||||
css=[{
|
||||
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.3/flatly/bootstrap.min.css",
|
||||
"integrity": "sha512-qoT4KwnRpAQ9uczPsw7GunsNmhRnYwSlE2KRCUPRQHSkDuLulCtDXuC2P/P6oqr3M5hoGagUG9pgHDPkD2zCDA=="
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
from typing import List, Optional
|
||||
from typing import List, Optional, Union
|
||||
|
||||
|
||||
class ThemeHook:
|
||||
"""
|
||||
Theme hook for injecting a Bootstrap 5 Theme and associated JS into alliance auth.
|
||||
these can be local or CDN delivered
|
||||
Theme hook for injecting a Bootstrap 5 Theme and associated JS into alliance auth.
|
||||
These can be local or CDN delivered.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -14,7 +14,7 @@ class ThemeHook:
|
||||
js: List[dict],
|
||||
css_template: Optional[str] = None,
|
||||
js_template: Optional[str] = None,
|
||||
html_tags: Optional[str] = "",
|
||||
html_tags: Optional[Union[dict, str]] = None,
|
||||
header_padding: Optional[str] = "4em"):
|
||||
"""
|
||||
:param name: Theme python name
|
||||
@@ -29,6 +29,10 @@ class ThemeHook:
|
||||
:type css_template: Optional[str], optional
|
||||
:param js_template: _description_, defaults to None
|
||||
:type js_template: Optional[str], optional
|
||||
:param html_tags: Attributes added to the `<html>` tag, defaults to None
|
||||
:type html_tags: Optional[dict|str], optional
|
||||
:param header_padding: Top padding, defaults to "4em"
|
||||
:type header_padding: Optional[str], optional
|
||||
"""
|
||||
self.name = name
|
||||
self.description = description
|
||||
@@ -41,7 +45,11 @@ class ThemeHook:
|
||||
self.css_template = css_template
|
||||
self.js_template = js_template
|
||||
|
||||
self.html_tags = html_tags
|
||||
self.html_tags = (
|
||||
" ".join([f"{key}={value}" for key, value in html_tags.items()])
|
||||
if isinstance(html_tags, dict)
|
||||
else html_tags
|
||||
)
|
||||
self.header_padding = header_padding
|
||||
def get_name(self):
|
||||
return f"{self.__class__.__module__}.{self.__class__.__name__}"
|
||||
|
||||
@@ -13,6 +13,7 @@ class MateriaThemeHook(ThemeHook):
|
||||
self,
|
||||
"Materia",
|
||||
"Material is the metaphor",
|
||||
html_tags={"data-theme": "materia"},
|
||||
css=[{
|
||||
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.3/materia/bootstrap.min.css",
|
||||
"integrity": "sha512-2S9Do+uTmZmmJpdmAcOKdUrK/YslcvAuRfIF2ws8+BW9AvZXMRZM+o8Wq+PZrfISD6ZlIaeCWWZAdeprXIoYuQ=="
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import logging
|
||||
import datetime
|
||||
import logging
|
||||
|
||||
from django import forms
|
||||
from django.utils import timezone
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .models import Timer, TimerType
|
||||
from .models import Timer
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -32,54 +33,28 @@ class TimerForm(forms.ModelForm):
|
||||
kwargs.update({'initial': initial})
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
structure_choices = [('POCO', 'POCO'),
|
||||
('I-HUB', 'I-HUB'),
|
||||
('TCU', 'TCU'),
|
||||
('POS[S]', 'POS[S]'),
|
||||
('POS[M]', 'POS[M]'),
|
||||
('POS[L]', 'POS[L]'),
|
||||
('Astrahus', 'Astrahus'),
|
||||
('Fortizar', 'Fortizar'),
|
||||
('Keepstar', 'Keepstar'),
|
||||
('Raitaru', 'Raitaru'),
|
||||
('Azbel', 'Azbel'),
|
||||
('Sotiyo', 'Sotiyo'),
|
||||
('Athanor', 'Athanor'),
|
||||
('Tatara', 'Tatara'),
|
||||
('Pharolux Cyno Beacon', 'Pharolux Cyno Beacon'),
|
||||
('Tenebrex Cyno Jammer', 'Tenebrex Cyno Jammer'),
|
||||
('Ansiblex Jump Gate', 'Ansiblex Jump Gate'),
|
||||
('Moon Mining Cycle', 'Moon Mining Cycle'),
|
||||
(_('Other'), _('Other'))]
|
||||
objective_choices = [('Friendly', _('Friendly')),
|
||||
('Hostile', _('Hostile')),
|
||||
('Neutral', _('Neutral'))]
|
||||
|
||||
details = forms.CharField(max_length=254, required=True, label=_('Details'))
|
||||
system = forms.CharField(max_length=254, required=True, label=_("System"))
|
||||
planet_moon = forms.CharField(max_length=254, label=_("Planet/Moon"), required=False, initial="")
|
||||
structure = forms.ChoiceField(choices=structure_choices, required=True, label=_("Structure Type"))
|
||||
timer_type = forms.ChoiceField(choices=TimerType.choices, label=_("Timer Type"))
|
||||
objective = forms.ChoiceField(choices=objective_choices, required=True, label=_("Objective"))
|
||||
structure = forms.ChoiceField(choices=Timer.Structure.choices, required=True, label=_("Structure Type"))
|
||||
timer_type = forms.ChoiceField(choices=Timer.TimerType.choices, label=_("Timer Type"))
|
||||
objective = forms.ChoiceField(choices=Timer.Objective.choices, required=True, label=_("Objective"))
|
||||
absolute_checkbox = forms.BooleanField(label=_("Absolute Timer"), required=False, initial=False)
|
||||
absolute_time = forms.CharField(required=False,label=_("Date and Time"))
|
||||
days_left = forms.IntegerField(required=False, label=_("Days Remaining"), validators=[MinValueValidator(0)])
|
||||
hours_left = forms.IntegerField(required=False, label=_("Hours Remaining"),
|
||||
validators=[MinValueValidator(0), MaxValueValidator(23)])
|
||||
minutes_left = forms.IntegerField(required=False, label=_("Minutes Remaining"),
|
||||
validators=[MinValueValidator(0), MaxValueValidator(59)])
|
||||
minutes_left = forms.IntegerField(required=False, label=_("Minutes Remaining"), validators=[MinValueValidator(0), MaxValueValidator(59)])
|
||||
important = forms.BooleanField(label=_("Important"), required=False)
|
||||
corp_timer = forms.BooleanField(label=_("Corp-Restricted"), required=False)
|
||||
|
||||
|
||||
def save(self, commit=True):
|
||||
timer = super().save(commit=False)
|
||||
|
||||
# Get character
|
||||
character = self.user.profile.main_character
|
||||
corporation = character.corporation
|
||||
logger.debug("Determined timer save request on behalf "
|
||||
"of character {} corporation {}".format(character, corporation))
|
||||
logger.debug(f"Determined timer save request on behalf of character {character} corporation {corporation}")
|
||||
|
||||
days_left = self.cleaned_data['days_left']
|
||||
hours_left = self.cleaned_data['hours_left']
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# Generated by Django 4.2 on 2024-09-09 03:45
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('timerboard', '0005_alter_timer_planet_moon'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='timer',
|
||||
name='objective',
|
||||
field=models.CharField(choices=[('Friendly', 'Friendly'), ('Hostile', 'Hostile'), ('Neutral', 'Neutral')], default='Neutral', max_length=254),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='timer',
|
||||
name='structure',
|
||||
field=models.CharField(choices=[('POCO', 'POCO'), ('Orbital Skyhook', 'Orbital Skyhook'), ('I-HUB', 'I-HUB'), ('TCU', 'TCU'), ('POS[S]', 'POS [S]'), ('POS[M]', 'POS [M]'), ('POS[L]', 'POS [L]'), ('Astrahus', 'Astrahus'), ('Fortizar', 'Fortizar'), ('Keepstar', 'Keepstar'), ('Raitaru', 'Raitaru'), ('Azbel', 'Azbel'), ('Sotiyo', 'Sotiyo'), ('Athanor', 'Athanor'), ('Tatara', 'Tatara'), ('Pharolux Cyno Beacon', 'Pharolux Cyno Beacon'), ('Tenebrex Cyno Jammer', 'Tenebrex Cyno Jammer'), ('Ansiblex Jump Gate', 'Ansiblex Jump Gate'), ('Moon Mining Cycle', 'Moon Mining Cycle'), ('Metenox Moon Drill', 'Metenox Moon Drill'), ('Other', 'Other')], default='Other', max_length=254),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='timer',
|
||||
name='timer_type',
|
||||
field=models.CharField(choices=[('UNSPECIFIED', 'Not Specified'), ('SHIELD', 'Shield'), ('ARMOR', 'Armor'), ('HULL', 'Hull'), ('FINAL', 'Final'), ('ANCHORING', 'Anchoring'), ('UNANCHORING', 'Unanchoring'), ('ABANDONED', 'Abandoned')], default='UNSPECIFIED', max_length=254),
|
||||
),
|
||||
]
|
||||
@@ -6,34 +6,63 @@ from allianceauth.eveonline.models import EveCharacter
|
||||
from allianceauth.eveonline.models import EveCorporationInfo
|
||||
|
||||
|
||||
class TimerType(models.TextChoices):
|
||||
"""
|
||||
Choices for Timer Type
|
||||
"""
|
||||
|
||||
UNSPECIFIED = "UNSPECIFIED", _("Not Specified")
|
||||
SHIELD = "SHIELD", _("Shield")
|
||||
ARMOR = "ARMOR", _("Armor")
|
||||
HULL = "HULL", _("Hull")
|
||||
FINAL = "FINAL", _("Final")
|
||||
ANCHORING = "ANCHORING", _("Anchoring")
|
||||
UNANCHORING = "UNANCHORING", _("Unanchoring")
|
||||
|
||||
|
||||
class Timer(models.Model):
|
||||
class Meta:
|
||||
ordering = ['eve_time']
|
||||
class Objective(models.TextChoices):
|
||||
"""
|
||||
Choices for Objective Type
|
||||
"""
|
||||
|
||||
FRIENDLY = "Friendly", _("Friendly")
|
||||
HOSTILE = "Hostile", _("Hostile")
|
||||
NEUTRAL = "Neutral", _("Neutral")
|
||||
|
||||
class Structure(models.TextChoices):
|
||||
"""
|
||||
Choices for Structure Type
|
||||
"""
|
||||
|
||||
POCO = "POCO", _("POCO")
|
||||
ORBITALSKYHOOK = "Orbital Skyhook", _("Orbital Skyhook")
|
||||
IHUB = "I-HUB", _("I-HUB")
|
||||
TCU = "TCU", _("TCU") # Pending Remval
|
||||
POSS = "POS[S]", _("POS [S]")
|
||||
POSM = "POS[M]", _("POS [M]")
|
||||
POSL = "POS[L]", _("POS [L]")
|
||||
ASTRAHUS = "Astrahus", _("Astrahus")
|
||||
FORTIZAR = "Fortizar", _("Fortizar")
|
||||
KEEPSTAR = "Keepstar", _("Keepstar")
|
||||
RAITARU = "Raitaru", _("Raitaru")
|
||||
AZBEL = "Azbel", _("Azbel")
|
||||
SOTIYO = "Sotiyo", _("Sotiyo")
|
||||
ATHANOR = "Athanor", _("Athanor")
|
||||
TATARA = "Tatara", _("Tatara")
|
||||
PHAROLUX = "Pharolux Cyno Beacon", _("Pharolux Cyno Beacon")
|
||||
TENEBREX = "Tenebrex Cyno Jammer", _("Tenebrex Cyno Jammer")
|
||||
ANSIBLEX = "Ansiblex Jump Gate", _("Ansiblex Jump Gate")
|
||||
MOONPOP = "Moon Mining Cycle", _("Moon Mining Cycle")
|
||||
METENOX = "Metenox Moon Drill", _("Metenox Moon Drill")
|
||||
OTHER = "Other", _("Other")
|
||||
|
||||
class TimerType(models.TextChoices):
|
||||
"""
|
||||
Choices for Timer Type
|
||||
"""
|
||||
|
||||
UNSPECIFIED = "UNSPECIFIED", _("Not Specified")
|
||||
SHIELD = "SHIELD", _("Shield")
|
||||
ARMOR = "ARMOR", _("Armor")
|
||||
HULL = "HULL", _("Hull")
|
||||
FINAL = "FINAL", _("Final")
|
||||
ANCHORING = "ANCHORING", _("Anchoring")
|
||||
UNANCHORING = "UNANCHORING", _("Unanchoring")
|
||||
ABANDONED = "ABANDONED", _("Abandoned")
|
||||
|
||||
details = models.CharField(max_length=254, default="")
|
||||
system = models.CharField(max_length=254, default="")
|
||||
planet_moon = models.CharField(max_length=254, blank=True, default="")
|
||||
structure = models.CharField(max_length=254, default="")
|
||||
timer_type = models.CharField(
|
||||
max_length=254,
|
||||
choices=TimerType.choices,
|
||||
default=TimerType.UNSPECIFIED,
|
||||
)
|
||||
objective = models.CharField(max_length=254, default="")
|
||||
structure = models.CharField(max_length=254,choices=Structure.choices,default=Structure.OTHER)
|
||||
timer_type = models.CharField(max_length=254,choices=TimerType.choices,default=TimerType.UNSPECIFIED)
|
||||
objective = models.CharField(max_length=254, choices=Objective.choices, default=Objective.NEUTRAL)
|
||||
eve_time = models.DateTimeField()
|
||||
important = models.BooleanField(default=False)
|
||||
eve_character = models.ForeignKey(EveCharacter, null=True, on_delete=models.SET_NULL)
|
||||
@@ -41,5 +70,8 @@ class Timer(models.Model):
|
||||
corp_timer = models.BooleanField(default=False)
|
||||
user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
return str(self.system) + ' ' + str(self.details)
|
||||
|
||||
class Meta:
|
||||
ordering = ['eve_time']
|
||||
|
||||
@@ -1,59 +1,59 @@
|
||||
{% load i18n %}
|
||||
{% load evelinks %}
|
||||
|
||||
<div class="col-12 align-self-stretch py-2">
|
||||
<div class="col-12 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title text-center">{% translate "Upcoming Timers" %}</h4>
|
||||
<div class="card-body">
|
||||
<div>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">{% translate "Details" %}</th>
|
||||
<th class="text-center">{% translate "Timer" %}</th>
|
||||
<th class="text-center">{% translate "Type" %}</th>
|
||||
<th class="text-center">{% translate "System" %}</th>
|
||||
<th class="text-center">{% translate "EVE Time" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% translate "Upcoming Timers" as widget_title %}
|
||||
{% include "framework/dashboard/widget-title.html" with title=widget_title %}
|
||||
|
||||
<tbody>
|
||||
{% for timer in timers %}
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
{{ timer.details }}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
{{ timer.get_timer_type_display }}
|
||||
</td>
|
||||
<td class="text-center" nowrap>
|
||||
{% if timer.objective == "Hostile" %}
|
||||
<div class="badge bg-danger">
|
||||
{% translate "Hostile" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if timer.objective == "Friendly" %}
|
||||
<div class="badge bg-primary">
|
||||
{% translate "Friendly" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if timer.objective == "Neutral" %}
|
||||
<div class="badge bg-default">
|
||||
{% translate "Neutral" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-center"><a href="{{ timer.system|dotlan_solar_system_url }}">
|
||||
{{ timer.system }} {{ timer.planet_moon }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-center" nowrap>{{ timer.eve_time | date:"Y-m-d H:i" }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">{% translate "Details" %}</th>
|
||||
<th class="text-center">{% translate "Timer" %}</th>
|
||||
<th class="text-center">{% translate "Type" %}</th>
|
||||
<th class="text-center">{% translate "System" %}</th>
|
||||
<th class="text-center">{% translate "EVE Time" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for timer in timers %}
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
{{ timer.details }}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
{{ timer.get_timer_type_display }}
|
||||
</td>
|
||||
<td class="text-center" nowrap>
|
||||
{% if timer.objective == "Hostile" %}
|
||||
<div class="badge bg-danger">
|
||||
{% translate "Hostile" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if timer.objective == "Friendly" %}
|
||||
<div class="badge bg-primary">
|
||||
{% translate "Friendly" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if timer.objective == "Neutral" %}
|
||||
<div class="badge bg-secondary">
|
||||
{% translate "Neutral" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-center"><a href="{{ timer.system|dotlan_solar_system_url }}">
|
||||
{{ timer.system }} {{ timer.planet_moon }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-center" nowrap>{{ timer.eve_time | date:"Y-m-d H:i" }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -18,174 +18,85 @@
|
||||
</tr>
|
||||
|
||||
{% for timer in timers %}
|
||||
{% if timer.important == True %}
|
||||
<tr class="danger">
|
||||
{% else %}
|
||||
<tr class="info">
|
||||
{% endif %}
|
||||
<tr class="{% if timer.important == True %}bg-danger bg-opacity-25{% else %}bg-info bg-opacity-25{% endif %}">
|
||||
|
||||
<td style="width: 150px;" class="text-center">
|
||||
{{ timer.details }}
|
||||
|
||||
{% if timer.timer_type != 'UNSPECIFIED' %}
|
||||
<br>({{ timer.get_timer_type_display }})
|
||||
<br />
|
||||
({{ timer.get_timer_type_display }})
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
<td class="text-center">
|
||||
{% if timer.objective == "Hostile" %}
|
||||
<div class="badge bg-danger">
|
||||
{% translate "Hostile" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.objective == "Friendly" %}
|
||||
<div class="badge bg-primary">
|
||||
{% translate "Friendly" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.objective == "Neutral" %}
|
||||
<div class="badge bg-default">
|
||||
{% translate "Neutral" %}
|
||||
</div>
|
||||
<div class="badge bg-danger">{% translate "Hostile" %}</div>
|
||||
{% elif timer.objective == "Friendly" %}
|
||||
<div class="badge bg-primary">{% translate "Friendly" %}</div>
|
||||
{% elif timer.objective == "Neutral" %}
|
||||
<div class="badge bg-secondary">{% translate "Neutral" %}</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
<td class="text-center">
|
||||
<a href="{{ timer.system|dotlan_solar_system_url }}">
|
||||
{{ timer.system }} {{ timer.planet_moon }}
|
||||
</a>
|
||||
<a href="{{ timer.system|dotlan_solar_system_url }}">{{ timer.system }} {{ timer.planet_moon }}</a>
|
||||
</td>
|
||||
|
||||
<td class="text-center">
|
||||
{% if timer.structure == "POCO" %}
|
||||
<div class="badge bg-info">
|
||||
{% translate "POCO" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "I-HUB" %}
|
||||
<div class="badge bg-warning">
|
||||
{% translate "I-HUB" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "TCU" %}
|
||||
<div class="badge bg-danger">
|
||||
{% translate "TCU" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "POS[S]" %}
|
||||
<div class="badge bg-info">
|
||||
{% translate "POS [S]" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "POS[M]" %}
|
||||
<div class="badge bg-info">
|
||||
{% translate "POS [M]" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "POS[L]" %}
|
||||
<div class="badge bg-info">
|
||||
{% translate "POS [L]" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "Citadel[M]" or timer.structure == "Astrahus" %}
|
||||
<div class="badge bg-danger">
|
||||
{% translate "Astrahus" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "Citadel[L]" or timer.structure == "Fortizar" %}
|
||||
<div class="badge bg-danger">
|
||||
{% translate "Fortizar" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "Citadel[XL]" or timer.structure == "Keepstar" %}
|
||||
<div class="badge bg-danger">
|
||||
{% translate "Keepstar" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "Engineering Complex[M]" or timer.structure == "Raitaru" %}
|
||||
<div class="badge bg-warning">
|
||||
{% translate "Raitaru" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "Engineering Complex[L]" or timer.structure == "Azbel" %}
|
||||
<div class="badge bg-warning">
|
||||
{% translate "Azbel" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "Engineering Complex[XL]" or timer.structure == "Sotiyo" %}
|
||||
<div class="badge bg-warning">
|
||||
{% translate "Sotiyo" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "Refinery[M]" or timer.structure == "Athanor" %}
|
||||
<div class="badge bg-warning">
|
||||
{% translate "Athanor" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "Refinery[L]" or timer.structure == "Tatara"%}
|
||||
<div class="badge bg-warning">
|
||||
{% translate "Tatara" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "Cyno Beacon" or timer.structure == "Pharolux Cyno Beacon" %}
|
||||
<div class="badge bg-warning">
|
||||
{% translate "Cyno Beacon" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "Cyno Jammer" or timer.structure == "Tenebrex Cyno Jammer" %}
|
||||
<div class="badge bg-warning">
|
||||
{% translate "Cyno Jammer" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "Jump Gate" or timer.structure == "Ansiblex Jump Gate" %}
|
||||
<div class="badge bg-warning">
|
||||
{% translate "Ansiblex Jump Gate" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "Moon Mining Cycle" %}
|
||||
<div class="badge bg-success">
|
||||
{% translate "Moon Mining Cycle" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if timer.structure == "Other" %}
|
||||
<div class="badge bg-default">
|
||||
{% translate "Other" %}
|
||||
</div>
|
||||
<div class="badge bg-info">{% translate "POCO" %}</div>
|
||||
{% elif timer.structure == "Orbital Skyhook" %}
|
||||
<div class="badge bg-warning">{% translate "Orbital Skyhook" %}</div>
|
||||
{% elif timer.structure == "I-HUB" %}
|
||||
<div class="badge bg-warning">{% translate "I-HUB" %}</div>
|
||||
{% elif timer.structure == "TCU" %} {% comment %} Pending Removal {% endcomment %}
|
||||
<div class="badge bg-secondary">{% translate "TCU" %}</div>
|
||||
{% elif timer.structure == "POS[S]" %}
|
||||
<div class="badge bg-info">{% translate "POS [S]" %}</div>
|
||||
{% elif timer.structure == "POS[M]" %}
|
||||
<div class="badge bg-info">{% translate "POS [M]" %}</div>
|
||||
{% elif timer.structure == "POS[L]" %}
|
||||
<div class="badge bg-info">{% translate "POS [L]" %}</div>
|
||||
{% elif timer.structure == "Citadel[M]" or timer.structure == "Astrahus" %}
|
||||
<div class="badge bg-danger">{% translate "Astrahus" %}</div>
|
||||
{% elif timer.structure == "Citadel[L]" or timer.structure == "Fortizar" %}
|
||||
<div class="badge bg-danger">{% translate "Fortizar" %}</div>
|
||||
{% elif timer.structure == "Citadel[XL]" or timer.structure == "Keepstar" %}
|
||||
<div class="badge bg-danger">{% translate "Keepstar" %}</div>
|
||||
{% elif timer.structure == "Engineering Complex[M]" or timer.structure == "Raitaru" %}
|
||||
<div class="badge bg-warning">{% translate "Raitaru" %}</div>
|
||||
{% elif timer.structure == "Engineering Complex[L]" or timer.structure == "Azbel" %}
|
||||
<div class="badge bg-warning">{% translate "Azbel" %}</div>
|
||||
{% elif timer.structure == "Engineering Complex[XL]" or timer.structure == "Sotiyo" %}
|
||||
<div class="badge bg-danger">{% translate "Sotiyo" %}</div>
|
||||
{% elif timer.structure == "Refinery[M]" or timer.structure == "Athanor" %}
|
||||
<div class="badge bg-warning">{% translate "Athanor" %}</div>
|
||||
{% elif timer.structure == "Refinery[L]" or timer.structure == "Tatara" %}
|
||||
<div class="badge bg-warning">{% translate "Tatara" %}</div>
|
||||
{% elif timer.structure == "Cyno Beacon" or timer.structure == "Pharolux Cyno Beacon" %}
|
||||
<div class="badge bg-warning">{% translate "Cyno Beacon" %}</div>
|
||||
{% elif timer.structure == "Cyno Jammer" or timer.structure == "Tenebrex Cyno Jammer" %}
|
||||
<div class="badge bg-warning">{% translate "Cyno Jammer" %}</div>
|
||||
{% elif timer.structure == "Jump Gate" or timer.structure == "Ansiblex Jump Gate" %}
|
||||
<div class="badge bg-warning">{% translate "Ansiblex Jump Gate" %}</div>
|
||||
{% elif timer.structure == "Moon Mining Cycle" %}
|
||||
<div class="badge bg-success">{% translate "Moon Mining Cycle" %}</div>
|
||||
{% elif timer.structure == "Metenox Moon Drill" %}
|
||||
<div class="badge bg-warning">{% translate "Metenox Moon Drill" %}</div>
|
||||
{% elif timer.structure == "Other" %}
|
||||
<div class="badge bg-secondary">{% translate "Other" %}</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
<td class="text-center" nowrap>
|
||||
{{ timer.eve_time | date:"Y-m-d H:i" }}
|
||||
</td>
|
||||
<td class="text-center" nowrap>{{ timer.eve_time | date:"Y-m-d H:i" }}</td>
|
||||
|
||||
<td class="text-center" nowrap>
|
||||
<div id="localtime{{ timer.id }}"></div>
|
||||
<div id="countdown{{ timer.id }}"></div>
|
||||
</td>
|
||||
|
||||
<td class="text-center">
|
||||
{{ timer.eve_character.character_name }}
|
||||
</td>
|
||||
<td class="text-center">{{ timer.eve_character.character_name }}</td>
|
||||
|
||||
{% if perms.auth.timer_management %}
|
||||
<td class="text-center">
|
||||
|
||||
@@ -167,8 +167,8 @@ class TimerboardViewsTestCase(WebTest):
|
||||
form['details'] = 'details'
|
||||
form['system'] = 'jita'
|
||||
form['planet_moon'] = '4-4'
|
||||
form['structure'] = TimerForm.structure_choices[0][0]
|
||||
form['objective'] = TimerForm.objective_choices[0][0]
|
||||
form['structure'] = Timer.Structure.choices[0][0]
|
||||
form['objective'] = Timer.Objective.choices[0][0]
|
||||
form['days_left'] = 1
|
||||
form['hours_left'] = 2
|
||||
form['minutes_left'] = 3
|
||||
@@ -206,8 +206,8 @@ class TimerboardViewsTestCase(WebTest):
|
||||
form['details'] = 'detailsUNIQUE'
|
||||
form['system'] = 'jita'
|
||||
form['planet_moon'] = '4-4'
|
||||
form['structure'] = TimerForm.structure_choices[0][0]
|
||||
form['objective'] = TimerForm.objective_choices[0][0]
|
||||
form['structure'] = Timer.Structure.choices[0][0]
|
||||
form['objective'] = Timer.Objective.choices[0][0]
|
||||
form['days_left'] = 1
|
||||
form['hours_left'] = 2
|
||||
form['minutes_left'] = 3
|
||||
|
||||
@@ -97,7 +97,7 @@ class EditTimerView(TimerManagementView, AddUpdateMixin, UpdateView):
|
||||
|
||||
|
||||
class RemoveTimerView(TimerManagementView, DeleteView):
|
||||
form_class = TimerForm
|
||||
pass
|
||||
|
||||
|
||||
def dashboard_timers(request):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
PROTOCOL=https://
|
||||
AUTH_SUBDOMAIN=%AUTH_SUBDOMAIN%
|
||||
DOMAIN=%DOMAIN%
|
||||
AA_DOCKER_TAG=registry.gitlab.com/allianceauth/allianceauth/auth:v4.0.0rc1
|
||||
AA_DOCKER_TAG=registry.gitlab.com/allianceauth/allianceauth/auth:v4.3.1
|
||||
|
||||
# Nginx Proxy Manager
|
||||
PROXY_HTTP_PORT=80
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
FROM python:3.11-slim
|
||||
ARG AUTH_VERSION=v4.0.0rc1
|
||||
ARG AUTH_VERSION=v4.3.1
|
||||
ARG AUTH_PACKAGE=allianceauth==${AUTH_VERSION}
|
||||
ENV AUTH_USER=allianceauth
|
||||
ENV AUTH_GROUP=allianceauth
|
||||
@@ -9,21 +9,21 @@ ENV AUTH_HOME=/home/allianceauth
|
||||
|
||||
# Setup user and directory permissions
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
RUN groupadd -g 61000 ${AUTH_GROUP}
|
||||
RUN useradd -g 61000 -l -M -s /bin/false -u 61000 ${AUTH_USER}
|
||||
RUN mkdir -p ${STATIC_BASE} \
|
||||
&& chown ${AUTH_USERGROUP} ${STATIC_BASE} \
|
||||
&& mkdir -p ${AUTH_HOME} \
|
||||
&& chown ${AUTH_USERGROUP} ${AUTH_HOME}
|
||||
RUN groupadd -g 61000 ${AUTH_GROUP} && \
|
||||
useradd -g 61000 -l -m -s /bin/false -u 61000 ${AUTH_USER}
|
||||
|
||||
# Install build dependencies
|
||||
RUN apt-get update && apt-get upgrade -y && apt-get install -y \
|
||||
libmariadb-dev gcc git pkg-config
|
||||
RUN mkdir -p ${STATIC_BASE}/myauth/static \
|
||||
&& chown ${AUTH_USERGROUP} ${STATIC_BASE}/myauth/static
|
||||
|
||||
# Install python dependencies
|
||||
RUN pip install --upgrade pip
|
||||
RUN pip install wheel gunicorn
|
||||
RUN pip install ${AUTH_PACKAGE}
|
||||
# Install Build Dependencies
|
||||
RUN apt-get update \
|
||||
&& apt-get upgrade -y \
|
||||
&& apt-get install -y --no-install-recommends libmariadb-dev gcc git pkg-config \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install AA and Dependencies
|
||||
RUN pip install --no-cache-dir ${AUTH_PACKAGE} gunicorn
|
||||
|
||||
# Switch to non-root user
|
||||
USER ${AUTH_USER}
|
||||
@@ -33,7 +33,6 @@ WORKDIR ${AUTH_HOME}
|
||||
RUN allianceauth start myauth
|
||||
COPY /allianceauth/project_template/project_name/settings/local.py ${AUTH_HOME}/myauth/myauth/settings/local.py
|
||||
RUN allianceauth update myauth
|
||||
RUN mkdir -p ${STATIC_BASE}/myauth/static
|
||||
|
||||
RUN echo 'alias auth="python $AUTH_HOME/myauth/manage.py"' >> ~/.bashrc && \
|
||||
source ~/.bashrc
|
||||
|
||||
@@ -9,6 +9,10 @@ from django.conf import settings # noqa
|
||||
|
||||
app = Celery('myauth')
|
||||
|
||||
# Automatically try to establish the connection to the AMQP broker on
|
||||
# Celery startup if it is unavailable.
|
||||
app.conf.broker_connection_retry_on_startup = True
|
||||
|
||||
# Using a string here means the worker don't have to serialize
|
||||
# the configuration object to child processes.
|
||||
app.config_from_object('django.conf:settings')
|
||||
|
||||
@@ -1,20 +1,28 @@
|
||||
server {
|
||||
listen 80;
|
||||
location = /favicon.ico { access_log off; log_not_found off; }
|
||||
location /static {
|
||||
alias /var/www/myauth/static;
|
||||
autoindex off;
|
||||
}
|
||||
events {}
|
||||
http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
location /robots.txt {
|
||||
alias /var/www/myauth/static/robots.txt;
|
||||
}
|
||||
sendfile on;
|
||||
|
||||
location / {
|
||||
proxy_pass http://allianceauth_gunicorn:8000;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_redirect off;
|
||||
server {
|
||||
listen 80;
|
||||
location = /favicon.ico { access_log off; log_not_found off; }
|
||||
location /static {
|
||||
alias /var/www/myauth/static;
|
||||
autoindex off;
|
||||
}
|
||||
|
||||
location /robots.txt {
|
||||
alias /var/www/myauth/static/robots.txt;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://allianceauth_gunicorn:8000;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_redirect off;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
ARG AA_DOCKER_TAG
|
||||
FROM $AA_DOCKER_TAG
|
||||
|
||||
RUN cd /home/allianceauth
|
||||
WORKDIR ${AUTH_HOME}
|
||||
|
||||
COPY /conf/requirements.txt requirements.txt
|
||||
RUN pip install -r requirements.txt
|
||||
RUN --mount=type=cache,target=~/.cache \
|
||||
pip install -r requirements.txt
|
||||
|
||||
@@ -62,10 +62,10 @@ services:
|
||||
max-file: "5"
|
||||
|
||||
nginx:
|
||||
image: nginx:1.25
|
||||
image: nginx:stable
|
||||
restart: always
|
||||
volumes:
|
||||
- ./conf/nginx.conf:/etc/nginx/conf.d/default.conf
|
||||
- ./conf/nginx.conf:/etc/nginx/nginx.conf
|
||||
- static-volume:/var/www/myauth/static
|
||||
depends_on:
|
||||
- allianceauth_gunicorn
|
||||
|
||||
@@ -36,7 +36,7 @@ from allianceauth.framework.api.evecharacter import get_user_from_evecharacter
|
||||
user = get_user_from_evecharacter(character=my_evecharacter)
|
||||
```
|
||||
|
||||
Now, `user` is a `User` object, or the sentinel username (see [get_sentinel_user](#get-sentinel-user))
|
||||
Now, `user` is a `User` object, or the sentinel username (see [get_sentinel_user](#get_sentinel_user))
|
||||
if the `EveCharacter` has no user.
|
||||
|
||||
## User API
|
||||
@@ -88,7 +88,7 @@ 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.
|
||||
the sentinel username (see [get_sentinel_user](#get_sentinel_user)) will be returned.
|
||||
|
||||
### get_sentinel_user
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ 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
|
||||
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):
|
||||
|
||||
@@ -28,6 +28,27 @@ 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.
|
||||
|
||||
### Dashboard Widget Title
|
||||
|
||||
To ensure the dashboard widgets have a unified style, we provide a template partial for the widget title.
|
||||
|
||||
To use it, you can use the following code in your dashboard widget template:
|
||||
|
||||
```django
|
||||
<div id="my-app-dashboard-widget" class="col-12 mb-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{% translate "My Widget Title" as widget_title %}
|
||||
{% include "framework/dashboard/widget-title.html" with title=widget_title %}
|
||||
|
||||
<div>
|
||||
<p>My widget content</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Page Header
|
||||
|
||||
On some pages you want to have a page header. To make this easier, we provide a template partial for this.
|
||||
@@ -38,7 +59,8 @@ To use it, you can use the following code in your template:
|
||||
{% block content %}
|
||||
<div>
|
||||
{% translate "My Page Header" as page_header %}
|
||||
{% include "framework/header/page-header.html" with title=page_header %}
|
||||
{% translate "My Page Header Subtitle" as optional_subtitle %}
|
||||
{% include "framework/header/page-header.html" with title=page_header subtitle=optional_subtitle %}
|
||||
|
||||
<p>My page content</p>
|
||||
</div>
|
||||
|
||||
@@ -122,10 +122,6 @@ class MyService(ServiceHook):
|
||||
|
||||
All of your apps defined urlpatterns will then be included in the `URLconf` when the core application starts.
|
||||
|
||||
#### self.service_ctrl_template
|
||||
|
||||
This is provided as a courtesy and defines the default template to be used with [render_service_ctrl](#render_service_ctrl). You are free to redefine or not use this variable at all.
|
||||
|
||||
#### title
|
||||
|
||||
This is a property which provides a user-friendly display of your service's name. It will usually do a reasonably good job unless your service name has punctuation or odd capitalization. If this is the case, you should override this method and return a string.
|
||||
@@ -134,7 +130,7 @@ This is a property which provides a user-friendly display of your service's name
|
||||
|
||||
#### self.service_ctrl_template
|
||||
|
||||
This is provided as a courtesy and defines the default template to be used with [render_service_ctrl](#render-service-ctrl). You are free to redefine or not use this variable at all.
|
||||
This is provided as a courtesy and defines the default template to be used with [render_service_ctrl](#render_service_ctrl). You are free to redefine or not use this variable at all.
|
||||
|
||||
#### delete_user
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ The `MenuItemHook` class specifies some parameters/instance variables required f
|
||||
:undoc-members:
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
### text
|
||||
|
||||
The text shown as menu item, e.g., usually the name of the app.
|
||||
|
||||
@@ -12,6 +12,8 @@ def register_urls():
|
||||
return UrlHook(app_name.urls, 'app_name', r^'app_name/')
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
#### urls
|
||||
|
||||
The urls module to include. See [the Django docs](https://docs.djangoproject.com/en/dev/topics/http/urls/#example) for designing urlpatterns.
|
||||
|
||||
@@ -337,7 +337,7 @@ To deactivate, click on the debug icon to switch to the debug view. Then uncheck
|
||||
|
||||
### AA debug config
|
||||
|
||||
In VSC, click on Debug / Add Configuration and choose "Django". Should Django not appear as an option, make sure to first open a Django file (e.g., the local.py settings) to help VSC detect that you are using Django.
|
||||
In VSC, click on Debug / Add Configuration and choose "Django". Should Django not appear as an option, make sure to first open a Django file (e.g., the `local.py` settings) to help VSC detect that you are using Django.
|
||||
|
||||
The result should look something like this:
|
||||
|
||||
|
||||
@@ -4,9 +4,33 @@ Auto Groups allows you to automatically place users of certain states into corp
|
||||
|
||||
## Installation
|
||||
|
||||
This is an optional app that needs to be installed.
|
||||
- Add `'allianceauth.eveonline.autogroups',` to `INSTALLED_APPS` in your `local.py`
|
||||
|
||||
To install this app add `'allianceauth.eveonline.autogroups',` to your `INSTALLED_APPS` list and run migrations. All other settings are controlled via the admin panel under the `Eve_Autogroups` section.
|
||||
Perform Django Maintenance and restart our Web Service and Workers.
|
||||
|
||||
::::{tabs}
|
||||
:::{group-tab} Bare Metal
|
||||
|
||||
```shell
|
||||
python manage.py migrate
|
||||
python manage.py collectstatic --noinput
|
||||
supervisorctl restart myauth:
|
||||
```
|
||||
|
||||
:::
|
||||
:::{group-tab} Containerized
|
||||
|
||||
```shell
|
||||
docker compose --env-file=.env up -d
|
||||
docker compose exec allianceauth_gunicorn bash
|
||||
auth migrate
|
||||
auth collectstatic
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
All other settings are controlled via the admin panel under the `Eve_Autogroups` section.
|
||||
|
||||
## Configuring a group
|
||||
|
||||
|
||||
@@ -8,7 +8,31 @@ This module is used to check the registration status of Corp members and to dete
|
||||
|
||||
Corp Stats requires access to the `esi-corporations.read_corporation_membership.v1` SSO scope. Update your application on the [EVE Developers site](https://developers.eveonline.com) to ensure it is available.
|
||||
|
||||
Add `'allianceauth.corputils',` to your `INSTALLED_APPS` list in your auth project's settings file. Run migrations to complete installation.
|
||||
- Add `'allianceauth.corputils',` to `INSTALLED_APPS` in your `local.py`
|
||||
|
||||
Perform Django Maintenance and restart our Web Service and Workers.
|
||||
|
||||
::::{tabs}
|
||||
:::{group-tab} Bare Metal
|
||||
|
||||
```shell
|
||||
python manage.py migrate
|
||||
python manage.py collectstatic --noinput
|
||||
supervisorctl restart myauth:
|
||||
```
|
||||
|
||||
:::
|
||||
:::{group-tab} Containerized
|
||||
|
||||
```shell
|
||||
docker compose --env-file=.env up -d
|
||||
docker compose exec allianceauth_gunicorn bash
|
||||
auth migrate
|
||||
auth collectstatic
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
## Creating a Corp Stats
|
||||
|
||||
|
||||
@@ -8,7 +8,31 @@ The Fleet Activity Tracking (FAT) app allows you to track fleet participation.
|
||||
|
||||
Fleet Activity Tracking requires access to the `esi-location.read_location.v1`, `esi-location.read_ship_type.v1`, and `esi-universe.read_structures.v1` SSO scopes. Update your application on the [EVE Developers site](https://developers.eveonline.com) to ensure these are available.
|
||||
|
||||
Add `'allianceauth.fleetactivitytracking',` to your `INSTALLED_APPS` list in your auth project's settings file. Run migrations to complete installation.
|
||||
Add `'allianceauth.fleetactivitytracking',` to `INSTALLED_APPS` in your `local.py`
|
||||
|
||||
Perform Django Maintenance and restart our Web Service and Workers.
|
||||
|
||||
::::{tabs}
|
||||
:::{group-tab} Bare Metal
|
||||
|
||||
```shell
|
||||
python manage.py migrate
|
||||
python manage.py collectstatic --noinput
|
||||
supervisorctl restart myauth:
|
||||
```
|
||||
|
||||
:::
|
||||
:::{group-tab} Containerized
|
||||
|
||||
```shell
|
||||
docker compose --env-file=.env up -d
|
||||
docker compose exec allianceauth_gunicorn bash
|
||||
auth migrate
|
||||
auth collectstatic
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
## Permissions
|
||||
|
||||
|
||||
@@ -10,7 +10,31 @@ This app allows you to manage applications for multiple corporations in your all
|
||||
|
||||
## Installation
|
||||
|
||||
Add `'allianceauth.hrapplications',` to your `INSTALLED_APPS` list in your auth project's settings file. Run migrations to complete installation.
|
||||
- Add `'allianceauth.hrapplications',` to `INSTALLED_APPS` in your `local.py`
|
||||
|
||||
Perform Django Maintenance and restart our Web Service and Workers.
|
||||
|
||||
::::{tabs}
|
||||
:::{group-tab} Bare Metal
|
||||
|
||||
```shell
|
||||
python manage.py migrate
|
||||
python manage.py collectstatic --noinput
|
||||
supervisorctl restart myauth:
|
||||
```
|
||||
|
||||
:::
|
||||
:::{group-tab} Containerized
|
||||
|
||||
```shell
|
||||
docker compose --env-file=.env up -d
|
||||
docker compose exec allianceauth_gunicorn bash
|
||||
auth migrate
|
||||
auth collectstatic
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
## Management
|
||||
|
||||
|
||||
@@ -6,7 +6,31 @@ Fleet Operations is an app for organizing and communicating fleet schedules.
|
||||
|
||||
## Installation
|
||||
|
||||
Add `'allianceauth.optimer',` to your `INSTALLED_APPS` list in your auth project's settings file. Run migrations to complete installation.
|
||||
- Add `'allianceauth.optimer',` to `INSTALLED_APPS` in your `local.py`
|
||||
|
||||
Perform Django Maintenance and restart our Web Service and Workers.
|
||||
|
||||
::::{tabs}
|
||||
:::{group-tab} Bare Metal
|
||||
|
||||
```shell
|
||||
python manage.py migrate
|
||||
python manage.py collectstatic --noinput
|
||||
supervisorctl restart myauth:
|
||||
```
|
||||
|
||||
:::
|
||||
:::{group-tab} Containerized
|
||||
|
||||
```shell
|
||||
docker compose --env-file=.env up -d
|
||||
docker compose exec allianceauth_gunicorn bash
|
||||
auth migrate
|
||||
auth collectstatic
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
## Permissions
|
||||
|
||||
|
||||
@@ -2,9 +2,33 @@
|
||||
|
||||
Access to most of Alliance Auth's features is controlled by Django's permissions system. To help you secure your services, Alliance Auth provides a permission auditing tool.
|
||||
|
||||
This is an optional app that needs to be installed.
|
||||
## Installation
|
||||
|
||||
To install it add `'allianceauth.permissions_tool',` to your `INSTALLED_APPS` list in your auth project's settings file.
|
||||
- Add `'allianceauth.permissions_tool',` to `INSTALLED_APPS` in your `local.py`
|
||||
|
||||
Perform Django Maintenance and restart our Web Service and Workers.
|
||||
|
||||
::::{tabs}
|
||||
:::{group-tab} Bare Metal
|
||||
|
||||
```shell
|
||||
python manage.py migrate
|
||||
python manage.py collectstatic --noinput
|
||||
supervisorctl restart myauth:
|
||||
```
|
||||
|
||||
:::
|
||||
:::{group-tab} Containerized
|
||||
|
||||
```shell
|
||||
docker compose --env-file=.env up -d
|
||||
docker compose exec allianceauth_gunicorn bash
|
||||
auth migrate
|
||||
auth collectstatic
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
@@ -6,7 +6,31 @@ Ship Replacement helps you to organize ship replacement programs (SRP) for your
|
||||
|
||||
## Installation
|
||||
|
||||
Add `'allianceauth.srp',` to your `INSTALLED_APPS` list in your auth project's settings file. Run migrations to complete installation.
|
||||
- Add `'allianceauth.srp',` to `INSTALLED_APPS` in your `local.py`
|
||||
|
||||
Perform Django Maintenance and restart our Web Service and Workers.
|
||||
|
||||
::::{tabs}
|
||||
:::{group-tab} Bare Metal
|
||||
|
||||
```shell
|
||||
python manage.py migrate
|
||||
python manage.py collectstatic --noinput
|
||||
supervisorctl restart myauth:
|
||||
```
|
||||
|
||||
:::
|
||||
:::{group-tab} Containerized
|
||||
|
||||
```shell
|
||||
docker compose --env-file=.env up -d
|
||||
docker compose exec allianceauth_gunicorn bash
|
||||
auth migrate
|
||||
auth collectstatic
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
## Permissions
|
||||
|
||||
|
||||
@@ -6,7 +6,31 @@ Structure Timers helps you keep track of both offensive and defensive structure
|
||||
|
||||
## Installation
|
||||
|
||||
Add `'allianceauth.timerboard',` to your `INSTALLED_APPS` list in your auth project's settings file. Run migrations to complete installation.
|
||||
- Add `'allianceauth.timerboard',` to `INSTALLED_APPS` in your `local.py`
|
||||
|
||||
Perform Django Maintenance and restart our Web Service and Workers.
|
||||
|
||||
::::{tabs}
|
||||
:::{group-tab} Bare Metal
|
||||
|
||||
```shell
|
||||
python manage.py migrate
|
||||
python manage.py collectstatic --noinput
|
||||
supervisorctl restart myauth:
|
||||
```
|
||||
|
||||
:::
|
||||
:::{group-tab} Containerized
|
||||
|
||||
```shell
|
||||
docker compose --env-file=.env up -d
|
||||
docker compose exec allianceauth_gunicorn bash
|
||||
auth migrate
|
||||
auth collectstatic
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
## Permissions
|
||||
|
||||
|
||||
@@ -33,23 +33,6 @@ Our Daily Stats contain the following:
|
||||
- A task to send a List of Installed Apps
|
||||
- Each Task contains the UUID and Alliance Auth Version
|
||||
|
||||
Our Celery Events contain the following:
|
||||
|
||||
- Unique Identifier (The UUID)
|
||||
- Celery Namespace of the task e.g., allianceauth.eveonline
|
||||
- Celery Task
|
||||
- Task Success or Exception
|
||||
- A context number for bulk tasks or sometimes a binary True/False
|
||||
|
||||
Our Page Views contain the following:
|
||||
|
||||
- Unique Identifier (The UUID)
|
||||
- Page Path
|
||||
- Page Title
|
||||
- The locale of the users browser
|
||||
- The User-Agent of the user's browser
|
||||
- The Alliance Auth Version
|
||||
|
||||
## Why
|
||||
|
||||
This data allows Alliance Auth development to gather accurate statistics on our installation base, as well as how those installations are used.
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
It has the following key features:
|
||||
|
||||
- Automatically grants or revokes users access to external services (e.g. Discord, Mumble) and web apps (e.g. SRP requests) based on the user's current membership to [in-game organizations](/features/core/states) and [groups](/features/core/groups)
|
||||
- Automatically grants or revokes user access to external services (e.g. Discord, Mumble) and web apps (e.g. SRP requests) based on the user's current membership to [in-game organizations](/features/core/states) and [groups](/features/core/groups)
|
||||
|
||||
- Provides a central website where users can directly access web apps (e.g., SRP requests) and manage their access to external services and groups.
|
||||
- Provides a central web site where users can directly access web apps (e.g. SRP requests, Fleet Schedule) and manage their access to external services and groups.
|
||||
|
||||
- Includes a set of connectors (called ["services"](/features/services/index)) for integrating access management with many popular external services like Discord, Mumble, Teamspeak 3, SMF and others
|
||||
|
||||
@@ -14,4 +14,4 @@ It has the following key features:
|
||||
|
||||
- It can be easily extended with additional services and apps. Many are provided by the [community](/features/community/index).
|
||||
|
||||
- Chinese, English, German and Spanish localization
|
||||
- English :flag_gb:, Chinese :flag_cn:, German :flag_de:, Spanish :flag_es:, Korean :flag_kr:, Russian :flag_ru:, Italian :flag_it:, French :flag_fr:, Japanese :flag_jp: and Ukrainian :flag_ua: Localization
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user