BS5 Theme

This commit is contained in:
Aaron Kable 2023-10-07 08:20:22 +00:00 committed by Ariel Rin
parent 567d97f38a
commit 2e78aa5f26
161 changed files with 3198 additions and 1655 deletions

View File

@ -1,5 +1,30 @@
from django.apps import AppConfig
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

View File

@ -0,0 +1,45 @@
from allianceauth.hooks import DashboardItemHook
from allianceauth import hooks
from .views import dashboard_characters, dashboard_groups, dashboard_admin
class UserCharactersHook(DashboardItemHook):
def __init__(self):
DashboardItemHook.__init__(
self,
dashboard_characters,
5
)
class UserGroupsHook(DashboardItemHook):
def __init__(self):
DashboardItemHook.__init__(
self,
dashboard_groups,
5
)
class AdminHook(DashboardItemHook):
def __init__(self):
DashboardItemHook.__init__(
self,
dashboard_admin,
0
)
@hooks.register('dashboard_hook')
def register_character_hook():
return UserCharactersHook()
@hooks.register('dashboard_hook')
def register_groups_hook():
return UserGroupsHook()
@hooks.register('dashboard_hook')
def register_admin_hook():
return AdminHook()

View File

@ -31,6 +31,7 @@ class UserSettingsMiddleware(MiddlewareMixin):
except Exception as e:
logger.exception(e)
# AA v3 NIGHT_MODE
# Set our Night mode flag from the DB
# Null = hasnt been set by the user ever, dont act.
#
@ -42,4 +43,11 @@ class UserSettingsMiddleware(MiddlewareMixin):
except Exception as e:
logger.exception(e)
# AA v4 Themes
try:
if request.user.profile.theme is not None:
request.session["THEME"] = request.user.profile.theme
except Exception as e:
logger.exception(e)
return response

View File

@ -0,0 +1,18 @@
# Generated by Django 4.0.10 on 2023-10-07 07:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('authentication', '0021_alter_userprofile_language'),
]
operations = [
migrations.AddField(
model_name='userprofile',
name='theme',
field=models.CharField(blank=True, help_text='Bootstrap 5 Themes from https://bootswatch.com/ or Community Apps', max_length=200, null=True, verbose_name='Theme'),
),
]

View File

@ -101,6 +101,13 @@ class UserProfile(models.Model):
_("Night Mode"),
blank=True,
null=True)
theme = models.CharField(
_("Theme"),
max_length=200,
blank=True,
null=True,
help_text="Bootstrap 5 Themes from https://bootswatch.com/ or Community Apps"
)
def assign_state(self, state=None, commit=True):
if not state:

View File

@ -0,0 +1,41 @@
{% load i18n %}
<div class="col-12 col-xl-8 align-self-stretch p-2">
<div class="card">
<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">
<div style="height: 300px;overflow:-moz-scrollbars-vertical;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' %}"><span class="d-md-inline m-2">{% translate 'Add Character' %}</span></a>
<a href="{% url 'authentication:change_main_character' %}" class="btn btn-primary flex-fill m-1" title="{% translate 'Change Main' %}"></span><span class="d-md-inline m-2">{% translate 'Change Main' %}</span></a>
</div>
<table class="table" style="--bs-table-bg: transparent;">
<thead>
<tr>
<th class="text-center"></th>
<th class="text-center">{% translate "Name" %}</th>
<th class="text-center">{% translate "Corp" %}</th>
<th class="text-center">{% translate "Alliance" %}</th>
</tr>
</thead>
<tbody>
{% for char in characters %}
<tr>
<td class="text-center"><img class="ra-avatar rounded-circle" src="{{ char.portrait_url_32 }}">
</td>
<td class="text-center">{{ char.character_name }}</td>
<td class="text-center">{{ char.corporation_name }}</td>
<td class="text-center">{{ char.alliance_name|default_if_none:"" }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,20 @@
{% load i18n %}
<div class="col-12 col-xl-4 align-self-stretch p-2">
<div class="card h-100">
<div class="card-body">
<h4 class="card-title text-center">{% translate "Membership" %}</h4>
<div class="card-body">
<div style="height: 300px;overflow:-moz-scrollbars-vertical;overflow-y:auto;">
<h6 class="text-center">{% translate "State:" %} {{ request.user.profile.state }}</h6>
<table class="table" style="--bs-table-bg: transparent;">
{% for group in groups %}
<tr>
<td class="text-center">{{ group.name }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
</div>
</div>

View File

@ -1,190 +1,15 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load static %}
{% load i18n %}
{% block page_title %}{% translate "Dashboard" %}{% endblock %}
{% block header_nav_brand %}
{% translate "Dashboard" %}
{% endblock %}
{% block content %}
<h1 class="page-header text-center">{% translate "Dashboard" %}</h1>
{% if user.is_staff %}
{% include 'allianceauth/admin-status/include.html' %}
{% endif %}
<div class="col-sm-12">
<div class="row vertical-flexbox-row2">
<div class="col-sm-6 text-center">
<div class="panel panel-primary" style="height:100%">
<div class="panel-heading">
<h3 class="panel-title">
{% blocktranslate with state=request.user.profile.state %}
Main Character (State: {{ state }})
{% endblocktranslate %}
</h3>
</div>
<div class="panel-body">
{% if request.user.profile.main_character %}
{% with request.user.profile.main_character as main %}
<div class="hidden-xs">
<div class="col-lg-4 col-sm-2">
<table class="table">
<tr>
<td class="text-center">
<img class="ra-avatar" src="{{ main.portrait_url_128 }}" alt="{{ main.character_name }}">
</td>
</tr>
<tr>
<td class="text-center">{{ main.character_name }}</td>
</tr>
</table>
</div>
<div class="col-lg-4 col-sm-2">
<table class="table">
<tr>
<td class="text-center">
<img class="ra-avatar" src="{{ main.corporation_logo_url_128 }}" alt="{{ main.corporation_name }}">
</td>
</tr>
<tr>
<td class="text-center">{{ main.corporation_name }}</td>
</tr>
</table>
</div>
<div class="col-lg-4 col-sm-2">
{% if main.alliance_id %}
<table class="table">
<tr>
<td class="text-center">
<img class="ra-avatar" src="{{ main.alliance_logo_url_128 }}" alt="{{ main.alliance_name }}">
</td>
</tr>
<tr>
<td class="text-center">{{ main.alliance_name }}</td>
<tr>
</table>
{% elif main.faction_id %}
<table class="table">
<tr>
<td class="text-center">
<img class="ra-avatar" src="{{ main.faction_logo_url_128 }}" alt="{{ main.faction_name }}">
</td>
</tr>
<tr>
<td class="text-center">{{ main.faction_name }}</td>
<tr>
</table>
{% endif %}
</div>
</div>
<div class="table visible-xs-block">
<p>
<img class="ra-avatar" src="{{ main.portrait_url_64 }}" alt="{{ main.corporation_name }}">
<img class="ra-avatar" src="{{ main.corporation_logo_url_64 }}" alt="{{ main.corporation_name }}">
{% if main.alliance_id %}
<img class="ra-avatar" src="{{ main.alliance_logo_url_64 }}" alt="{{ main.alliance_name }}">
{% endif %}
{% if main.faction_id %}
<img class="ra-avatar" src="{{ main.faction_logo_url_64 }}" alt="{{ main.faction_name }}">
{% endif %}
</p>
<p>
<strong>{{ main.character_name }}</strong><br>
{{ main.corporation_name }}<br>
{% if main.alliance_id %}
{{ main.alliance_name }}<br>
{% endif %}
{% if main.faction_id %}
{{ main.faction_name }}
{% endif %}
</p>
</div>
{% endwith %}
{% else %}
<div class="alert alert-danger" role="alert">
{% translate "No main character set." %}
</div>
{% endif %}
<div class="clearfix"></div>
<div class="row">
<div class="col-sm-6">
<p>
<a href="{% url 'authentication:add_character' %}" class="btn btn-block btn-info"
title="Add Character">{% translate 'Add Character' %}</a>
</p>
</div>
<div class="col-sm-6">
<p>
<a href="{% url 'authentication:change_main_character' %}" class="btn btn-block btn-info"
title="Change Main Character">{% translate "Change Main" %}</a>
</p>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-6 text-center">
<div class="panel panel-success" style="height:100%">
<div class="panel-heading">
<h3 class="panel-title">{% translate "Group Memberships" %}</h3>
</div>
<div class="panel-body">
<div style="height: 240px;overflow-y:auto;">
<table class="table table-aa">
{% for group in groups %}
<tr>
<td>{{ group.name }}</td>
</tr>
<div class="d-flex justify-content-around align-self-center flex-wrap">
{% for dash in views %}
{{ dash | safe }}
{% endfor %}
</table>
</div>
</div>
</div>
</div>
</div>
<div class="clearfix"></div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title text-center" style="text-align: center">
{% translate 'Characters' %}
</h3>
</div>
<div class="panel-body">
<table class="table table-aa hidden-xs">
<thead>
<tr>
<th class="text-center"></th>
<th class="text-center">{% translate 'Name' %}</th>
<th class="text-center">{% translate 'Corp' %}</th>
<th class="text-center">{% translate 'Alliance' %}</th>
</tr>
</thead>
<tbody>
{% for char in characters %}
<tr>
<td class="text-center">
<img class="ra-avatar img-circle" src="{{ char.portrait_url_32 }}" alt="{{ char.character_name }}">
</td>
<td class="text-center">{{ char.character_name }}</td>
<td class="text-center">{{ char.corporation_name }}</td>
<td class="text-center">{{ char.alliance_name|default:"" }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<table class="table table-aa visible-xs-block" style="width: 100%">
<tbody>
{% for char in characters %}
<tr>
<td class="text-center" style="vertical-align: middle">
<img class="ra-avatar img-circle" src="{{ char.portrait_url_32 }}" alt="{{ char.character_name }}">
</td>
<td class="text-center" style="vertical-align: middle; width: 100%">
<strong>{{ char.character_name }}</strong><br>
{{ char.corporation_name }}<br>
{{ char.alliance_name|default:"" }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,7 +1,7 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}{% translate "Dashboard" %}{% endblock %}
{% block page_title %}{% translate "Dashboard" %}{% endblock page_title %}
{% block content %}
<h1 class="page-header text-center">{% translate "Token Management" %}</h1>
@ -10,7 +10,7 @@
<thead>
<tr>
<th>{% translate "Scopes" %}</th>
<th class="text-right">{% translate "Actions" %}</th>
<th class="text-end">{% translate "Actions" %}</th>
<th>{% translate "Character" %}</th>
</tr>
@ -18,8 +18,8 @@
<tbody>
{% for t in tokens %}
<tr>
<td styl="white-space:initial;">{% for s in t.scopes.all %}<span class="label label-default">{{s.name}}</span> {% endfor %}</td>
<td nowrap class="text-right"><a href="{% url 'authentication:token_delete' t.id %}" class="btn btn-danger"><i class="fas fa-trash"></i></a> <a href="{% url 'authentication:token_refresh' t.id %}" class="btn btn-success"><i class="fas fa-sync-alt"></i></a></td>
<td styl="white-space:initial;">{% for s in t.scopes.all %}<span class="badge badge-secondar">{{ s.name }}</span> {% endfor %}</td>
<td nowrap class="text-end"><a href="{% url 'authentication:token_delete' t.id %}" class="btn btn-danger"><i class="fas fa-trash"></i></a> <a href="{% url 'authentication:token_refresh' t.id %}" class="btn btn-success"><i class="fas fa-sync-alt"></i></a></td>
<td>{{ t.character_name }}</td>
</tr>
{% endfor %}
@ -27,15 +27,15 @@
</table>
{% translate "This page is a best attempt, but backups or database logs can still contain your tokens. Always revoke tokens on https://community.eveonline.com/support/third-party-applications/ where possible."|urlize %}
</div>
{% endblock %}
{% endblock content %}
{% block extra_javascript %}
{% include 'bundles/datatables-js.html' %}
{% endblock %}
{% include "bundles/datatables-js-bs5.html" %}
{% endblock extra_javascript %}
{% block extra_css %}
{% include 'bundles/datatables-css.html' %}
{% endblock %}
{% include "bundles/datatables-css-bs5.html" %}
{% endblock extra_css %}
{% block extra_script %}
$(document).ready(function(){
@ -59,4 +59,4 @@
"stateSave": true,
});
});
{% endblock %}
{% endblock extra_script %}

View File

@ -7,6 +7,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<!-- TODO Bundle all the site specific stuff up into its own template for easy overide -->
<meta property="og:title" content="{{ SITE_NAME }}">
<meta property="og:image" content="{{ SITE_URL }}{% static 'allianceauth/icons/apple-touch-icon.png' %}">
<meta property="og:description" content="Alliance Auth - An auth system for EVE Online to help in-game organizations manage online service access.">

View File

@ -1,4 +1,5 @@
import logging
from allianceauth.hooks import get_hooks
from django_registration.backends.activation.views import (
REGISTRATION_SALT, ActivationView as BaseActivationView,
@ -42,23 +43,51 @@ def index(request):
return redirect('authentication:dashboard')
@login_required
def dashboard(request):
def dashboard_groups(request):
groups = request.user.groups.all()
if _has_auto_groups:
groups = groups\
.filter(managedalliancegroup__isnull=True)\
.filter(managedcorpgroup__isnull=True)
groups = groups.order_by('name')
context = {
'groups': groups,
}
return render_to_string('authentication/dashboard.groups.html', context=context, request=request)
def dashboard_characters(request):
characters = EveCharacter.objects\
.filter(character_ownership__user=request.user)\
.select_related()\
.order_by('character_name')
context = {
'groups': groups,
'characters': characters
}
return render_to_string('authentication/dashboard.characters.html', context=context, request=request)
def dashboard_admin(request):
if request.user.is_superuser:
return render_to_string('allianceauth/admin-status/include.html', request=request)
else:
return ""
@login_required
def dashboard(request):
_dash_items = list()
hooks = get_hooks('dashboard_hook')
items = [fn() for fn in hooks]
items.sort(key=lambda i: i.order)
for item in items:
_dash_items.append(item.render(request))
context = {
'views': _dash_items,
}
return render(request, 'authentication/dashboard.html', context)

View File

@ -1,5 +1,5 @@
from django.conf import settings
from .views import NightModeRedirectView
from .views import NightModeRedirectView, ThemeRedirectView
def auth_settings(request):

View File

@ -1,4 +1,5 @@
from allianceauth.services.hooks import MenuItemHook, UrlHook
from allianceauth.menu.hooks import MenuItemHook
from allianceauth.services.hooks import UrlHook
from django.utils.translation import gettext_lazy as _
from allianceauth import hooks
from allianceauth.corputils import urls

View File

@ -1,6 +1,8 @@
{% extends 'allianceauth/base.html' %}
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}{% translate "Corporation Member Data" %}{% endblock %}
{% block page_title %}
{% translate "Corporation Member Data" %}
{% endblock page_title %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "Corporation Member Data" %}</h1>
@ -26,12 +28,13 @@
</ul>
<form class="navbar-form navbar-right" role="search" action="{% url 'corputils:search' %}" method="GET">
<div class="form-group">
<input type="text" class="form-control" name="search_string" placeholder="{% if search_string %}{{ search_string }}{% else %}{% translate "Search all corporations..." %}{% endif %}">
<input type="text" class="form-control" name="search_string" placeholder="{% if search_string %}{{ search_string }}{% else %}{% translate 'Search all corporations...' %}{% endif %}">
</div>
</form>
</div>
</nav>
{% block member_data %}{% endblock %}
{% block member_data %}
{% endblock member_data %}
</div>
</div>
{% endblock %}
{% endblock content %}

View File

@ -87,7 +87,7 @@
<td class="text-center" style="width:30%">{{ alt.corporation_name }}</td>
<td class="text-center" style="width:30%">{{ alt.alliance_name }}</td>
<td class="text-center" style="width:5%">
<a href="https://zkillboard.com/character/{{ alt.character_id }}/" class="label label-danger" target="_blank">
<a href="https://zkillboard.com/character/{{ alt.character_id }}/" class="badge badge-danger" target="_blank">
{% translate "Killboard" %}
</a>
</td>
@ -122,7 +122,7 @@
<td><img src="{{ member.portrait_url }}" class="img-circle" alt="{{ member }}"></td>
<td class="text-center">{{ member }}</td>
<td class="text-center">
<a href="https://zkillboard.com/character/{{ member.character_id }}/" class="label label-danger" target="_blank">{% translate "Killboard" %}</a>
<a href="https://zkillboard.com/character/{{ member.character_id }}/" class="badge badge-danger" target="_blank">{% translate "Killboard" %}</a>
</td>
<td class="text-center">{{ member.character_ownership.user.profile.main_character.character_name }}</td>
<td class="text-center">{{ member.character_ownership.user.profile.main_character.corporation_name }}</td>
@ -134,7 +134,7 @@
<td><img src="{{ member.portrait_url }}" class="img-circle" alt="{{ member.character_name }}"></td>
<td class="text-center">{{ member.character_name }}</td>
<td class="text-center">
<a href="https://zkillboard.com/character/{{ member.character_id }}/" class="label label-danger" target="_blank">{% translate "Killboard" %}</a>
<a href="https://zkillboard.com/character/{{ member.character_id }}/" class="badge badge-danger" target="_blank">{% translate "Killboard" %}</a>
</td>
<td class="text-center"></td>
<td class="text-center"></td>
@ -163,7 +163,7 @@
<td><img src="{{ member.portrait_url }}" class="img-circle" alt="{{ member.character_name }}"></td>
<td class="text-center">{{ member.character_name }}</td>
<td class="text-center">
<a href="https://zkillboard.com/character/{{ member.character_id }}/" class="label label-danger" target="_blank">
<a href="https://zkillboard.com/character/{{ member.character_id }}/" class="badge badge-danger" target="_blank">
{% translate "Killboard" %}
</a>
</td>

View File

@ -24,7 +24,7 @@
<td class="text-center"><img src="{{ result.1.portrait_url }}" class="img-circle" alt="{{ result.1.character_name }}"></td>
<td class="text-center">{{ result.1.character_name }}</td>
<td class="text-center">{{ result.0.corp.corporation_name }}</td>
<td class="text-center"><a href="https://zkillboard.com/character/{{ result.1.character_id }}/" class="label label-danger" target="_blank">{% translate "Killboard" %}</a></td>
<td class="text-center"><a href="https://zkillboard.com/character/{{ result.1.character_id }}/" class="badge badge-danger" target="_blank">{% translate "Killboard" %}</a></td>
<td class="text-center">{{ result.1.main_character.character_name }}</td>
<td class="text-center">{{ result.1.main_character.corporation_name }}</td>
<td class="text-center">{{ result.1.main_character.alliance_name }}</td>

View File

@ -8,10 +8,10 @@ Needs to be called with a context containing three objects:
-->
{% extends 'allianceauth/base.html' %}
{% extends "allianceauth/base-bs5.html" %}
{% load evelinks %}
{% block page_title %}Evelinks examples{% endblock %}
{% block page_title %}Evelinks Examples{% endblock page_title %}
{% block content %}
@ -53,7 +53,6 @@ Needs to be called with a context containing three objects:
<p><a href="{{ 30002813|zkillboard_solar_system_url }}">solar sytem from ID</a></p>
</div>
</div>
</div>
<h2>image URLs</h2>
@ -75,10 +74,8 @@ Needs to be called with a context containing three objects:
<p>alliance from character object: <img src="{{ my_character|alliance_logo_url:128 }}"></p>
<p>alliance from alliance object: <img src="{{ my_alliance|alliance_logo_url:128 }}"></p>
</div>
</div>
</div>
</div>
{% endblock %}
{% endblock content %}

View File

@ -1,7 +1,8 @@
from allianceauth.menu.hooks import MenuItemHook
from . import urls
from django.utils.translation import gettext_lazy as _
from allianceauth import hooks
from allianceauth.services.hooks import MenuItemHook, UrlHook
from allianceauth.services.hooks import UrlHook
@hooks.register('menu_item_hook')

View File

@ -1,7 +1,8 @@
{% extends 'allianceauth/base.html' %}
{% extends 'allianceauth/base-bs5.html' %}
{% load i18n %}
{% block page_title %}{% translate "Fleet Participation" %}{% endblock %}
{% block page_title %}
{% translate "Fleet Participation" %}
{% endblock %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "Character not found!" %}</h1>

View File

@ -1,31 +1,31 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load bootstrap %}
{% load i18n %}
{% block page_title %}{% translate "Create Fatlink" %}{% endblock page_title %}
{% block page_title %}
{% translate "Create Fatlink" %}
{% endblock page_title %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "Create Fleet Operation" %}</h1>
<div class="container-fluid">
{% if badrequest %}
<div class="alert alert-danger" role="alert">{% translate "Bad request!" %}</div>
{% endif %}
{% for message in errormessages %}
<div class="alert alert-danger" role="alert">{{ message }}</div>
{% endfor %}
<div class="col-md-4 col-md-offset-4">
{% for message in errormessages %}<div class="alert alert-danger" role="alert">{{ message }}</div>{% endfor %}
<div class="col-md-4 offset-md-4">
<div class="row">
<form class="form-signin" role="form" action="" method="POST">
{% csrf_token %}
{{ form|bootstrap }}
<br>
<button class="btn btn-lg btn-primary btn-block" type="submit" name="submit_fat">{% translate "Create fatlink" %}</button>
<br/>
<button class="btn btn-lg btn-primary btn-block"
type="submit"
name="submit_fat">
{% translate "Create fatlink" %}
</button>
</form>
</div>
</div>
</div>
</div>
{% endblock content %}

View File

@ -1,11 +1,11 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}{% translate "Fatlink view" %}{% endblock page_title %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "Edit fatlink" %} "{{ fatlink }}"
<div class="text-right">
<div class="text-end">
<form>
<button type="submit" onclick="return confirm('Are you sure?')" class="btn btn-danger" name="deletefat" value="True">
{% translate "Delete fat" %}

View File

@ -1,4 +1,4 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}{% translate "Personal fatlink statistics" %}{% endblock page_title %}
@ -7,7 +7,7 @@
<div class="col-lg-12">
<h1 class="page-header text-center">{% blocktranslate %}Participation data statistics for {{ month }}, {{ year }}{% endblocktranslate %}
{% if char_id %}
<div class="text-right">
<div class="text-end">
<a href="{% url 'fatlink:user_statistics_month' char_id previous_month|date:'Y' previous_month|date:'m' %}" class="btn btn-info">{% translate "Previous month" %}</a>
<a href="{% url 'fatlink:user_statistics_month' char_id next_month|date:'Y' next_month|date:'m' %}" class="btn btn-info">{% translate "Next month" %}</a>
</div>
@ -51,7 +51,7 @@
</tr>
{% for link in created_fats %}
<tr>
<td class="text-center"><a href="{% url 'fatlink:click' link.hash %}" class="label label-primary">{{ link.fleet }}</a></td>
<td class="text-center"><a href="{% url 'fatlink:click' link.hash %}" class="badge badge-primary">{{ link.fleet }}</a></td>
<td class="text-center">{{ link.creator.username }}</td>
<td class="text-center">{{ link.fatdatetime }}</td>
<td class="text-center">{{ link.duration }}</td>

View File

@ -1,30 +1,29 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}{% translate "Personal fatlink statistics" %}{% endblock page_title %}
{% block page_title %}
{% translate "Personal fatlink statistics" %}
{% endblock page_title %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% blocktranslate %}Participation data statistics for {{ year }}{% endblocktranslate %}
<div class="text-right">
<a href="{% url 'fatlink:personal_statistics_year' previous_year %}" class="btn btn-info">{% translate "Previous year" %}</a>
<h1 class="page-header text-center">
{% blocktranslate %}Participation data statistics for {{ year }}{% endblocktranslate %}
<div class="text-end">
<a href="{% url "fatlink:personal_statistics_year" previous_year %}" class="btn btn-info"><i class="fa-solid fa-chevron-left"></i> {% translate "Previous year" %}</a>
{% if next_year %}
<a href="{% url 'fatlink:personal_statistics_year' next_year %}" class="btn btn-info">{% translate "Next year" %}</a>
<a href="{% url "fatlink:personal_statistics_year" next_year %}" class="btn btn-info">{% translate "Next year" %} <i class="fa-solid fa-chevron-right"></i></a>
{% endif %}
</div>
</h1>
<div class="col-lg-2 col-lg-offset-5">
<div class="col-lg-2 offset-lg-5">
<table class="table table-responsive">
<tr>
<th class="col-md-2 text-center">{% translate "Month" %}</th>
<th class="col-md-2 text-center">{% translate "Fats" %}</th>
<th scope="col" class="col-md-2 text-center">{% translate "Month" %}</th>
<th scope="col" class="col-md-2 text-center">{% translate "Fats" %}</th>
</tr>
{% for monthnr, month, n_fats in monthlystats %}
<tr>
<td class="text-center">
<a href="{% url 'fatlink:personal_statistics_month' year monthnr %}">
{{ month }}
</a>
<a href="{% url 'fatlink:personal_statistics_month' year monthnr %}">{{ month }}</a>
</td>
<td class="text-center">{{ n_fats }}</td>
</tr>

View File

@ -1,27 +1,30 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}{% translate "Fatlink Corp Statistics" %}{% endblock page_title %}
{% block page_title %}
{% translate "Fatlink Corp Statistics" %}
{% endblock page_title %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% blocktranslate %}Participation data statistics for {{ month }}, {{ year }}{% endblocktranslate %}
<div class="text-right">
<a href="{% url 'fatlink:statistics_corp_month' corpid previous_month|date:"Y" previous_month|date:"m" %}" class="btn btn-info">{% translate "Previous month" %}</a>
<h1 class="page-header text-center">
{% blocktranslate %}Participation data statistics for {{ month }}, {{ year }}{% endblocktranslate %}
<div class="text-end">
<a href="{% url "fatlink:statistics_corp_month" corpid previous_month|date:"Y" previous_month|date:"m" %}" class="btn btn-info">{% translate "Previous month" %}</a>
{% if next_month %}
<a href="{% url 'fatlink:statistics_corp_month' corpid next_month|date:"Y" next_month|date:"m" %}" class="btn btn-info">{% translate "Next month" %}</a>
<a href="{% url "fatlink:statistics_corp_month" corpid next_month|date:"Y" next_month|date:"m" %}" class="btn btn-info">{% translate "Next month" %}</a>
{% endif %}
</div>
</h1>
{% if fatStats %}
<table class="table table-responsive">
<div class="table-responsive">
<table class="table table-striped">
<tr>
<th class="col-md-1"></th>
<th class="col-md-2 text-center">{% translate "Main Character" %}</th>
<th class="col-md-2 text-center">{% translate "Characters" %}</th>
<th class="col-md-2 text-center">{% translate "Fats" %}</th>
<th class="col-md-2 text-center">{% translate "Average fats" %}
<i class="glyphicon glyphicon-question-sign" rel="tooltip" title="Fats ÷ Characters"></i>
<th scope="col" class="col-md-1"></th>
<th scope="col" class="col-md-2 text-center">{% translate "Main Character" %}</th>
<th scope="col" class="col-md-2 text-center">{% translate "Characters" %}</th>
<th scope="col" class="col-md-2 text-center">{% translate "Fats" %}</th>
<th scope="col" class="col-md-2 text-center">
{% translate "Average fats" %}
<i class="fa-solid fa-question" rel="tooltip" title="Fats / Characters"></i>
</th>
</tr>
{% for memberStat in fatStats %}
@ -36,6 +39,7 @@
</tr>
{% endfor %}
</table>
</div>
{% endif %}
</div>
{% endblock content %}

View File

@ -1,36 +1,41 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}{% translate "Fatlink statistics" %}{% endblock page_title %}
{% block page_title %}
{% translate "Fatlink Statistics" %}
{% endblock page_title %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% blocktranslate %}Participation data statistics for {{ month }}, {{ year }}{% endblocktranslate %}
<div class="text-right">
<a href="{% url 'fatlink:statistics_month' previous_month|date:"Y" previous_month|date:"m" %}" class="btn btn-info">{% translate "Previous month" %}</a>
<h1 class="page-header text-center">
{% blocktranslate %}Participation data statistics for {{ month }}, {{ year }}{% endblocktranslate %}
<div class="text-end">
<a href="{% url "fatlink:statistics_month" previous_month|date:"Y" previous_month|date:"m" %}" class="btn btn-info">{% translate "Previous month" %}</a>
{% if next_month %}
<a href="{% url 'fatlink:statistics_month' next_month|date:"Y" next_month|date:"m" %}" class="btn btn-info">{% translate "Next month" %}</a>
<a href="{% url 'fatlink:statistics_month' next_month|date:"Y" next_month|date:"m" %}" wclass="btn btn-info">{% translate "Next month" %}</a>
{% endif %}
</div>
</h1>
{% if fatStats %}
<table class="table table-responsive">
<div class="table-responsive">
<table class="table table-striped">
<tr>
<th class="col-md-1"></th>
<th class="col-md-2 text-center">{% translate "Ticker" %}</th>
<th class="col-md-5 text-center">{% translate "Corp" %}</th>
<th class="col-md-2 text-center">{% translate "Members" %}</th>
<th class="col-md-2 text-center">{% translate "Fats" %}</th>
<th class="col-md-2 text-center">{% translate "Average fats" %}
<i class="glyphicon glyphicon-question-sign" rel="tooltip" title="Fats ÷ Characters"></i>
<th scope="col" class="col-md-1"></th>
<th scope="col" class="col-md-2 text-center">{% translate "Ticker" %}</th>
<th scope="col" class="col-md-5 text-center">{% translate "Corp" %}</th>
<th scope="col" class="col-md-2 text-center">{% translate "Members" %}</th>
<th scope="col" class="col-md-2 text-center">{% translate "Fats" %}</th>
<th scope="col" class="col-md-2 text-center">
{% translate "Average fats" %}
<i class="fa-solid fa-question" rel="tooltip" title="Fats / Characters"></i>
</th>
</tr>
{% for corpStat in fatStats %}
<tr>
<td>
<img src="{{ corpStat.corp.logo_url_32 }}" class="ra-avatar img-responsive" alt="{{ corpStat.corp.corporation_name }}">
<img src="{{ corpStat.corp.logo_url_32 }}" class="ra-avatar img-responsive" alt="{{ corpStat.corp.corporation_name }}"/>
</td>
<td class="text-center">
<a href="{% url 'fatlink:statistics_corp' corpStat.corp.corporation_id %}">[{{ corpStat.corp.corporation_ticker }}]</a>
</td>
<td class="text-center"><a href="{% url 'fatlink:statistics_corp' corpStat.corp.corporation_id %}">[{{ corpStat.corp.corporation_ticker }}]</a></td>
<td class="text-center">{{ corpStat.corp.corporation_name }}</td>
<td class="text-center">{{ corpStat.corp.member_count }}</td>
<td class="text-center">{{ corpStat.n_fats }}</td>
@ -38,6 +43,7 @@
</tr>
{% endfor %}
</table>
</div>
{% endif %}
</div>
{% endblock content %}

View File

@ -1,39 +1,41 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}{% translate "Fatlink view" %}{% endblock page_title %}
{% block page_title %}
{% translate "Fatlink view" %}
{% endblock page_title %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "Participation data" %}</h1>
<table class="table">
<div class="table-responsive">
<table class="table table-striped">
<tr>
<th class="col-md-11">
<h4><b>{% translate "Most recent clicked fatlinks" %}</b>
<th class="col-md-10">
<h4>
<b>{% translate "Most recent clicked fatlinks" %}</b>
</h4>
</th>
<th class="col-md-1">
<a href="{% url 'fatlink:personal_statistics' %}" class="btn btn-info">
{% translate "Personal statistics" %}
</a>
<th class="col-md-2 align-self-end">
<a href="{% url 'fatlink:personal_statistics' %}" class="btn btn-info"><i class="fa-solid fa-circle-info fa-fw"></i>{% translate "Personal statistics" %}</a>
</th>
</tr>
</table>
</div>
{% if fats %}
<table class="table table-responsive">
<div class="table-responsive">
<table class="table table-striped">
<tr>
<th class="text-center">{% translate "Fleet" %}</th>
<th class="text-center">{% translate "Character" %}</th>
<th class="text-center">{% translate "System" %}</th>
<th class="text-center">{% translate "Ship" %}</th>
<th class="text-center">{% translate "Eve Time" %}</th>
<th scope="col" class="text-center">{% translate "Fleet" %}</th>
<th scope="col" class="text-center">{% translate "Character" %}</th>
<th scope="col" class="text-center">{% translate "System" %}</th>
<th scope="col" class="text-center">{% translate "Ship" %}</th>
<th scope="col" class="text-center">{% translate "Eve Time" %}</th>
</tr>
{% for fat in fats %}
<tr>
<td class="text-center">{{ fat.fatlink.fleet }}</td>
<td class="text-center">{{ fat.character.character_name }}</td>
{% if fat.station != "No Station" %}
<td class="text-center">{% blocktranslate %}Docked in {% endblocktranslate %}{{ fat.system }}</td>
<td class="text-center">{% translate "Docked in" %} {{ fat.system }}</td>
{% else %}
<td class="text-center">{{ fat.system }}</td>
{% endif %}
@ -42,57 +44,63 @@
</tr>
{% endfor %}
</table>
</div>
{% else %}
<div class="alert alert-warning text-center">{% translate "No fleet activity on record." %}</div>
{% endif %}
{% if perms.auth.fleetactivitytracking %}
<table class="table">
<div class="table-responsive">
<table class="table table-striped">
<tr>
<th class="col-md-10">
<h4><b>{% translate "Most recent fatlinks" %}</b>
<th class="col-md-8">
<h4>
<b>{% translate "Most recent fatlinks" %}</b>
</h4>
</th>
<th class="col-md-1">
<a href="{% url 'fatlink:statistics' %}" class="btn btn-info">
{% translate "View statistics" %}
</a>
<th class="col-md-2 align-self-end">
<a href="{% url 'fatlink:statistics' %}" class="btn btn-info"><i class="fa-solid fa-eye fa-fw"></i> {% translate "View statistics" %}</a>
</th>
<th class="col-md-1">
<a href="{% url 'fatlink:create' %}" class="btn btn-success">
{% translate "Create fatlink" %}
</a>
<th class="col-md-2 align-self-end">
<a href="{% url 'fatlink:create' %}" class="btn btn-success"><i class="fa-solid fa-plus fa-fw"></i> {% translate "Create fatlink" %}</a>
</th>
</tr>
</table>
</div>
{% if fatlinks %}
<table class="table">
<div class="table-responsive">
<table class="table table-striped">
<tr>
<th class="text-center">{% translate "Name" %}</th>
<th class="text-center">{% translate "Creator" %}</th>
<th class="text-center">{% translate "Fleet" %}</th>
<th class="text-center">{% translate "Eve Time" %}</th>
<th class="text-center">{% translate "Duration" %}</th>
<th class="text-center">{% translate "Edit" %}</th>
<th scope="col" class="text-center">{% translate "Name" %}</th>
<th scope="col" class="text-center">{% translate "Creator" %}</th>
<th scope="col" class="text-center">{% translate "Fleet" %}</th>
<th scope="col" class="text-center">{% translate "Eve Time" %}</th>
<th scope="col" class="text-center">{% translate "Duration" %}</th>
<th scope="col" class="text-center">{% translate "Edit" %}</th>
</tr>
{% for link in fatlinks %}
<tr>
<td class="text-center"><a href="{% url 'fatlink:click' link.hash %}" class="label label-primary">{{ link.fleet }}</a></td>
<td class="text-center">
<a href="{% url 'fatlink:click' link.hash %}" class="badge badge-primary">{{ link.fleet }}</a>
</td>
<td class="text-center">{{ link.creator.username }}</td>
<td class="text-center">{{ link.fleet }}</td>
<td class="text-center">{{ link.fatdatetime }}</td>
<td class="text-center">{{ link.duration }}</td>
<td class="text-center">
{{ link.duration }}
</td>
<td class="text-center">
<a href="{% url 'fatlink:modify' link.hash %}" class="btn btn-info">
<span class="glyphicon glyphicon-edit"></span>
<i class="fa-solid fa-pen-to-square fa-fw"></i>
</a>
</td>
</tr>
{% endfor %}
</table>
</div>
{% else %}
<div class="alert alert-warning text-center">{% translate "No created fatlinks on record." %}</div>
<div class="alert alert-warning text-center">
{% translate "No created fatlinks on record." %}
</div>
{% endif %}
{% endif %}
</div>

View File

@ -1,6 +1,7 @@
from django.utils.translation import gettext_lazy as _
from allianceauth.menu.hooks import MenuItemHook
from allianceauth.services.hooks import MenuItemHook, UrlHook
from allianceauth.services.hooks import UrlHook
from allianceauth import hooks
from . import urls
@ -33,11 +34,43 @@ class GroupManagementMenuItem(MenuItemHook):
return ""
"""
<li class="d-flex m-2 p-2 pt-0 pb-0 mt-0 mb-0">
<i class="fas fa-users fa-fw align-self-center me-2"></i>
<a class="nav-link flex-fill align-self-center {% navactive request 'groupmanagement:groups' %}" href="{% url 'groupmanagement:groups' %}">
{% translate "Groups" %}
</a>
</li>
"""
class GroupsMenuItem(MenuItemHook):
def __init__(self):
MenuItemHook.__init__(
self,
text=_("Groups"),
classes="fas fa-user fa-fw",
url_name="groupmanagement:groups",
order=25,
navactive=[
"groupmanagement:groups", # group list view
],
)
def render(self, request):
return MenuItemHook.render(self, request)
@hooks.register("menu_item_hook")
def register_menu():
def register_manager_menu():
return GroupManagementMenuItem()
@hooks.register("menu_item_hook")
def register_groups_menu():
return GroupsMenuItem()
@hooks.register("url_hook")
def register_urls():
return UrlHook(urls, "group", r"^groups/")

View File

@ -1,30 +1,22 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load static %}
{% load i18n %}
{% load navactive %}
{% block page_title %}{{ group }} {% translate "Audit Log" %}{% endblock page_title %}
{% block header_nav_brand %}{% translate "Audit Log" %} - {{ group.name }}{% endblock header_nav_brand %}
{% block header_nav_collapse_left %}
<li class="nav-item ">
<a class="nav-link {% navactive request 'groupmanagement:management' %}" href="{% url 'groupmanagement:management' %}">{% translate "Back" %}</a>
</li>
{% endblock %}
{% block content %}
<div class="col-lg-12">
<br>
{% include 'groupmanagement/menu.html' %}
<div class="panel panel-default">
<div class="panel-heading">
{{ group }} - {% translate "Audit Log" %}
</div>
<div class="panel-body">
<p>
<a class="btn btn-default" href="{% url 'groupmanagement:membership' %}" role="button">
{% translate "Back" %}
</a>
</p>
{% if entries %}
<div class="table-responsive">
<table class="table table-striped" id="log-entries">
<thead>
<tr>
<th scope="col">{% translate "Date/Time" %}</th>
<th scope="col">{% translate "Requestor" %}</th>
<th scope="col">{% translate "Character" %}</th>
@ -32,7 +24,6 @@
<th scope="col">{% translate "Type" %}</th>
<th scope="col">{% translate "Action" %}</th>
<th scope="col">{% translate "Actor" %}</th>
</tr>
</thead>
<tbody>
@ -67,19 +58,16 @@
{% translate "No entries found for this group." %}
</div>
{% endif %}
</div>
</div>
</div>
{% endblock %}
{% block extra_javascript %}
{% include 'bundles/datatables-js.html' %}
{% include 'bundles/datatables-js-bs5.html' %}
{% include 'bundles/moment-js.html' with locale=True %}
{% include 'bundles/filterdropdown-js.html' %}
{% endblock %}
{% block extra_css %}
{% include 'bundles/datatables-css.html' %}
{% include 'bundles/datatables-css-bs5.html' %}
{% endblock %}
{% block extra_script %}

View File

@ -1,26 +1,19 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load static %}
{% load i18n %}
{% load evelinks %}
{% load navactive %}
{% block page_title %}{% translate "Group Members" %}{% endblock page_title %}
{% block header_nav_brand %}{% translate "Group Members" %} - {{ group.name }}{% endblock header_nav_brand %}
{% block header_nav_collapse_left %}
<li class="nav-item ">
<a class="nav-link {% navactive request 'groupmanagement:management' %}" href="{% url 'groupmanagement:management' %}">{% translate "Back" %}</a>
</li>
{% endblock %}
{% block content %}
<div class="col-lg-12">
<br>
{% include 'groupmanagement/menu.html' %}
<div class="panel panel-default">
<div class="panel-heading">
{{ group.name }} - {% translate 'Members' %}
</div>
<div class="panel-body">
<p>
<a class="btn btn-default" href="{% url 'groupmanagement:membership' %}" role="button">
{% translate "Back" %}
</a>
</p>
{% if group.user_set %}
<div class="table-responsive">
<table class="table table-aa" id="tab_group_members">
@ -36,7 +29,7 @@
{% for member in members %}
<tr>
<td>
<img src="{{ member.main_char|character_portrait_url:32 }}" class="img-circle" style="margin-right: 1rem;" alt="{{ member.main_char.character_name }}">
<img src="{{ member.main_char|character_portrait_url:32 }}" class="rounded-circle" style="margin-right: 1rem;">
{% if member.main_char %}
<a href="{{ member.main_char|evewho_character_url }}" target="_blank">
{{ member.main_char.character_name }}
@ -46,7 +39,7 @@
{% endif %}
{% if member.is_leader %}
<i class="fas fa-star" title="{% translate "Group leader" %}" style="margin-left: 1rem;"></i>&nbsp;
<i class="fa-solid fa-star"> title="{% translate "Group leader" %}" style="margin-left: 1rem;"></i>&nbsp;
{% endif %}
</td>
@ -60,10 +53,9 @@
{% translate "(unknown)" %}
{% endif %}
</td>
<td class="text-right">
<td class="text-end">
<a href="{% url 'groupmanagement:membership_remove' group.id member.user.id %}" class="btn btn-danger" title="{% translate "Remove from group" %}">
<i class="glyphicon glyphicon-remove"></i>
<i class="fa-solid fa-xmark"></i>
</a>
</td>
</tr>
@ -72,7 +64,7 @@
</table>
<p class="text-muted">
<i class="fas fa-star"></i>: {% translate "Group leader" %}
<i class="fa-solid fa-star"></i>: {% translate "Group leader" %}
</p>
</div>
{% else %}
@ -80,18 +72,15 @@
{% translate "No group members to list." %}
</div>
{% endif %}
</div>
</div>
</div>
{% endblock content %}
{% block extra_javascript %}
{% include 'bundles/datatables-js.html' %}
{% include 'bundles/datatables-js-bs5.html' %}
{% endblock %}
{% block extra_css %}
{% include 'bundles/datatables-css.html' %}
{% include 'bundles/datatables-css-bs5.html' %}
{% endblock %}
{% block extra_script %}

View File

@ -1,20 +1,20 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load static %}
{% load i18n %}
{% load navactive %}
{% block page_title %}{% translate "Groups Membership" %}{% endblock page_title %}
{% block header_nav_brand %}{% translate "Groups Membership" %}{% endblock header_nav_brand %}
{% block extra_css %}{% endblock extra_css %}
{% block header_nav_collapse_left %}
<li class="nav-item ">
<a class="nav-link {% navactive request 'groupmanagement:management' %}" href="{% url 'groupmanagement:management' %}">{% translate "Join/Leave Requests" %}</a>
</li>
{% endblock header_nav_collapse_left %}
{% block content %}
<div class="col-lg-12">
<br>
{% include 'groupmanagement/menu.html' %}
<div class="panel panel-default">
<div class="panel-heading">
{% translate "Groups" %}
</div>
<div class="panel-body">
{% if groups %}
<div class="table-responsive">
<table class="table table-aa">
@ -23,12 +23,12 @@
<th>{% translate "Name" %}</th>
<th>{% translate "Description" %}</th>
<th>{% translate "Status" %}</th>
<th style="white-space: nowrap;">{% translate "Member Count" %}</th>
<th style="white-space: nowrap;" class="text-center">{% translate "Member Count" %}</th>
<th style="min-width: 170px;"></th>
</tr>
</thead>
<tbody>
<tbody class="align-middle">
{% for group in groups %}
<tr>
<td>
@ -39,29 +39,30 @@
<td>
{% if group.authgroup.hidden %}
<span class="label label-info">{% translate "Hidden" %}</span>
{% elif group.authgroup.open %}
<span class="label label-success">{% translate "Open" %}</span>
<span class="badge bg-info">{% translate "Hidden" %}</span>
{% endif %}
{% if group.authgroup.open %}
<span class="badge bg-success">{% translate "Open" %}</span>
{% else %}
<span class="label label-default">{% translate "Requestable" %}</span>
<span class="badge bg-secondary">{% translate "Requestable" %}</span>
{% endif %}
</td>
<td class="text-right">
<td class="text-center">
{{ group.num_members }}
</td>
<td class="text-right">
<td class="text-end">
<a href="{% url 'groupmanagement:membership' group.id %}" class="btn btn-primary" title="{% translate "View Members" %}">
<i class="glyphicon glyphicon-eye-open"></i>
<i class="far fa-eye"></i>
</a>
<a href="{% url "groupmanagement:audit_log" group.id %}" class="btn btn-info" title="{% translate "Audit Members" %}">
<i class="glyphicon glyphicon-list-alt"></i>
<i class="far fa-list-alt"></i>
</a>
<a id="clipboard-copy" data-clipboard-text="{{ SITE_URL }}{% url 'groupmanagement:request_add' group.id %}" class="btn btn-warning" title="{% translate "Copy Direct Join Link" %}">
<i class="glyphicon glyphicon-copy"></i>
<a id="clipboard-copy" data-clipboard-text="{{ request.scheme }}://{{request.get_host}}{% url 'groupmanagement:request_add' group.id %}" class="btn btn-warning" title="{% translate "Copy Direct Join Link" %}">
<i class="far fa-clipboard"></i>
</a>
</td>
</tr>
@ -74,15 +75,12 @@
{% translate "No groups to list." %}
</div>
{% endif %}
</div>
</div>
</div>
{% endblock content %}
{% block extra_javascript %}
{% include 'bundles/clipboard-js.html' %}
{% include "bundles/clipboard-js.html" %}
<script>
new ClipboardJS('#clipboard-copy');
</script>
{% endblock %}
{% endblock extra_javascript %}

View File

@ -1,29 +1,48 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load static %}
{% load i18n %}
{% block page_title %}{% translate "Available Groups" %}{% endblock page_title %}
{% block extra_css %}{% endblock extra_css %}
{% block header_nav_brand %}{% translate "Available Groups" %}{% endblock header_nav_brand %}
{% if manager_perms %}
{% block header_nav_collapse_left %}
<li class="nav-item">
<a class="nav-link" href="{% url 'groupmanagement:management' %}">{% translate "Group Management" %}
{% if req_count %}
<span class="badge bg-secondary">{{ req_count }}</span>
{% endif %}
</a>
</li>
{% endblock %}
{% endif %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "Available Groups" %}</h1>
{% if groups %}
<table class="table table-aa">
<table class="table" id="groupsTable" >
<thead>
<tr>
<th>{% translate "Name" %}</th>
<th>{% translate "Description" %}</th>
<th>{% translate "Leaders" %}<span class="m-1 fw-lighter badge bg-primary">User</span><span class="m-1 fw-lighter badge bg-secondary ">Group</span></th>
<th></th>
</tr>
</thead>
<tbody>
<tbody class>
{% for g in groups %}
<tr>
<td>{{ g.group.name }}</td>
<td>{{ g.group.authgroup.description|linebreaks|urlize }}</td>
<td class="text-right">
{% if g.group in user.groups.all %}
<td style="max-width: 30%;">
{% if g.group.authgroup.group_leaders.all.count %}
{% for leader in g.group.authgroup.group_leaders.all %}{% if leader.profile.main_character %}<span class="m-1 badge bg-primary">{{leader.profile.main_character}}</span>{% endif %}{% endfor %}
{% endif %}
{% if g.group.authgroup.group_leaders.all.count %}
{% for group in g.group.authgroup.group_leader_groups.all %}<span class="badge bg-secondary">{{group.name}}</span>{% endfor %}
{% endif %}
</td>
<td class="text-end">
{% if g.group in user_groups %}
{% if not g.request %}
<a href="{% url 'groupmanagement:request_leave' g.group.id %}" class="btn btn-danger">
{% translate "Leave" %}
@ -53,10 +72,25 @@
{% endfor %}
</tbody>
</table>
{% else %}
<div class="alert alert-warning text-center">
{% translate "No groups available." %}
</div>
{% endif %}
</div>
{% endblock content %}
{% block extra_javascript %}
{% include 'bundles/datatables-js-bs5.html' %}
{% endblock %}
{% block extra_css %}
{% include 'bundles/datatables-css-bs5.html' %}
{% endblock %}
{% block extra_script %}
$(document).ready(function () {
$('#groupsTable').DataTable();
});
{% endblock extra_script %}

View File

@ -1,51 +1,46 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load static %}
{% load i18n %}
{% load evelinks %}
{% load navactive %}
{% block page_title %}{% translate "Groups Management" %}{% endblock page_title %}
{% block header_nav_brand %}{% translate "Groups Management" %}{% endblock header_nav_brand %}
{% block extra_css %}
<style>
.nav-tabs > li.active > a {
background-color: rgb(236, 240, 241) !important;
color: rgb(44, 62, 80);
}
</style>
{% endblock extra_css %}
{% block content %}
<div class="col-lg-12">
<br>
{% include 'groupmanagement/menu.html' %}
<ul class="nav nav-tabs">
{% block header_nav_collapse_left %}
<li class="active">
<a data-toggle="tab" href="#add">
<a class="nav-link active" id="add-tab" data-bs-toggle="tab" data-bs-target="#add" type="button" role="tab" aria-controls="addd" aria-selected="true">
{% translate "Join Requests" %}
{% if acceptrequests %}
<span class="badge">{{ acceptrequests|length }}</span>
<span class="badge bg-secondary">{{ acceptrequests|length }}</span>
{% endif %}
</a>
</li>
{% if not auto_leave %}
<li>
<a data-toggle="tab" href="#leave">
<a class="nav-link" id="leave-tab" data-bs-toggle="tab" data-bs-target="#leave" type="button" role="tab" aria-controls="leave" aria-selected="false">
{% translate "Leave Requests" %}
{% if leaverequests %}
<span class="badge">{{ leaverequests|length }}</span>
<span class="badge bg-secondary">{{ leaverequests|length }}</span>
{% endif %}
</a>
</li>
{% endif %}
</ul>
<li class="nav-item ">
<a class="nav-link {% navactive request 'groupmanagement:membership groupmanagement:audit_log' %}" href="{% url 'groupmanagement:membership' %}">{% translate "Group Membership" %}</a>
</li>
<div class="panel panel-default panel-tabs-aa">
<div class="panel-body">
{% endblock %}
{% block content %}
<div class="tab-content">
<div id="add" class="tab-pane active">
{% if acceptrequests %}
<div class="table-responsive">
@ -59,11 +54,11 @@
</tr>
</thead>
<tbody>
<tbody class="align-middle">
{% for acceptrequest in acceptrequests %}
<tr>
<td>
<img src="{{ acceptrequest.main_char|character_portrait_url:32 }}" class="img-circle" style="margin-right: 1rem;" alt="{{ acceptrequest.main_char.character_name }}">
<img src="{{ acceptrequest.main_char|character_portrait_url:32 }}" class="rounded-circle" style="margin-right: 1rem;">
{% if acceptrequest.main_char %}
<a href="{{ acceptrequest.main_char|evewho_character_url }}" target="_blank">
{{ acceptrequest.main_char.character_name }}
@ -83,7 +78,7 @@
{% endif %}
</td>
<td>{{ acceptrequest.group.name }}</td>
<td class="text-right">
<td class="text-end">
<a href="{% url 'groupmanagement:accept_request' acceptrequest.id %}" class="btn btn-success">
{% translate "Accept" %}
</a>
@ -116,11 +111,11 @@
</tr>
</thead>
<tbody>
<tbody class="align-middle">
{% for leaverequest in leaverequests %}
<tr>
<td>
<img src="{{ leaverequest.main_char|character_portrait_url:32 }}" class="img-circle" style="margin-right: 1rem;" alt="{{ leaverequest.main_char.character_name }}">
<img src="{{ leaverequest.main_char|character_portrait_url:32 }}" class="rounded-circle" style="margin-right: 1rem;">
{% if leaverequest.main_char %}
<a href="{{ leaverequest.main_char|evewho_character_url }}" target="_blank">
{{ leaverequest.main_char.character_name }}
@ -140,7 +135,7 @@
{% endif %}
</td>
<td>{{ leaverequest.group.name }}</td>
<td class="text-right">
<td class="text-end">
<a href="{% url 'groupmanagement:leave_accept_request' leaverequest.id %}" class="btn btn-success">
{% translate "Accept" %}
</a>
@ -160,7 +155,4 @@
</div>
{% endif %}
</div>
</div>
</div>
</div>
{% endblock content %}

View File

@ -1,27 +1,10 @@
{% load i18n %}
{% load navactive %}
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">{% translate "Toggle navigation" %}</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="{% url 'groupmanagement:management' %}">{% translate "Group Management" %}</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="{% navactive request 'groupmanagement:management' %}">
<a href="{% url 'groupmanagement:management' %}">{% translate "Group Requests" %}</a>
<li class="nav-item ">
<a class="nav-link {% navactive request 'groupmanagement:management' %}" href="{% url 'groupmanagement:management' %}">{% translate "Group Requests" %}</a>
</li>
<li class="{% navactive request 'groupmanagement:membership groupmanagement:audit_log' %}">
<a href="{% url 'groupmanagement:membership' %}">{% translate "Group Membership" %}</a>
<li class="nav-item ">
<a class="nav-link {% navactive request 'groupmanagement:membership groupmanagement:audit_log' %}" href="{% url 'groupmanagement:membership' %}">{% translate "Group Membership" %}</a>
</li>
</ul>
</div>
</div>
</nav>

View File

@ -87,7 +87,7 @@ def group_membership_audit(request, group_id):
except ObjectDoesNotExist:
raise Http404("Group does not exist")
render_items = {'group': group.name}
render_items = {'group': group}
entries = RequestLog.objects.filter(group=group).order_by('-date')
render_items['entries'] = entries
@ -311,8 +311,10 @@ def groups_view(request):
groups_qs = GroupManager.get_joinable_groups_for_user(
request.user, include_hidden=False
)
groups_qs = groups_qs.order_by('name')
groups_qs = groups_qs.order_by('name').select_related("authgroup").prefetch_related('authgroup__group_leaders', 'authgroup__group_leaders__profile__main_character', 'authgroup__group_leader_groups')
groups = []
## TODO see about making this faster
for group in groups_qs:
group_request = GroupRequest.objects\
.filter(user=request.user)\
@ -322,7 +324,14 @@ def groups_view(request):
'request': group_request[0] if group_request else None
})
context = {'groups': groups}
count = 0
perms = GroupManager.can_manage_groups(request.user)
if perms:
count = GroupManager.pending_requests_count_for_user(request.user)
user_groups_list = list(request.user.groups.all())
context = {'groups': groups, "manager_perms": perms, "req_count":count, "user_groups": user_groups_list}
return render(request, 'groupmanagement/groups.html', context=context)

View File

@ -91,7 +91,7 @@ def get_app_modules():
def get_app_submodules(module_name):
"""
"""pyt
Get a specific sub module of the app
:param module_name: module name to get
:return: name, module tuple
@ -122,3 +122,17 @@ def get_hooks(name):
"""
register_all_hooks()
return _hooks.get(name, [])
class DashboardItemHook:
def __init__(self, view_function, order:int=10):
self.view_function = view_function
self.order = order
def render(self, request):
try:
logger.debug(f"Rendering {self.view_function} to dashboard")
return self.view_function(request)
except Exception as e:
logger.exception("Rendering {self.view_function} Failed!")
return ""

View File

@ -1,7 +1,8 @@
from django.utils.translation import gettext_lazy as _
from allianceauth import hooks
from allianceauth.services.hooks import MenuItemHook, UrlHook
from allianceauth.menu.hooks import MenuItemHook
from allianceauth.services.hooks import UrlHook
from . import urls
from .models import Application

View File

@ -1,4 +1,4 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}{% translate "Choose a Corp" %}{% endblock page_title %}

View File

@ -1,4 +1,4 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}{% translate "Apply To" %} {{ corp.corporation_name }}{% endblock page_title %}

View File

@ -8,7 +8,7 @@
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "Personal Applications" %}
<div class="text-right">
<div class="text-end">
{% if create %}
<a href="{% url 'hrapplications:create_view' %}">
<button type="button" class="btn btn-success">{% translate "Create Application" %}</button>
@ -33,11 +33,11 @@
<td class="text-center">{{ personal_app.form.corp.corporation_name }}</td>
<td class="text-center">
{% if personal_app.approved == None %}
<div class="label label-warning">{% translate "Pending" %}</div>
<div class="badge badge-warning">{% translate "Pending" %}</div>
{% elif personal_app.approved == True %}
<div class="label label-success">{% translate "Approved" %}</div>
<div class="badge badge-success">{% translate "Approved" %}</div>
{% else %}
<div class="label label-danger">{% translate "Rejected" %}</div>
<div class="badge badge-danger">{% translate "Rejected" %}</div>
{% endif %}
</td>
<td class="text-center">
@ -58,7 +58,7 @@
{% endif %}
{% if perms.auth.human_resources %}
<h1 class="page-header text-center">{% translate "Application Management" %}
<div class="text-right">
<div class="text-end">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#myModal">
{% translate "Search Applications" %}
@ -91,14 +91,14 @@
<td class="text-center">
{% if app.approved == None %}
{% if app.reviewer_str %}
<div class="label label-info">{% translate "Reviewer:" %} {{ app.reviewer_str }}</div>
<div class="badge badge-info">{% translate "Reviewer:" %} {{ app.reviewer_str }}</div>
{% else %}
<div class="label label-warning">{% translate "Pending" %}</div>
<div class="badge badge-warning">{% translate "Pending" %}</div>
{% endif %}
{% elif app.approved == True %}
<div class="label label-success">{% translate "Approved" %}</div>
<div class="badge badge-success">{% translate "Approved" %}</div>
{% else %}
<div class="label label-danger">{% translate "Rejected" %}</div>
<div class="badge badge-danger">{% translate "Rejected" %}</div>
{% endif %}
</td>
<td class="text-center">
@ -135,14 +135,14 @@
<td class="text-center">
{% if app.approved == None %}
{% if app.reviewer_str %}
<div class="label label-info">{% translate "Reviewer:" %} {{ app.reviewer_str }}</div>
<div class="badge badge-info">{% translate "Reviewer:" %} {{ app.reviewer_str }}</div>
{% else %}
<div class="label label-warning">{% translate "Pending" %}</div>
<div class="badge badge-warning">{% translate "Pending" %}</div>
{% endif %}
{% elif app.approved == True %}
<div class="label label-success">{% translate "Approved" %}</div>
<div class="badge badge-success">{% translate "Approved" %}</div>
{% else %}
<div class="label label-danger">{% translate "Rejected" %}</div>
<div class="badge badge-danger">{% translate "Rejected" %}</div>
{% endif %}
</td>
<td class="text-center">

View File

@ -9,7 +9,7 @@
<div class="col-lg-12">
{% if perms.auth.human_resources %}
<h1 class="page-header text-center">{% translate "Application Search Results" %}
<div class="text-right">
<div class="text-end">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#myModal">
{% translate "Search Applications" %}
@ -34,11 +34,11 @@
<td class="text-center">{{ app.form.corp }}</td>
<td class="text-center">
{% if app.approved == None %}
<div class="label label-warning">{% translate "Pending" %}</div>
<div class="badge badge-warning">{% translate "Pending" %}</div>
{% elif app.approved == True %}
<div class="label label-success">{% translate "Approved" %}</div>
<div class="badge badge-success">{% translate "Approved" %}</div>
{% else %}
<div class="label label-danger">{% translate "Rejected" %}</div>
<div class="badge badge-danger">{% translate "Rejected" %}</div>
{% endif %}
</td>
<td class="text-center">

View File

View File

@ -0,0 +1,9 @@
from django.contrib import admin
from . import models
@admin.register(models.MenuItem)
class MenuItemAdmin(admin.ModelAdmin):
list_display = ['text', 'hide', 'parent', 'url', 'icon_classes', 'rank']
ordering = ('rank',)

19
allianceauth/menu/apps.py Normal file
View File

@ -0,0 +1,19 @@
import logging
from django.apps import AppConfig
from django.db.utils import ProgrammingError, OperationalError
logger = logging.getLogger(__name__)
class MenuConfig(AppConfig):
name = "allianceauth.menu"
label = "menu"
def ready(self):
try:
logger.debug("Syncing MenuItem Hooks")
from allianceauth.menu.providers import MenuItem
MenuItem.sync_hook_models()
except (ProgrammingError, OperationalError):
logger.warning("Migrations not completed for MenuItems")

View File

@ -0,0 +1,42 @@
from django.template.loader import render_to_string
from typing import List, Optional
class MenuItemHook:
"""
Auth Hook for generating Side Menu Items
"""
def __init__(self, text: str, classes: List[str], url_name: str, order: Optional[int] = None, navactive: List = list([])):
"""
:param text: The text shown as menu item, e.g. usually the name of the app.
:type text: str
:param classes: The classes that should be applied to the menu item icon
:type classes: List[str]
:param url_name: The name of the Django URL to use
:type url_name: str
:param order: An integer which specifies the order of the menu item, lowest to highest. Community apps are free to use any order above `1000`. Numbers below are served for Auth.
:type order: Optional[int], optional
:param navactive: A list of views or namespaces the link should be highlighted on. See [django-navhelper](https://github.com/geelweb/django-navhelper#navactive) for usage. Defaults to the supplied `url_name`.
:type navactive: List, optional
"""
self.text = text
self.classes = classes
self.url_name = url_name
self.template = 'public/menuitem.html'
self.order = order if order is not None else 9999
# count is an integer shown next to the menu item as badge when count != None
# apps need to set the count in their child class, e.g. in render() method
self.count = None
navactive = navactive or []
navactive.append(url_name)
self.navactive = navactive
def render(self, request):
return render_to_string(self.template,
{'item': self},
request=request)

View File

@ -0,0 +1,28 @@
# Generated by Django 4.0.2 on 2022-08-28 14:00
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='MenuItem',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('hook_function', models.CharField(max_length=500)),
('icon_classes', models.CharField(max_length=150)),
('text', models.CharField(max_length=150)),
('url', models.CharField(blank=True, default=None, max_length=2048, null=True)),
('rank', models.IntegerField(default=1000)),
('hide', models.BooleanField(default=False)),
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='menu.menuitem')),
],
),
]

View File

@ -0,0 +1,28 @@
# Generated by Django 4.0.2 on 2022-08-28 14:10
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('menu', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='menuitem',
name='hook_function',
field=models.CharField(blank=True, default=None, max_length=500, null=True),
),
migrations.AlterField(
model_name='menuitem',
name='icon_classes',
field=models.CharField(blank=True, default=None, max_length=150, null=True),
),
migrations.AlterField(
model_name='menuitem',
name='text',
field=models.CharField(blank=True, default=None, max_length=150, null=True),
),
]

View File

@ -0,0 +1,17 @@
# Generated by Django 4.0.8 on 2023-02-05 07:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('menu', '0002_alter_menuitem_hook_function_and_more'),
]
operations = [
migrations.AddIndex(
model_name='menuitem',
index=models.Index(fields=['rank'], name='menu_menuit_rank_e880ab_idx'),
),
]

View File

@ -0,0 +1,39 @@
# Generated by Django 4.0.10 on 2023-07-16 11:41
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('menu', '0003_menuitem_menu_menuit_rank_e880ab_idx'),
]
operations = [
migrations.AlterField(
model_name='menuitem',
name='hide',
field=models.BooleanField(default=False, help_text='Hide this menu item. If this item is a header all items under it will be hidden too.'),
),
migrations.AlterField(
model_name='menuitem',
name='icon_classes',
field=models.CharField(blank=True, default=None, help_text='Font Awesome classes to show as icon on menu', max_length=150, null=True),
),
migrations.AlterField(
model_name='menuitem',
name='parent',
field=models.ForeignKey(blank=True, help_text='Parent Header. (Optional)', null=True, on_delete=django.db.models.deletion.SET_NULL, to='menu.menuitem'),
),
migrations.AlterField(
model_name='menuitem',
name='rank',
field=models.IntegerField(default=1000, help_text='Order of the menu. Lowest First.'),
),
migrations.AlterField(
model_name='menuitem',
name='text',
field=models.CharField(blank=True, default=None, help_text='Text to show on menu', max_length=150, null=True),
),
]

View File

174
allianceauth/menu/models.py Normal file
View File

@ -0,0 +1,174 @@
import logging
from allianceauth.hooks import get_hooks
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.template.loader import render_to_string
logger = logging.getLogger(__name__)
class MenuItem(models.Model):
# Auto Generated model from an auth_hook
hook_function = models.CharField(
max_length=500, default=None, null=True, blank=True)
# User Made Model
icon_classes = models.CharField(
max_length=150, default=None, null=True, blank=True, help_text="Font Awesome classes to show as icon on menu")
text = models.CharField(
max_length=150, default=None, null=True, blank=True, help_text="Text to show on menu")
url = models.CharField(max_length=2048, default=None,
null=True, blank=True)
# Put it under a header?
parent = models.ForeignKey(
'self', on_delete=models.SET_NULL, null=True, blank=True, help_text="Parent Header. (Optional)")
# Put it where? lowest first
rank = models.IntegerField(default=1000, help_text="Order of the menu. Lowest First.")
# Hide it fully? Hiding a parent will hide all it's children
hide = models.BooleanField(default=False, help_text="Hide this menu item. If this item is a header all items under it will be hidden too.")
class Meta:
indexes = [
models.Index(fields=['rank', ]),
]
def __str__(self) -> str:
return self.text
@property
def classes(self): # Helper function to make this model closer to the hook functions
return self.icon_classes
@staticmethod
def hook_to_name(mh):
return f"{mh.__class__.__module__}.{mh.__class__.__name__}"
@staticmethod
def sync_hook_models():
# TODO define aa way for hooks to predefine a "parent" to create a sub menu from modules
menu_hooks = get_hooks('menu_item_hook')
hook_functions = []
for hook in menu_hooks:
mh = hook()
cls = MenuItem.hook_to_name(mh)
try:
# if it exists update the text only
# Users can adjust ranks so lets not change it if they have.
mi = MenuItem.objects.get(hook_function=cls)
mi.text = getattr(mh, "text", mh.__class__.__name__)
mi.save()
except MenuItem.DoesNotExist:
# This is a new hook, Make the database model.
MenuItem.objects.create(
hook_function=cls,
rank=getattr(mh, "order", 500),
text=getattr(mh, "text", mh.__class__.__name__)
)
hook_functions.append(cls)
# Get rid of any legacy hooks from modules removed
MenuItem.objects.filter(hook_function__isnull=False).exclude(
hook_function__in=hook_functions).delete()
@classmethod
def filter_items(cls, menu_item: dict):
"""
filter any items with no valid children from a menu
"""
count_items = len(menu_item['items'])
if count_items: # if we have children confirm we can see them
for i in menu_item['items']:
if len(i['render']) == 0:
count_items -= 1
if count_items == 0: # no children left dont render header
return False
return True
else:
return True
@classmethod
def render_menu(cls, request):
"""
Return the sorted side menu items with any items the user can't see removed.
"""
# Override all the items to the bs5 theme
template = "menu/menu-item-bs5.html"
# TODO discuss permissions for user defined links
# Turn all the hooks into functions
menu_hooks = get_hooks('menu_item_hook')
items = {}
for fn in menu_hooks:
f = fn()
items[cls.hook_to_name(f)] = f
menu_items = MenuItem.objects.all().order_by("rank")
menu = {}
for mi in menu_items:
if mi.hide:
# hidden item, skip it completely
continue
try:
_cnt = 0
_render = None
if mi.hook_function:
# This is a module hook, so we need to render it as the developer intended
# TODO add a new attribute for apps that want to override it in the new theme
items[mi.hook_function].template = template
_render = items[mi.hook_function].render(request)
_cnt = items[mi.hook_function].count
else:
# This is a user defined menu item so we render it with defaults.
_render = render_to_string(template,
{'item': mi},
request=request)
parent = mi.id
if mi.parent_id: # Set it if present
parent = mi.parent_id
if parent not in menu: # this will cause the menu headers to be out of order
menu[parent] = {"items": [],
"count": 0,
"render": None,
"text": "None",
"rank": 9999,
}
_mi = {
"count": _cnt,
"render": _render,
"text": mi.text,
"rank": mi.rank,
"classes": (mi.icon_classes if mi.icon_classes != "" else "fas fa-folder"),
"hide": mi.hide
}
if parent != mi.id:
# this is a sub item
menu[parent]["items"].append(_mi)
if _cnt:
#add its count to the header count
menu[parent]["count"] += _cnt
else:
if len(menu[parent]["items"]):
# this is a top folder dont update the count.
del(_mi["count"])
menu[parent].update(_mi)
except Exception as e:
logger.exception(e)
# reset to list
menu = list(menu.values())
# sort the menu list as the parents may be out of order.
menu.sort(key=lambda i: i['rank'])
# ensure no empty groups
menu = filter(cls.filter_items, menu)
return menu

View File

@ -0,0 +1,10 @@
from django.template.loader import render_to_string
from allianceauth.hooks import get_hooks
from .models import MenuItem
class MenuProvider():
def __init__(self) -> None:
pass

View File

@ -0,0 +1,7 @@
{% for data in menu_items %}
{% if data.items|length > 0 %}
{% include "menu/menu-item-bs5.html" with item=data %}
{% else %}
{{ data.render }}
{% endif %}
{% endfor %}

View File

@ -0,0 +1,32 @@
{% load i18n %}
{% load navactive %}
{% if not item.hide %}
<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 {{ item.classes }} fa-fw align-self-center me-3 {% if item.navactive %}{% navactive request item.navactive|join:' ' %}{% endif %}" {% if item.items|length %} type="button" data-bs-toggle="collapse" data-bs-target="#id-{{ item.text|slugify }}" aria-expanded="false" aria-controls="" {% endif %}></i>
<a class="nav-link flex-fill align-self-center" {% if item.items|length %} type="button" data-bs-toggle="collapse" data-bs-target="#id-{{ item.text|slugify }}" aria-expanded="false" aria-controls="" {% endif %}
href="{% if item.url_name %}{% url item.url_name %}{% else %}{{ item.url }}{% endif %}">
{% translate item.text %}
</a>
{% if item.count >= 1 %}
<span class="badge bg-primary rounded-pill m-2 align-self-center {% if item.items|length == 0 %}me-4{% endif %}">
{{ item.count }}
</span>
{% elif item.url %}
<span class="pill m-2 me-4 align-self-center fas fa-external-link-alt"></span>
{% endif %}
{% if item.items|length > 0 %}
<span class="pill m-2 me-4 align-self-center fas fa-solid fa-chevron-down"
type="button"
data-bs-toggle="collapse"
data-bs-target="#id-{{ item.text|slugify }}"
aria-expanded="false"
aria-controls=""></span>
<!--<hr class="m-0 w-100">-->
<ul class="collapse ps-1 w-100 border-start rounded-start border-light border-3" id="id-{{ item.text|slugify }}">
{% for sub_item in item.items %}
{{ sub_item.render }}
{% endfor %}
</ul>
{% endif %}
</li>
{% endif %}

View File

@ -0,0 +1,19 @@
{% load i18n %}
{% load navactive %}
{% load auth_notifications %}
<li class="nav-item {% navactive request 'notifications:' %}"
id="menu_item_notifications">
<a class="nav-link"
href="{% url 'notifications:list' %}">
<span class="fa">
{% with unread_count=request.user|user_unread_notification_count %}
<i
class="fas fa-bell{% if unread_count %} text-danger{% endif %}"
></i>
{% endwith %}
</span>
<span class="d-lg-none d-md-inline m-2">
{% translate "Notifications" %}
</span>
</a>
</li>

View File

@ -0,0 +1,51 @@
{% load i18n %}
{% load evelinks %}
{% load theme_tags %}
<div style="z-index:5;" class="w100 d-flex flex-column justify-content-center align-items-center text-center pb-2">
{% if request.user.profile.main_character %}
{% with request.user.profile.main_character as main %}
<div class="p-2 position-relative m-2">
<img class="rounded-circle" src="{{ main.character_id|character_portrait_url:64 }}" alt="{{ main.character_name }}"/>
<img class="rounded-circle position-absolute bottom-0 start-0" src="{{ main.corporation_logo_url_32 }}" alt="{{ main.corporation_name }}"/>
{% if main.alliance_id %}
<img class="rounded-circle position-absolute bottom-0 end-0" src="{{ main.alliance_logo_url_32 }}" alt="{{ main.alliance_name }}"/>
{% elif main.faction_id %}
<img class="rounded-circle position-absolute bottom-0 end-0" src="{{ main.faction_logo_url_32 }}" alt="{{ main.faction_name }}"/>
{% endif %}
</div>
<h5>{{ main.character_name }}</h5>
{% endwith %}
{% else %}
<img class="rounded-circle m-2" src="{{ 1|character_portrait_url:32 }}" alt="{% translate 'No Main Character!' %}"/>
<h5>{% translate "No Main Character!" %}</h5>
{% endif %}
{% if user.is_authenticated %}
{% theme_select %}
{% endif %}
<div class="btn-group m-2">
<button type="button" class="btn btn-secondary p-1">
{% include "public/lang_select.html" %}
</button>
{% if user.is_superuser %}
<a role="button" class="btn btn btn-secondary d-flex"
href="{% url 'admin:index' %}"
bs-data-toggle="button">
<span class="align-self-center">{% translate "Admin" %}</span>
</a>
{% endif %}
</div>
<div class="btn-group m-2">
<a role="button" class="btn btn-info" href="{% url 'authentication:token_management' %}" alt="Token Management"><i class="fa-solid fa-user-lock fa-fw"></i></a>
{% if user.is_superuser %}
<a role="button" class="btn btn-info" href="https://allianceauth.readthedocs.io/" alt="Alliance Auth Documentation"><i class="fa-solid fa-book fa-fw"></i></a>
<a role="button" class="btn btn-info" href="https://discord.gg/fjnHAmk" alt="Alliance Auth Discord"><i class="fa-brands fa-discord fa-fw"></i></a>
<a role="button" class="btn btn-info" href="https://gitlab.com/allianceauth/allianceauth" alt="Alliance Auth Git"><i class="fa-brands fa-gitlab fa-fw"></i></a>
{% endif %}
{% if user.is_authenticated %}
<a role="button" class="btn btn-danger" href="{% url 'logout' %}" alt="{% translate 'Sign Out' %}"><i class="fa-solid fa-right-from-bracket fa-fw"></i></a>
{% else %}
<a role="button" class="btn btn-success" href="{% url 'authentication:login' %}" alt="{% translate 'Sign In' %}"> <i class="fa-solid fa-right-to-bracket fa-fw"></i></a>
{% endif %}
</div>
</div>

View File

@ -0,0 +1,21 @@
{% load i18n %}
{% load navactive %}
{% load menu_items %}
<div class="col-auto px-0 " >
<div class="collapse collapse-horizontal" tabindex="-1" id="sidebar" >
<div style="width: 350px;">
<div class="nav-padding navbar-dark bg-dark text-light px-0 d-flex flex-column overflow-hidden vh-100 auth-logo" >
<ul style="z-index:5;" 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' %}">
{% translate "Dashboard" %}
</a>
</li>
{% sorted_menu_items %}
</ul>
{% include 'menu/menu-user.html' %}
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,35 @@
from django import template
from allianceauth.hooks import get_hooks
from allianceauth.menu.models import MenuItem
from ..providers import MenuProvider
register = template.Library()
def process_menu_items(hooks, request):
_menu_items = list()
items = [fn() for fn in hooks]
items.sort(key=lambda i: i.order)
for item in items:
_menu_items.append(item.render(request))
return _menu_items
@register.inclusion_tag('public/menublock.html', takes_context=True)
def menu_items(context):
request = context['request']
return {
'menu_items': process_menu_items(get_hooks('menu_item_hook'), request),
}
@register.inclusion_tag('menu/menu-block.html', takes_context=True)
def sorted_menu_items(context):
request = context['request']
manu_items = MenuItem.render_menu(request)
return {
'menu_items':manu_items
}

View File

@ -1,37 +1,47 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load static %}
{% load i18n %}
{% block page_title %}{% translate "Notifications" %}{% endblock %}
{% block page_title %}
{% translate "Notifications" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "Notifications" %}
{% endblock header_nav_brand %}
{% block header_nav_collapse_left %}
<li class="nav-item">
<a class="nav-link active" id="unread-tab" data-bs-toggle="tab" data-bs-target="#unread" type="button" role="tab" aria-controls="unread" aria-selected="true">
{% translate "Unread" %}
<span class="badge bg-secondary">{{ unread|length }}</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" id="read-tab" data-bs-toggle="tab" data-bs-target="#read" type="button" role="tab" aria-controls="read" aria-selected="false">
{% translate "Read" %}
<span class="badge bg-secondary">{{ read|length }}</span>
</a>
</li>
{% endblock %}
{% block header_nav_collapse_right %}
<li class="nav-item">
<a href="{% url 'notifications:mark_all_read' %}" class="nav-link">
<i class="fas fa-check-double"></i>
</a>
</li>
<li class="nav-item">
<a href="{% url 'notifications:delete_all_read' %}" class="nav-link">
<i class="fas fa-trash"></i>
</a>
</li>
{% endblock %}
{% block content %}
<h1 class="page-header text-center">{% translate "Notifications" %}</h1>
<div class="panel panel-default">
<div class="panel-heading clearfix">
<ul class="nav nav-pills navbar-left">
<li class="active"><a data-toggle="tab" href="#unread">{% translate "Unread" %}<b>({{ unread|length }})</b></a></li>
<li><a data-toggle="tab" href="#read">{% translate "Read" %} <b>({{ read|length }})</b></a></li>
</ul>
<div class="nav navbar-nav navbar-right" style="margin-right: 0;">
<a href="{% url 'notifications:mark_all_read' %}" class="btn btn-warning">{% translate "Mark All Read" %}</a>
<a href="{% url 'notifications:delete_all_read' %}" class="btn btn-danger">{% translate "Delete All Read" %}</a>
</div>
</div>
<div class="panel-body">
<div class="tab-content">
<div id="unread" class="tab-pane fade in active">
<div class="tab-pane active" id="unread">
{% include "notifications/list_partial.html" with notifications=unread %}
</div>
<div id="read" class="tab-pane fade">
{% include "notifications/list_partial.html" with notifications=read %}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,8 +1,7 @@
{% load i18n %}
{% if notifications %}
<div class="table-responsive">
<table class="table table-condensed table-hover table-striped">
<table class="table table-striped">
<tr>
<th class="text-center">{% translate "Timestamp" %}</th>
<th class="text-center">{% translate "Title" %}</th>
@ -14,16 +13,15 @@
<td class="text-center">{{ notif.title }}</td>
<td class="text-center">
<a href="{% url 'notifications:view' notif.id %}" class="btn btn-primary" title="View">
<span class="glyphicon glyphicon-eye-open"></span>
<span class="fas fa-eye"></span>
</a>
<a href="{% url 'notifications:remove' notif.id %}" class="btn btn-danger" title="Remove">
<span class="glyphicon glyphicon-remove"></span>
<span class="fas fa-trash"></span>
</a>
</td>
</tr>
{% endfor %}
</table>
</div>
{% else %}
<div class="alert alert-default text-center">{% translate "No notifications." %}</div>
{% endif %}

View File

@ -6,7 +6,7 @@
{% block content %}
<h1 class="page-header text-center">
{% translate "View Notification" %}
<div class="text-right">
<div class="text-end">
<a href="{% url 'notifications:list' %}" class="btn btn-primary btn-lg">
<span class="glyphicon glyphicon-arrow-left"></span>
</a>

View File

@ -1,4 +1,6 @@
from allianceauth.services.hooks import MenuItemHook, UrlHook
from allianceauth.menu.hooks import MenuItemHook
from allianceauth.optimer.views import dashboard_ops
from allianceauth.services.hooks import UrlHook
from django.utils.translation import gettext_lazy as _
from allianceauth import hooks
from . import urls
@ -27,3 +29,17 @@ def register_menu():
@hooks.register('url_hook')
def register_url():
return UrlHook(urls, 'optimer', r'^optimer/')
class NextOpsHook(hooks.DashboardItemHook):
def __init__(self): #TODO add the view permms so if they cant see it is not rendered
hooks.DashboardItemHook.__init__(
self,
dashboard_ops,
6
)
@hooks.register('dashboard_hook')
def register_groups_hook():
return NextOpsHook()

View File

@ -0,0 +1,38 @@
{% load i18n %}
{% load evelinks %}
<div class="col-12 col-xl-6 align-self-stretch p-2">
<div class="card h-100">
<div class="card-body">
<h4 class="card-title text-center">{% translate "Upcoming Fleets" %}</h4>
<div class="card-body">
<div style="height: 300px;overflow:-moz-scrollbars-vertical;overflow-y:auto;">
<table class="table" style="--bs-table-bg: transparent;">
<thead>
<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 "Start Time" %}</th>
</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>
</div>
</div>
</div>
</div>

View File

@ -16,7 +16,7 @@
<th>{% translate "FC" %}</th>
{% if perms.auth.optimer_management %}
{# <th>{% translate "Creator" %}</th>#}
<th class="text-right" style="width: 150px;">{% translate "Action" %}</th>
<th class="text-end" style="width: 150px;">{% translate "Action" %}</th>
{% endif %}
</tr>
</thead>
@ -40,7 +40,7 @@
<td>{{ ops.fc }}</td>
{% if perms.auth.optimer_management %}
{# <td>{{ ops.eve_character }}</td>#}
<td class="text-right">
<td class="text-end">
<a href="{% url 'optimer:remove' ops.id %}" class="btn btn-danger">
<span class="glyphicon glyphicon-remove"></span>
</a>

View File

@ -8,7 +8,7 @@
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "Fleet Operation Timers" %}
<div class="text-right">
<div class="text-end">
{% if perms.auth.optimer_management %}
<a href="{% url 'optimer:add' %}" class="btn btn-success">{% translate "Create Operation" %}</a>
{% endif %}
@ -16,10 +16,10 @@
</h1>
<div class="col-lg-12 text-center row">
<div class="label label-info text-left">
<div class="badge badge-info text-start">
<b>{% translate "Current Eve Time:" %} </b>
</div>
<strong class="label label-info text-left" id="current-time"></strong>
<strong class="badge badge-info text-start" id="current-time"></strong>
<br>
</div>

View File

@ -5,10 +5,11 @@ from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import permission_required
from django.shortcuts import get_object_or_404
from django.shortcuts import render, redirect
from django.template.loader import render_to_string
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from .form import OpForm
from .form import OpForm
from .models import OpTimer, OpTimerType
logger = logging.getLogger(__name__)
@ -137,3 +138,15 @@ def edit_optimer(request, optimer_id):
}
form = OpForm(initial=data, data_list=OpTimerType.objects.all())
return render(request, 'optimer/update.html', context={'form': form})
def dashboard_ops(request):
base_query = OpTimer.objects.select_related('eve_character', 'type')
timers = base_query.filter(start__gte=timezone.now())[:5]
if timers.count():
context = {
'timers': timers,
}
return render_to_string('optimer/dashboard.ops.html', context=context, request=request)
else:
return ""

View File

@ -1,7 +1,8 @@
from allianceauth.menu.hooks import MenuItemHook
from . import urls
from allianceauth import hooks
from allianceauth.services.hooks import MenuItemHook, UrlHook
from allianceauth.services.hooks import UrlHook
class PermissionsTool(MenuItemHook):

View File

@ -1,39 +1,39 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}{{ permission.permission.codename }} - {% translate "Permissions Audit" %}{% endblock page_title %}
{% block page_title %}
{{ permission.permission.codename }} - {% translate "Permissions Audit" %}
{% endblock page_title %}
{% block content %}
<div>
<h1 class="page-header">{% translate "Permissions Audit" %}: {{ permission.permission.codename }}</h1>
<p>
<a href="{% url 'permissions_tool:overview' %}" class="btn btn-default">
<i class="glyphicon glyphicon-chevron-left"></i> {% translate "Back" %}
<a href="{% url 'permissions_tool:overview' %}" class="btn btn-primary">
<i class="fa-solid fa-chevron-left"></i> {% translate "Back" %}
</a>
</p>
<div class="table-responsive">
<table class="table table-striped" id="tab_permissions_audit">
<thead>
<tr>
<th>{% translate "Group" %}</th>
<th></th>
<th>{% translate "User / Character" %}</th>
<th>{% translate "Organization" %}</th>
<th scope="col">{% translate "Group" %}</th>
<th scope="col"></th>
<th scope="col">{% translate "User / Character" %}</th>
<th scope="col">{% translate "Organization" %}</th>
</tr>
</thead>
<tbody>
{% for user in permission.users %}
{% include 'permissions_tool/audit_row.html' with type="User" name="Permission granted directlty" %}
{% include "permissions_tool/audit_row.html" with type="User" name="Permission granted directly" %}
{% endfor %}
{% for group in permission.groups %}
{% for user in group.user_set.all %}
{% include 'permissions_tool/audit_row.html' with type="Group" name=group%}
{% include "permissions_tool/audit_row.html" with type="Group" name=group %}
{% endfor %}
{% endfor %}
{% for state in permission.states %}
{% for profile in state.userprofile_set.all %}
{% with profile.user as user %}
{% include 'permissions_tool/audit_row.html' with type="State" name=state%}
{% include "permissions_tool/audit_row.html" with type="State" name=state %}
{% endwith %}
{% endfor %}
{% endfor %}
@ -42,46 +42,48 @@
</div>
</div>
{% endblock content %}
{% block extra_javascript %}
{% include 'bundles/datatables-js.html' %}
{% include 'bundles/filterdropdown-js.html' %}
{% endblock %}
{% include "bundles/datatables-js-bs5.html" %}
{% include "bundles/filterdropdown-js.html" %}
{% endblock extra_javascript %}
{% block extra_css %}
{% include 'bundles/datatables-css.html' %}
{% endblock %}
{% include "bundles/datatables-css-bs5.html" %}
{% endblock extra_css %}
{% block extra_script %}
$(document).ready(function () {
let groupColumn = 0;
$('#tab_permissions_audit').DataTable({
columnDefs: [
{ "visible": false, "targets": groupColumn }
columnDefs: [{
"visible": false,
"targets": groupColumn
}],
order: [
[groupColumn, 'asc'],
[2, 'asc']
],
order: [[ groupColumn, 'asc' ], [ 2, 'asc' ] ],
filterDropDown:
{
columns: [
{
filterDropDown: {
columns: [{
idx: 0,
title: 'Source'
}
],
}],
bootstrap: true
},
"stateSave": true,
"stateDuration": 0,
drawCallback: function (settings) {
let api = this.api();
let rows = api.rows( {page:'current'} ).nodes();
let rows = api.rows({
page: 'current'
}).nodes();
let last = null;
api.column(groupColumn, {page:'current'} ).data().each( function ( group, i ) {
api.column(groupColumn, {
page: 'current'
}).data().each(function (group, i) {
if (last !== group) {
$(rows).eq(i).before(
'<tr class="tr-group"><td colspan="3">' + group + '</td></tr>'
'<tr class="h4 table-secondary"><td colspan="3">' + group + '</td></tr>'
);
last = group;
@ -90,4 +92,4 @@
}
});
});
{% endblock %}
{% endblock extra_script %}

View File

@ -1,25 +1,17 @@
{% load evelinks %}
{% load i18n %}
<tr>
<td>
{{ type }}: {{ name }}
</td>
<td class="text-right">
<img src="{{ user.profile.main_character|character_portrait_url:32 }}" class="img-circle" alt="{{ user.profile.main_character.character_name }}">
</td>
<td>
<strong>{{ user }}<br></strong>
{{ user.profile.main_character.character_name }}
</td>
<td class="text-left">
<td>{{ type }}: {{ name }}</td>
<td class="text-end">
<img src="{{ user.profile.main_character|character_portrait_url:32 }}" class="img-circle" alt="{{ user.profile.main_character.character_name }}"/></td>
<td><strong>{{ user }}<br/></strong>{{ user.profile.main_character.character_name }}</td>
<td class="text-start">
{% if user.profile.main_character %}
<a href="{{ user.profile.main_character|dotlan_corporation_url }}" target="_blank">
{{ user.profile.main_character.corporation_name }}
</a><br>
<a href="{{ user.profile.main_character|dotlan_corporation_url }}" target="_blank">{{ user.profile.main_character.corporation_name }}</a>
<br/>
{{ user.profile.main_character.alliance_name|default_if_none:"" }}
{% else %}
(unknown)
{% translate "(unknown)" %}
{% endif %}
</td>
</tr>

View File

@ -1,73 +1,47 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}{% translate "Permissions Overview" %}{% endblock page_title %}
{% block page_title %}
{% translate "Permissions Overview" %}
{% endblock page_title %}
{% block content %}
<div class="col-sm-12">
<h1 class="page-header">{% translate "Permissions Overview" %}</h1>
<p>
{% if request.GET.all != 'yes' %}
{% blocktranslate %}Showing only applied permissions{% endblocktranslate %}
{% translate "Showing only applied permissions" %}
<a href="{% url 'permissions_tool:overview' %}?all=yes" class="btn btn-primary">{% translate "Show All" %}</a>
{% else %}
{% blocktranslate %}Showing all permissions{% endblocktranslate %}
{% translate "Showing all permissions" %}
<a href="{% url 'permissions_tool:overview' %}?all=no" class="btn btn-primary">{% translate "Show Applied" %}</a>
{% endif %}
</p>
<div class="table-responsive">
<table class="table table-striped" id="tab_permissions_overview" style="width:100%">
<table class="table table-striped" id="tab_permissions_overview">
<thead>
<tr>
<th>
{% translate "App" %}
</th>
<th>
{% translate "Model" %}
</th>
<th>
{% translate "Code Name" %}
</th>
<th>
{% translate "Name" %}
</th>
<th class="col-md-1">
{% translate "Users" %}
</th>
<th class="col-md-1">
{% translate "Groups" %}
</th>
<th class="col-md-1">
{% translate "States" %}
</th>
<th scope="col">{% translate "App" %}</th>
<th scope="col">{% translate "Model" %}</th>
<th scope="col">{% translate "Code Name" %}</th>
<th scope="col">{% translate "Name" %}</th>
<th scope="col">{% translate "Users" %}</th>
<th scope="col">{% translate "Groups" %}</th>
<th scope="col">{% translate "States" %}</th>
</tr>
</thead>
<tbody>
{% for perm in permissions %}
<tr>
<td>
{{ perm.permission.content_type.app_label }}
</td>
<td>
{{ perm.permission.content_type.model }}
</td>
<td>{{ perm.permission.content_type.app_label }}</td>
<td>{{ perm.permission.content_type.model }}</td>
<td>
<a href="{% url "permissions_tool:audit" app_label=perm.permission.content_type.app_label model=perm.permission.content_type.model codename=perm.permission.codename %}">
{{ perm.permission.codename }}
</a>
</td>
<td>
{{ perm.permission.name }}
</td>
<td class="{% if perm.users > 0 %}info {% endif %}text-right">
{{ perm.users }}
</td>
<td class="{% if perm.groups > 0 %}info {% endif %}text-right">
{{ perm.groups }} ({{ perm.group_users }})
</td>
<td class="{% if perm.states > 0 %}info {% endif %}text-right">
{{ perm.states }} ({{ perm.state_users }})
</td>
<td>{{ perm.permission.name }}</td>
<td class="{% if perm.users > 0 %}info{% endif %}text-end">{{ perm.users }}</td>
<td class="{% if perm.groups > 0 %}info{% endif %}text-end">{{ perm.groups }} ({{ perm.group_users }})</td>
<td class="{% if perm.states > 0 %}info{% endif %}text-end">{{ perm.states }} ({{ perm.state_users }})</td>
</tr>
{% endfor %}
</tbody>
@ -75,29 +49,28 @@
</div>
</div>
{% endblock content %}
{% block extra_javascript %}
{% include 'bundles/datatables-js.html' %}
{% include 'bundles/filterdropdown-js.html' %}
{% endblock %}
{% include "bundles/datatables-js-bs5.html" %}
{% include "bundles/filterdropdown-js.html" %}
{% endblock extra_javascript %}
{% block extra_css %}
{% include 'bundles/datatables-css.html' %}
{% endblock %}
{% include "bundles/datatables-css-bs5.html" %}
{% endblock extra_css %}
{% block extra_script %}
$(document).ready(function () {
let groupColumn = 0;
$('#tab_permissions_overview').DataTable({
columnDefs: [
{ "visible": false, "targets": groupColumn }
columnDefs: [{
"visible": false,
"targets": groupColumn
}],
order: [
[groupColumn, 'asc'],
[1, 'asc'],
[2, 'asc']
],
order: [[ groupColumn, 'asc' ], [ 1, 'asc' ], [ 2, 'asc' ] ],
filterDropDown:
{
columns: [
{
filterDropDown: {
columns: [{
idx: 0
},
{
@ -110,19 +83,25 @@
"stateDuration": 0,
drawCallback: function (settings) {
let api = this.api();
let rows = api.rows( {page:'current'} ).nodes();
let rows = api.rows({
page: 'current'
}).nodes();
let last = null;
api.column(groupColumn, {page:'current'} ).data().each( function ( group, i ) {
api.column(groupColumn, {
page: 'current'
}).data().each(function (group, i) {
if (last !== group) {
$(rows).eq(i).before(
'<tr class="tr-group"><td colspan="6">' + group + '</td></tr>'
'
<tr class="h4 table-secondary">
<td colspan="6">' + group + '</td>
</tr>
'
);
last = group;
}
});
}
});
});
{% endblock %}
{% endblock extra_script %}

View File

@ -31,6 +31,11 @@ INSTALLED_APPS = [
'allianceauth.notifications',
'allianceauth.thirdparty.navhelper',
'allianceauth.analytics',
'allianceauth.menu',
'allianceauth.theme',
'allianceauth.theme.darkly',
'allianceauth.theme.flatly',
'allianceauth.theme.materia',
]
SECRET_KEY = "wow I'm a really bad default secret key"
@ -188,6 +193,8 @@ DATABASES = {
SITE_NAME = 'Alliance Auth'
DEFAULT_THEME = "allianceauth.theme.darkly"
LOGIN_URL = 'auth_login_user' # view that handles login logic
LOGIN_REDIRECT_URL = 'authentication:dashboard' # default destination when logging in if no redirect specified

View File

@ -26,7 +26,7 @@ DEBUG = False
# Add any additional apps to this list.
INSTALLED_APPS += [
#'allianceauth.theme.bootstrap',
]
# To change the logging level for extensions, uncomment the following line.

View File

@ -1,7 +1,7 @@
from django.utils.translation import gettext_lazy as _
from allianceauth import hooks
from django.utils.translation import gettext_lazy as _
from .hooks import MenuItemHook
from ..menu.hooks import MenuItemHook
from .hooks import ServicesHook

View File

@ -1,5 +1,5 @@
from django.urls import include, re_path
from string import Formatter
from django.urls import include, re_path
from typing import Iterable, Optional
from django.conf import settings
@ -9,6 +9,11 @@ from django.urls import include, re_path
from django.utils.functional import cached_property
from allianceauth.hooks import get_hooks
from allianceauth.menu.hooks import MenuItemHook
from django.conf import settings
from django.urls import include, re_path
from django.core.exceptions import ObjectDoesNotExist
from django.utils.functional import cached_property
from .models import NameFormatConfig
@ -136,26 +141,15 @@ class ServicesHook:
yield fn()
class MenuItemHook:
def __init__(self, text, classes, url_name, order=None, navactive=list([])):
self.text = text
self.classes = classes
self.url_name = url_name
self.template = 'public/menuitem.html'
self.order = order if order is not None else 9999
class MenuItemHook(MenuItemHook):
"""
MenuItemHook shim to allianceauth.menu.hooks
# count is an integer shown next to the menu item as badge when count != None
# apps need to set the count in their child class, e.g. in render() method
self.count = None
navactive = navactive or []
navactive.append(url_name)
self.navactive = navactive
def render(self, request):
return render_to_string(self.template,
{'item': self},
request=request)
:param MenuItemHook: _description_
:type MenuItemHook: _type_
"""
def __init_subclass__(cls) -> None:
return super().__init_subclass__()
class UrlHook:

View File

@ -1,37 +1,34 @@
{% load i18n %}
<tr>
<td class="text-center">{% translate "Discord" %}</td>
<td class="text-center">
<div class="card text-center m-4" style="min-width: 18rem; min-height: 18rem;">
<div class="card-body ">
<h5 class="card-title ">{% translate "Discord" %}</h5>
<p class="card-text">{% if server_name %}{{ server_name }}{% else %}{% translate "Unlinked Server" %}{% endif %}</p>
<p class="card-text"><span class="badge {% if user_has_account %}bg-success{% else %}bg-warning{% endif %}">{% if user_has_account %}{% translate "Active" %}{% else %}{% translate "Disabled" %}{% endif %}</span></p>
<p class="card-text">
{% if not user_has_account %}
(not activated)
{% translate "(not activated)" %}
{% else %}
{{ discord_username }}
{% endif %}
</td>
<td class="text-center">
{{server_name}}
</td>
<td class="text-center">
</p>
</div>
<div class="card-footer">
{% if not user_has_account %}
<a href="{% url 'discord:activate' %}" title="{% translate 'Join the Discord server' %}" class="btn btn-primary">
<span class="glyphicon glyphicon-ok"></span>
<span class="fas fa-check fa-fw"></span>
</a>
{% else %}
<a href="{% url 'discord:reset' %}" title="{% translate 'Leave- and rejoin the Discord Server (Reset)' %}" class="btn btn-warning">
<span class="glyphicon glyphicon-refresh"></span>
<span class="fas fa-sync fa-fw"></span>
</a>
<a href="{% url 'discord:deactivate' %}" title="{% translate 'Leave the Discord server' %}" class="btn btn-danger">
<span class="glyphicon glyphicon-remove"></span>
<span class="fas fa-times fa-fw"></span>
</a>
{% endif %}
{% if request.user.is_superuser %}
<div class="text-center" style="padding-top:5px;">
<a type="button" id="btnLinkDiscordServer" class="btn btn-default" href="{% url 'discord:add_bot' %}">
{% translate "Link Discord Server" %}
<a type="button" id="btnLinkDiscordServer" class="btn btn-primary" href="{% url 'discord:add_bot' %}">
<span class="fas fa-link fa-fw"></span>
</a>
</div>
{% endif %}
</td>
</tr>
</div>
</div>

View File

@ -1,10 +1,20 @@
{% extends "services/services_ctrl_base.html" %}
{% load i18n %}
<tr>
<td class="text-center">Discourse</td>
<td class="text-center">{{ char.character_name }}</td>
<td class="text-center"><a href="{{ DISCOURSE_URL }}">{{ DISCOURSE_URL }}</a></td>
<td class="text-center">
<a title="Go To Forums" class="btn btn-success" href="{{ DISCOURSE_URL }}"><span class="glyphicon glyphicon-arrow-right"></span></a>
</td>
</tr>
{% block title %}
{% translate "Discourse" %}
{% endblock %}
{% block url %}
<a href="{{ DISCOURSE_URL }}">{{ DISCOURSE_URL }}</a>
{% endblock %}
{% block user %}
Username: {{ char.character_name }}
{% endblock %}
{% block controls %}
<a title="Go To Forums" href="{{ DISCOURSE_URL }}" class="btn btn-success" title="Connect">
<span class="fas fa-arrow-right fa-fw"></span>
</a>
{% endblock %}

View File

@ -1,28 +1,34 @@
<tr>
<td class="text-center">{{ service_name }}</td>
<td class="text-center">{{ username }}</td>
{% load i18n %}
<div class="card text-center m-4" style="min-width: 18rem; min-height: 18rem;">
<div class="card-body ">
<h5 class="card-title ">{{ service_name }}</h5>
<p class="card-text"><a href="mumble://{{ service_url }}">{{ service_url }}</a></p>
<p class="card-text"><span class="badge {% if username != '' %}bg-success{% else %}bg-warning{% endif %}">{% if username != '' %}Active{% else %}Disabled{% endif %}</span></p>
<p class="card-text">Username: <span class="badge bg-secondary text-end">{{ username }}</span></p>
</div>
<div class="card-footer">
{% if username == "" %}
<td class="text-center">{{ service_url }}</td>
<td class="text-center">
<a href="{% url 'mumble:activate' %}" title="Activate" class="btn btn-warning">
<span class="glyphicon glyphicon-ok"></span>
<span class="fas fa-check fa-fw"></span>
</a>
</td>
{% else %}
<td class="text-center"><a href="mumble://{{ connect_url }}">{{ service_url }}</a></td>
<td class="text-center">
<a href="{% url 'mumble:set_password' %}" title="Set Password" class="btn btn-warning">
<span class="glyphicon glyphicon-pencil"></span>
<span class="fas fa-edit fa-fw"></span>
</a>
<a href="{% url 'mumble:reset_password' %}" title="Reset Password" class="btn btn-primary">
<span class="glyphicon glyphicon-refresh"></span>
<span class="fas fa-sync fa-fw"></span>
</a>
<a href="{% url 'mumble:deactivate' %}" title="Deactivate" class="btn btn-danger">
<span class="glyphicon glyphicon-remove"></span>
<span class="fas fa-times fa-fw"></span>
</a>
<a href="mumble://{{ connect_url }}" class="btn btn-success" title="Connect">
<span class="glyphicon glyphicon-arrow-right"></span>
<span class="fas fa-arrow-right fa-fw"></span>
</a>
</td>
{% endif %}
</tr>
</div>
</div>

View File

@ -5,7 +5,8 @@ from django.template.loader import render_to_string
from django.utils.translation import gettext_lazy as _
from allianceauth import hooks
from allianceauth.services.hooks import ServicesHook, MenuItemHook
from allianceauth.menu.hooks import MenuItemHook
from allianceauth.services.hooks import ServicesHook
from .tasks import OpenfireTasks
from .urls import urlpatterns

View File

@ -1,27 +1,39 @@
{% extends "services/services_ctrl_base.html" %}
{% load i18n %}
<tr>
<td class="text-center">Teamspeak 3</td>
<td class="text-center">{{ authinfo.teamspeak3_uid }}</td>
<td class="text-center"><a href="ts3server://{{ TEAMSPEAK3_PUBLIC_URL }}">{{ TEAMSPEAK3_PUBLIC_URL }}</a></td>
<td class="text-center">
{% block title %}
{% translate "Teamspeak 3" %}
{% endblock %}
{% block url %}
<a href="ts3server://{{ TEAMSPEAK3_PUBLIC_URL }}">{{ TEAMSPEAK3_PUBLIC_URL }}</a>
{% endblock %}
{% block active %}
<span class="badge {% if authinfo.teamspeak3_uid != '' %}bg-success{% else %}bg-warning{% endif %}">{% if authinfo.teamspeak3_uid != '' %}Active{% else %}Disabled{% endif %}</span>
{% endblock %}
{% block user %}
{{ authinfo.teamspeak3_uid }}
{% endblock %}
{% block controls %}
{% if authinfo.teamspeak3_uid == "" %}
<a href="{% url 'teamspeak3:activate' %}" title="Activate" class="btn btn-warning">
<span class="glyphicon glyphicon-ok"></span>
<span class="fas fa-check fa-fw"></span>
</a>
{% else %}
<a href="{% url 'teamspeak3:verify' %}" title="Verify Client ID" class="btn btn-success">
<span class="glyphicon glyphicon-log-in"></span>
<span class="far fa-sign-in fa-fw"></span>
</a>
<a href="{% url 'teamspeak3:reset_perm' %}" title="Refresh Token" class="btn btn-primary">
<span class="glyphicon glyphicon-refresh"></span>
<span class="fas fa-sync fa-fw"></span>
</a>
<a href="{% url 'teamspeak3:deactivate' %}" title="Deactivate" class="btn btn-danger">
<span class="glyphicon glyphicon-remove"></span>
<span class="fas fa-times fa-fw"></span>
</a>
<a href="ts3server://{{ TEAMSPEAK3_PUBLIC_URL }}?nickname={{ authinfo.teamspeak3_uid }}" title="Connect" class="btn btn-success">
<span class="glyphicon glyphicon-arrow-right"></span>
<span class="fas fa-arrow-right fa-fw"></span>
</a>
{% endif %}
</td>
</tr>
{% endblock %}

View File

@ -1,4 +1,4 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load bootstrap %}
{% load i18n %}

View File

@ -1,29 +1,48 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}{% translate "Services Management" %}{% endblock page_title %}
{% block extra_css %}{% endblock extra_css %}
{% block header_nav_brand %}{% translate "Available Services" %}{% endblock header_nav_brand %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "Available Services" %}</h1>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th class="text-center">{% translate "Service" %}</th>
<th class="text-center">{% translate "Username" %}</th>
<th class="text-center">{% translate "Domain" %}</th>
<th class="text-center">{% translate "Action" %}</th>
</tr>
</thead>
<tbody>
<div class="d-flex p-2 bd-highlight justify-content-center flex-wrap">
{% for svc in service_ctrls %}
{{ svc }}
{% endfor %}
</tbody>
</table>
</div>
<div class="w-100 text-center">
<h4>Legend</h4>
<div class="d-inline-flex bd-highlight justify-content-center flex-wrap">
<div class="d-inline-flex m-3">
<a title="Activate" class="btn btn-warning">
<span class="fas fa-check fa-fw"></span>
</a>
<p class="m-2 p-0 align-self-center">{% translate "Click to activate the service for your user." %}</p>
</div>
<div class="d-inline-flex m-3">
<a title="Set Password" class="btn btn-warning">
<span class="fas fa-edit fa-fw"></span>
</a>
<p class="m-2 p-0 align-self-center">{% translate "Click to manually set your password." %}</p>
</div>
<div class="d-inline-flex m-3">
<a title="Reset Password" class="btn btn-primary">
<span class="fas fa-sync fa-fw"></span>
</a>
<p class="m-2 p-0 align-self-center">{% translate "Click to randomly generate your password." %}</p>
</div>
<div class="d-inline-flex m-3">
<a title="Deactivate" class="btn btn-danger">
<span class="fas fa-times fa-fw"></span>
</a>
<p class="m-2 p-0 align-self-center">{% translate "Click to deactivate the service for your user" %}</p>
</div>
</div>
<p class="m-2 p-0 align-self-center">{% translate "Some services provide different options. Hover over the buttons to see more." %}</p>
</div>
{% endblock content %}

View File

@ -1,32 +1,44 @@
{% extends "services/services_ctrl_base.html" %}
{% load i18n %}
<tr>
<td class="text-center">{{ service_name }}</td>
<td class="text-center">{{ username }}</td>
<td class="text-center"><a href="{{ service_url }}">{{ service_url }}</a></td>
<td class="text-center">
{% block title %}
{{ service_name }}
{% endblock %}
{% block url %}
<a href="{{ service_url }}">{{ service_url }}</a>
{% endblock %}
{% block active %}
<span class="badge {% if username != '' %}bg-success{% else %}bg-warning{% endif %}">{% if username != '' %}Active{% else %}Disabled{% endif %}</span>
{% endblock %}
{% block user %}
Username: <span class="badge bg-secondary">{{ username }}</span>
{% endblock %}
{% block controls %}
{% if username == "" %}
{% if urls.auth_activate %}
<a href="{% url urls.auth_activate %}" title="Activate" class="btn btn-warning">
<span class="glyphicon glyphicon-ok"></span>
<span class="fas fa-check fa-fw"></span>
</a>
{% endif %}
{% else %}
{% if urls.auth_set_password %}
<a href="{% url urls.auth_set_password %}" title="Set Password" class="btn btn-warning">
<span class="glyphicon glyphicon-pencil"></span>
<span class="fas fa-edit fa-fw"></span>
</a>
{% endif %}
{% if urls.auth_reset_password %}
<a href="{% url urls.auth_reset_password %}" title="Reset Password" class="btn btn-primary">
<span class="glyphicon glyphicon-refresh"></span>
<span class="fas fa-sync fa-fw"></span>
</a>
{% endif %}
{% if urls.auth_deactivate %}
<a href="{% url urls.auth_deactivate %}" title="Deactivate" class="btn btn-danger">
<span class="glyphicon glyphicon-remove"></span>
<span class="fas fa-times fa-fw"></span>
</a>
{% endif %}
{% endif %}
</td>
</tr>
{% endblock %}

View File

@ -0,0 +1,15 @@
{% load i18n %}
<div class="card text-center m-4" style="min-width: 18rem; min-height: 18rem">
<div class="card-body">
<h5 class="card-title">{% block title %}{% endblock title %}</h5>
<p class="card-text">{% block url %}{% endblock url %}</p>
<p class="card-text">
{% block active %}
<span class="badge bg-success">Active</span>
{% endblock active %}
</p>
<p class="card-text">{% block user %}{% endblock user %}</p>
{% block extra %}{% endblock extra %}
</div>
<div class="card-footer">{% block controls %}{% endblock controls %}</div>
</div>

View File

@ -1,7 +1,8 @@
from django.utils.translation import gettext_lazy as _
from allianceauth import hooks
from allianceauth.services.hooks import MenuItemHook, UrlHook
from allianceauth.menu.hooks import MenuItemHook
from allianceauth.services.hooks import UrlHook
from . import urls
from .managers import SRPManager

View File

@ -1,54 +1,13 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% load humanize %}
{% block page_title %}{% translate "Srp Fleet Data" %}{% endblock page_title %}
{% block extra_css %}
{% include 'bundles/datatables-css.html' %}
{% include 'bundles/x-editable.css.html' %}
{% include 'bundles/checkbox-css.html' %}
<style>
.copy-text-fa-icon:hover {
cursor: pointer;
}
.radio label, .checkbox label {
padding-left: 10px;
}
.editable {
width:150px;
text-align: center;
}
.editableform .form-control {
width: 95%;
text-align: center;
margin-left: 10px;
}
.editable-input {
width: 95%;
}
.radio, .checkbox {
margin-top: 0;
margin-bottom: 0;
}
.editable-error-block {
white-space: nowrap;
}
.editable-click, a.editable-click, a.editable-click:hover {
border-bottom: none;
}
.tooltip-inner {
white-space:pre;
max-width: none;
}
</style>
{% endblock extra_css %}
{% block content %}
<div class="col-lg-12">
<div class="row">
<h1 class="page-header text-center">{% translate "SRP Fleet Data" %}
<div class="text-right">
<div class="text-end">
{% if perms.auth.srp_management %}
{% if fleet_status == "Completed" %}
<a href="{% url 'srp:mark_uncompleted' fleet_id %}" class="btn btn-warning">
@ -67,7 +26,7 @@
<form method="POST">
{% csrf_token %}
<div class="alert alert-info" role="alert">
<div class="text-right">
<div class="text-end">
<b><span style="padding-right:2.5em">{% translate "Total Losses:" %} {{ srpfleetrequests.count }}</span></b>
<b><span style="padding-right:2.5em">{% translate "Total ISK Cost:" %} {{ totalcost | intcomma }}</span></b>
{% if perms.auth.srp_management %}
@ -114,7 +73,7 @@ ESC to cancel{% endblocktranslate %}" id="blah"></i></th>
</td>
<td class="text-center">
<a href="{{ srpfleetrequest.killboard_link }}"
target="_blank" class="label label-warning">Link</a>
target="_blank" class="badge badge-warning">{% translate "Link" %}</a>
</td>
<td class="text-center">{{ srpfleetrequest.additional_info }}</td>
<td class="text-center">{{ srpfleetrequest.srp_ship_name }}</td>
@ -123,15 +82,15 @@ ESC to cancel{% endblocktranslate %}" id="blah"></i></th>
<td class="text-center" data-sort="{{ srpfleetrequest.post_time | date:"Y-m-d H:i" }}">{{ srpfleetrequest.post_time | date:"Y-M-d H:i" }}</td>
<td class="text-center">
{% if srpfleetrequest.srp_status == "Approved" %}
<div class="label label-success">
<div class="badge badge-success">
{% translate "Approved" %}
</div>
{% elif srpfleetrequest.srp_status == "Rejected" %}
<div class="label label-danger">
<div class="badge badge-danger">
{% translate "Rejected" %}
</div>
{% else %}
<div class="label label-warning">
<div class="badge badge-warning">
{% translate "Pending" %}
</div>
{% endif %}
@ -148,12 +107,12 @@ ESC to cancel{% endblocktranslate %}" id="blah"></i></th>
{% endif %}
</tr>
{% endfor %}
<tbody>
</tbody>
</table>
</div>
<div class="alert alert-info" role="alert">
<div class="text-right">
<div class="text-end">
<b><span style="padding-right:2.5em">{% translate "Total Losses:" %} {{ srpfleetrequests.count }}</span></b>
<b><span style="padding-right:2.5em">{% translate "Total ISK Cost:" %} {{ totalcost | intcomma }}</span></b>
{% if perms.auth.srp_management %}
@ -180,10 +139,10 @@ ESC to cancel{% endblocktranslate %}" id="blah"></i></th>
{% endblock content %}
{% block extra_javascript %}
{% include 'bundles/datatables-js.html' %}
{% include 'bundles/x-editable-js.html' %}
{% include 'bundles/moment-js.html' %}
{% include 'bundles/clipboard-js.html' %}
{% include "bundles/datatables-js-bs5.html" %}
{% include "bundles/x-editable-js.html" %}
{% include "bundles/moment-js.html" %}
{% include "bundles/clipboard-js.html" %}
<script>
const clipboard = new ClipboardJS('.copy-text-fa-icon');
@ -273,3 +232,44 @@ ESC to cancel{% endblocktranslate %}" id="blah"></i></th>
$("[rel=tooltip]").tooltip({ placement: 'top'});
});
{% endblock extra_script %}
{% block extra_css %}
{% include "bundles/datatables-css-bs5.html" %}
{% include "bundles/x-editable.css.html" %}
{% include "bundles/checkbox-css.html" %}
<style>
.copy-text-fa-icon:hover {
cursor: pointer;
}
.radio label, .checkbox label {
padding-left: 10px;
}
.editable {
width:150px;
text-align: center;
}
.editableform .form-control {
width: 95%;
text-align: center;
margin-left: 10px;
}
.editable-input {
width: 95%;
}
.radio, .checkbox {
margin-top: 0;
margin-bottom: 0;
}
.editable-error-block {
white-space: nowrap;
}
.editable-click, a.editable-click, a.editable-click:hover {
border-bottom: none;
}
.tooltip-inner {
white-space:pre;
max-width: none;
}
</style>
{% endblock extra_css %}

View File

@ -1,4 +1,4 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% load humanize %}
@ -10,7 +10,7 @@
<div class="col-lg-12">
<div class="row">
<h1 class="page-header text-center">{% translate "SRP Management" %}
<div class="text-right">
<div class="text-end">
{% if perms.auth.srp_management %}
<a href="{% url 'srp:all' %}" class="btn btn-primary">
{% translate "View All" %}
@ -24,7 +24,7 @@
</div>
</h1>
<div class="alert alert-info" role="alert">
<div class="text-right">
<div class="text-end">
<b>{% translate "Total ISK Cost:" %} {{ totalcost | intcomma }}</b>
</div>
</div>
@ -46,27 +46,27 @@
{% for srpfleet in srpfleets %}
<tr>
<td class="text-center">
<div class="label label-info">
<div class="badge badge-info">
{{ srpfleet.fleet_name }}
</div>
</td>
<td class="text-center">{{ srpfleet.fleet_time | date:"Y-m-d H:i" }}</td>
<td class="text-center">{{ srpfleet.fleet_doctrine }}</td>
<td class="text-center">
<div class="label label-success">
<div class="badge badge-success">
{{ srpfleet.fleet_commander.character_name }}
</div>
</td>
<td class="text-center">
{% if srpfleet.fleet_srp_aar_link %}
<a href="{{ srpfleet.fleet_srp_aar_link }}" target="_blank" class="label label-primary">{% translate 'Link' %}</a>
<a href="{{ srpfleet.fleet_srp_aar_link }}" target="_blank" class="badge badge-primary">{% translate "Link" %}</a>
{% endif %}
</td>
<td class="text-center">
{% if srpfleet.fleet_srp_code %}
<a class="label label-warning" href="{% url 'srp:request' srpfleet.fleet_srp_code %}">{{ srpfleet.fleet_srp_code }}</a>
<a class="badge badge-warning" href="{% url 'srp:request' srpfleet.fleet_srp_code %}">{{ srpfleet.fleet_srp_code }}</a>
{% else %}
<div class="label label-danger">
<div class="badge badge-danger">
{% translate "Disabled" %}
</div>
{% endif %}
@ -75,17 +75,17 @@
<td class="text-center">
{% if srpfleet.fleet_srp_status == "" %}
<div class="label label-warning">
<div class="badge badge-warning">
{% translate "Pending" %}
</div>
{% else %}
<div class="label label-success">
<div class="badge badge-success">
{% translate "Completed" %}
</div>
{% endif %}
</td>
<td class="text-center">
<div class="label label-warning">{{ srpfleet.pending_requests }}</div>
<div class="badge badge-warning">{{ srpfleet.pending_requests }}</div>
</td>
<td class="text-center">

View File

@ -1,4 +1,4 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load bootstrap %}
{% load i18n %}

View File

@ -1,4 +1,4 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load bootstrap %}
{% load i18n %}
@ -26,7 +26,6 @@
</div>
</div>
</div>
</div>
{% endblock content %}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg122"
width="256"
height="256"
viewBox="0 0 255.99999 256"
sodipodi:docname="allianceauth (2).svg"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs126" />
<sodipodi:namedview
id="namedview124"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
showgrid="false"
inkscape:zoom="3.8506576"
inkscape:cx="30.514269"
inkscape:cy="102.57988"
inkscape:window-width="2560"
inkscape:window-height="1369"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="g128" />
<g
inkscape:groupmode="layer"
inkscape:label="Image"
id="g128">
<g
id="g2338"
transform="translate(41.953499,36.607802)">
<path
style="display:inline;fill:#e14852;stroke-width:0.32"
d="M 131.07236,159.67687 C 109.26615,147.02458 91.302022,136.55002 91.152067,136.40007 l -0.272649,-0.27265 23.786292,-13.82371 c 13.08247,-7.60304 23.9186,-13.82025 24.08029,-13.81602 l 0.294,0.008 15.93273,36.83413 c 8.763,20.25877 15.891,36.95054 15.84,37.09283 l -0.0927,0.25869 z"
id="path2342"
sodipodi:nodetypes="cscsccsscc" />
<path
style="display:inline;fill:#436195;stroke-width:0.32"
d="m 1.28,182.46369 c 0,-0.16969 17.354495,-40.46543 38.565546,-89.546103 L 78.411088,3.68 C 79.919052,1.4903841 82.294641,0.02199886 86.08,0.01224344 89.865359,0.00248802 92.288,1.4677954 93.674477,3.5158445 l 21.668143,50.1206965 21.66814,50.120699 -0.26538,0.23285 C 136.59942,104.11816 106.528,121.61441 69.92,142.87065 33.312,164.12688 2.892,181.80046 2.32,182.14527 l -1.04,0.62693 z"
id="path2340"
sodipodi:nodetypes="ssczcccssscs" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

File diff suppressed because one or more lines are too long

View File

@ -1,36 +1,41 @@
{% load i18n %}
{% load humanize %}
<div class="col-sm-12">
<div class="row vertical-flexbox-row2">
<div class="col-sm-6">
<div class="panel panel-primary" style="height:100%;position:relative;">
<div class="panel-heading text-center"><h3 class="panel-title">{% translate "Alliance Auth Notifications" %}</h3></div>
<div class="panel-body">
{% if notifications %}
<div class="col-12 align-self-stretch p-2">
<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">
{% translate "Alliance Auth Notifications" %}
</h4>
<div class="card-body">
<ul class="list-group">
{% for notif in notifications %}
<li class="list-group-item">
{% if notif.state == 'opened' %}
<span class="label label-success">{% translate "Open" %}</span>
<span class="badge badge-success">{% translate "Open" %}</span>
{% else %}
<span class="label label-danger">{% translate "Closed" %}</span>
<span class="badge badge-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>
<div class="text-right" style="position: absolute; bottom: 5px; right: 5px;">
<div class="text-end" style="position: absolute; bottom: 5px; right: 5px;">
<a href="https://gitlab.com/allianceauth/allianceauth/issues" target="_blank" style="margin-right: 0.5rem;">
<span class="label" style="background-color: #e65328;">
<span class="badge" style="background-color: #e65328;">
<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="label" style="background-color: rgb(110,133,211);">
<span class="badge" style="background-color: rgb(110,133,211);">
<i class="fab fa-discord" aria-hidden="true"></i>
{% translate 'Support Discord' %}
</span>
@ -38,45 +43,54 @@
</div>
</div>
</div>
<div class="col-sm-6">
<div class="panel panel-primary" style="height:50%;">
<div class="panel-heading text-center"><h3 class="panel-title">{% translate "Software Version" %}</h3></div>
<div class="panel-body flex-center-horizontal">
<ul class="list-group list-group-horizontal" style="margin-bottom: 0;">
<li class="list-group-item">
</div>
</div>
</div>
{% endif %}
<div class="col-12 align-self-stretch p-2">
<div class="card">
<div class="card-body d-flex flex-row flex-wrap">
<div 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>
<div class="card-body pb-0">
<ul class="list-group list-group-horizontal w-100" role="group" aria-label="Basic example">
<li type="button" class="list-group-item w-100">
<h5 class="list-group-item-heading">{% translate "Current" %}</h5>
<p class="list-group-item-text">
{{ current_version }}
</p>
</li>
<li class="list-group-item list-group-item-{% if latest_patch %}success{% elif latest_minor %}warning{% else %}danger{% endif %}">
<li class="list-group-item list-group-item-{% if latest_patch %}success{% elif latest_minor %}warning{% else %}danger{% endif %} w-100" href="https://gitlab.com/allianceauth/allianceauth/-/tags/v{{ latest_patch_version }}">
<h5 class="list-group-item-heading">{% translate "Latest Stable" %}</h5>
<p class="list-group-item-text">
<a href="https://gitlab.com/allianceauth/allianceauth/-/tags/v{{ latest_patch_version }}" style="color:#000;">
<i class="fab fa-gitlab hidden-xs" aria-hidden="true"></i>
{{ latest_patch_version }}
</a>
{% if not latest_patch %}<br>{% translate "Update available" %}{% endif %}
</p>
</li>
{% if latest_beta %}
<li class="list-group-item list-group-item-info">
<li>
<a type="button" class="btn btn-info w-100" href="https://gitlab.com/allianceauth/allianceauth/-/tags/v{{ latest_beta_version }}">
<h5 class="list-group-item-heading">{% translate "Latest Pre-Release" %}</h5>
<p class="list-group-item-text">
<a href="https://gitlab.com/allianceauth/allianceauth/-/tags/v{{ latest_beta_version }}" style="color:#000;">
<i class="fab fa-gitlab hidden-xs" aria-hidden="true"></i>
{{ latest_beta_version }}
</a>
<br>{% translate "Pre-Release available" %}
</p>
</a>
</li>
{% endif %}
</ul>
</div>
</div>
<div class="panel panel-primary" style="height:50%;">
<div class="panel-heading text-center"><h3 class="panel-title">{% translate "Task Queue" %}</h3></div>
<div class="panel-body flex-center-horizontal">
<div class="d-xl-none d-lg-show d-md-show d-sm-show m-2"></div>
<div 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>
<div class="card-body pb-0">
<p>
{% blocktranslate with total=tasks_total|intcomma latest=earliest_task|timesince|default:"?" %}
Status of {{ total }} processed tasks • last {{ latest }}
@ -99,7 +113,6 @@
</div>
</div>
</div>
<div class="clearfix"></div>
</div>
<script>

View File

@ -0,0 +1,123 @@
{% load static %}
{% load i18n %}
{% load navactive %}
{% load auth_notifications %}
{% load theme_tags %}
<!DOCTYPE html>
<html lang="en" {% theme_html_tags %}>
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- End Required meta tags -->
<!-- Meta tags -->
<!-- TODO Bundle all the site specific stuff up into its own template for easy overide -->
<meta name="description" content="">
<meta name="author" content="">
{% include 'allianceauth/icons.html' %}
<!-- Meta tags -->
<title>{% block title %}{% block page_title %}{% endblock page_title %} - {{ SITE_NAME }}{% endblock title %}</title>
{% theme_css %}
{% include 'bundles/fontawesome.html' %}
<style>
.navbar-toggler.collapsed{
transform: rotate(180deg);
}
.nav-padding {
padding-top: {% header_padding_size %} !important;
}
.auth-logo {
background-position: bottom;
background-repeat: no-repeat;
background-image: url("{% static 'allianceauth/images/auth-logo.png' %}") ;
}
</style>
{% block extra_css %}{% endblock extra_css %}
</head>
<body class="overflow-none">
{% 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">
<a class="navbar-brand" data-bs-toggle="collapse" data-bs-target="#sidebar" role="button">
<i class="fas fa-solid fa-bars ms-2 me-2"></i>
</a>
<a class="navbar-brand">{% block header_nav_brand %}{{ SITE_NAME }}{% endblock %}</a>
<div class="collapse navbar-collapse" id="navbarexpand">
<div class="m-2"></div>
<ul id="nav-left" class="navbar-nav nav me-auto">
{% block header_nav_collapse_left %}
{% endblock %}
</ul>
<ul id="nav-right" class="navbar-nav">
{% block header_nav_collapse_right %} <!-- 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="fas fa-solid fa-chevron-up"></i>
</a>
</div>
</nav>
<!-- End Top Menu -->
<!-- Body -->
<main class="row flex-nowrap m-0">
{% include 'menu/sortable-side-menu.html' %}
<div class="nav-padding col flex-nowrap px-0 m-0 vh-100 overflow-auto">
<div class="p-2">
{% include 'allianceauth/messages-bs5.html' %}
{% block content %}
{% endblock content %}
</div>
</div>
</main>
<!-- End Body -->
{% endif %}
<script>
(function () {
// TODO Extend this to the groups in the sidebar too.
// TODO Move to own JS file
var sidebar = document.getElementById('sidebar')
sidebar.addEventListener("shown.bs.collapse", function () {
localStorage.removeItem("sidebar_" + sidebar.id);
});
sidebar.addEventListener("hidden.bs.collapse", function () {
localStorage.setItem("sidebar_" + sidebar.id, true);
});
if (localStorage.getItem("sidebar_" + sidebar.id) === "true") {
sidebar.classList.remove("show")
}
else {
sidebar.classList.add("show")
}
})();
</script>
{% include 'bundles/jquery-js.html' %}
{% theme_js %}
<script type="application/javascript">
let notificationUPdateSettings = {
notificationsListViewUrl: "{% url 'notifications:list' %}",
notificationsRefreshTime: "{% notifications_refresh_time %}",
userNotificationsCountViewUrl: "{% url 'notifications:user_notifications_count' request.user.pk %}"
};
</script>
{% block extra_javascript %}
{% endblock extra_javascript %}
<script>
{% block extra_script %}
{% endblock extra_script %}
</script>
</body>
</html>

View File

@ -0,0 +1,27 @@
{% extends "allianceauth/base-bs5.html" %}
{% block page_title %}
{{ error_title }}
{% endblock page_title %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{{ error_title }}</h1>
<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"></p>>{{ error_message }}</p>
</div>
{% endblock content %}

Some files were not shown because too many files have changed in this diff Show More