Improve image tags to also work with eveonline objects, use new tags in group managenet, optimer, timerboard

This commit is contained in:
Erik Kalkoken 2020-02-05 04:31:13 +00:00 committed by colcrunch
parent 337c4d9ce5
commit fcb66a11a3
18 changed files with 1227 additions and 151 deletions

View File

@ -0,0 +1,17 @@
# this package generates profile URL for eve entities
# on 3rd party websites like evewho and zKillboard
#
# It contains of modules for views and templatetags for templates
# list of all eve entity categories as defined in ESI
ESI_CATEGORY_AGENT = "agent"
ESI_CATEGORY_ALLIANCE = "alliance"
ESI_CATEGORY_CHARACTER = "character"
ESI_CATEGORY_CONSTELLATION = "constellation"
ESI_CATEGORY_CORPORATION = "corporation"
ESI_CATEGORY_FACTION = "faction"
ESI_CATEGORY_INVENTORYTYPE = "inventory_type"
ESI_CATEGORY_REGION = "region"
ESI_CATEGORY_SOLARSYSTEM = "solar_system"
ESI_CATEGORY_STATION = "station"
ESI_CATEGORY_WORMHOLE = "wormhole"

View File

@ -0,0 +1,52 @@
# this module generates profile URLs for dotlan
from urllib.parse import urljoin, quote
from . import *
BASE_URL = 'http://evemaps.dotlan.net'
def _build_url(category: str, name: str) -> str:
"""return url to profile page for an eve entity"""
if category == ESI_CATEGORY_ALLIANCE:
partial = 'alliance'
elif category == ESI_CATEGORY_CORPORATION:
partial = 'corp'
elif category == ESI_CATEGORY_REGION:
partial = 'map'
elif category == ESI_CATEGORY_SOLARSYSTEM:
partial = 'system'
else:
raise NotImplementedError(
"Not implemented yet for category:" + category
)
url = urljoin(
BASE_URL,
'{}/{}'.format(partial, quote(str(name).replace(" ", "_")))
)
return url
def alliance_url(name: str) -> str:
"""url for page about given alliance on dotlan"""
return _build_url(ESI_CATEGORY_ALLIANCE, name)
def corporation_url(name: str) -> str:
"""url for page about given corporation on dotlan"""
return _build_url(ESI_CATEGORY_CORPORATION, name)
def region_url(name: str) -> str:
"""url for page about given region on dotlan"""
return _build_url(ESI_CATEGORY_REGION, name)
def solar_system_url(name: str) -> str:
"""url for page about given solar system on dotlan"""
return _build_url(ESI_CATEGORY_SOLARSYSTEM, name)

View File

@ -0,0 +1,44 @@
# this module generates profile URLs for evewho
from urllib.parse import urljoin, quote
from . import *
BASE_URL = 'https://evewho.com'
def _build_url(category: str, eve_id: int) -> str:
"""return url to profile page for an eve entity"""
if category == ESI_CATEGORY_ALLIANCE:
partial = 'alliance'
elif category == ESI_CATEGORY_CORPORATION:
partial = 'corporation'
elif category == ESI_CATEGORY_CHARACTER:
partial = 'character'
else:
raise NotImplementedError(
"Not implemented yet for category:" + category
)
url = urljoin(
BASE_URL,
'{}/{}'.format(partial, int(eve_id))
)
return url
def alliance_url(eve_id: int) -> str:
"""url for page about given alliance on evewho"""
return _build_url(ESI_CATEGORY_ALLIANCE, eve_id)
def character_url(eve_id: int) -> str:
"""url for page about given character on evewho"""
return _build_url(ESI_CATEGORY_CHARACTER, eve_id)
def corporation_url(eve_id: int) -> str:
"""url for page about given corporation on evewho"""
return _build_url(ESI_CATEGORY_CORPORATION, eve_id)

View File

@ -0,0 +1,92 @@
from django.test import TestCase
from ...models import EveCharacter, EveCorporationInfo, EveAllianceInfo
from .. import dotlan, zkillboard, evewho
from ...templatetags import evelinks
class TestEveWho(TestCase):
def test_alliance_url(self):
self.assertEqual(
evewho.alliance_url(12345678),
'https://evewho.com/alliance/12345678'
)
def test_corporation_url(self):
self.assertEqual(
evewho.corporation_url(12345678),
'https://evewho.com/corporation/12345678'
)
def test_character_url(self):
self.assertEqual(
evewho.character_url(12345678),
'https://evewho.com/character/12345678'
)
class TestDotlan(TestCase):
def test_alliance_url(self):
self.assertEqual(
dotlan.alliance_url('Wayne Enterprices'),
'http://evemaps.dotlan.net/alliance/Wayne_Enterprices'
)
def test_corporation_url(self):
self.assertEqual(
dotlan.corporation_url('Wayne Technology'),
'http://evemaps.dotlan.net/corp/Wayne_Technology'
)
self.assertEqual(
dotlan.corporation_url('Crédit Agricole'),
'http://evemaps.dotlan.net/corp/Cr%C3%A9dit_Agricole'
)
def test_region_url(self):
self.assertEqual(
dotlan.region_url('Black Rise'),
'http://evemaps.dotlan.net/map/Black_Rise'
)
def test_solar_system_url(self):
self.assertEqual(
dotlan.solar_system_url('Jita'),
'http://evemaps.dotlan.net/system/Jita'
)
class TestZkillboard(TestCase):
def test_alliance_url(self):
self.assertEqual(
zkillboard.alliance_url(12345678),
'https://zkillboard.com/alliance/12345678/'
)
def test_corporation_url(self):
self.assertEqual(
zkillboard.corporation_url(12345678),
'https://zkillboard.com/corporation/12345678/'
)
def test_character_url(self):
self.assertEqual(
zkillboard.character_url(12345678),
'https://zkillboard.com/character/12345678/'
)
def test_region_url(self):
self.assertEqual(
zkillboard.region_url(12345678),
'https://zkillboard.com/region/12345678/'
)
def test_solar_system_url(self):
self.assertEqual(
zkillboard.solar_system_url(12345678),
'https://zkillboard.com/system/12345678/'
)

View File

@ -0,0 +1,334 @@
from django.test import TestCase
from ...models import EveCharacter, EveCorporationInfo, EveAllianceInfo
from .. import dotlan, zkillboard, evewho
from ...templatetags import evelinks
class TestTemplateTags(TestCase):
def setUp(self):
self.my_character = EveCharacter.objects.create(
character_id=1001,
character_name='Bruce Wayne',
corporation_id=2001,
corporation_name='Dummy Corporation 1',
corporation_ticker='DC1',
alliance_id=3001,
alliance_name='Dummy Alliance 1',
alliance_ticker='DA1',
)
self.my_character_2 = EveCharacter.objects.create(
character_id=1002,
character_name='Peter Parker',
corporation_id=2002,
corporation_name='Dummy Corporation 2',
corporation_ticker='DC2',
)
self.my_alliance = EveAllianceInfo.objects.create(
alliance_id=3001,
alliance_name='Dummy Alliance 1',
alliance_ticker='DA1',
executor_corp_id=2001
)
self.my_corporation = EveCorporationInfo(
corporation_id=2001,
corporation_name='Dummy Corporation 1',
corporation_ticker='DC1',
member_count=42,
alliance=self.my_alliance
)
self.my_region_id = 8001
self.my_region_name = 'Southpark'
self.my_solar_system_id = 9001
self.my_solar_system_name = 'Gotham'
def test_evewho_character_url(self):
self.assertEqual(
evelinks.evewho_character_url(self.my_character),
evewho.character_url(self.my_character.character_id),
)
self.assertEqual(
evelinks.evewho_character_url(None),
''
)
self.assertEqual(
evelinks.evewho_character_url(self.my_character.character_id),
evewho.character_url(self.my_character.character_id),
)
def test_evewho_corporation_url(self):
self.assertEqual(
evelinks.evewho_corporation_url(self.my_character),
evewho.corporation_url(self.my_character.corporation_id),
)
self.assertEqual(
evelinks.evewho_corporation_url(self.my_corporation),
evewho.corporation_url(self.my_corporation.corporation_id),
)
self.assertEqual(
evelinks.evewho_corporation_url(None),
''
)
self.assertEqual(
evelinks.evewho_corporation_url(self.my_character.corporation_id),
evewho.corporation_url(self.my_character.corporation_id),
)
def test_evewho_alliance_url(self):
self.assertEqual(
evelinks.evewho_alliance_url(self.my_character),
evewho.alliance_url(self.my_character.alliance_id),
)
self.assertEqual(
evelinks.evewho_alliance_url(self.my_character_2),
'',
)
self.assertEqual(
evelinks.evewho_alliance_url(self.my_alliance),
evewho.alliance_url(self.my_alliance.alliance_id),
)
self.assertEqual(
evelinks.evewho_alliance_url(None),
''
)
self.assertEqual(
evelinks.evewho_alliance_url(self.my_character.alliance_id),
evewho.alliance_url(self.my_character.alliance_id),
)
# dotlan
def test_dotlan_corporation_url(self):
self.assertEqual(
evelinks.dotlan_corporation_url(self.my_character),
dotlan.corporation_url(self.my_character.corporation_name),
)
self.assertEqual(
evelinks.dotlan_corporation_url(self.my_corporation),
dotlan.corporation_url(self.my_corporation.corporation_name),
)
self.assertEqual(
evelinks.dotlan_corporation_url(None),
''
)
self.assertEqual(
evelinks.dotlan_corporation_url(self.my_character.corporation_name),
dotlan.corporation_url(self.my_character.corporation_name),
)
def test_dotlan_alliance_url(self):
self.assertEqual(
evelinks.dotlan_alliance_url(self.my_character),
dotlan.alliance_url(self.my_character.alliance_name),
)
self.assertEqual(
evelinks.dotlan_alliance_url(self.my_character_2),
'',
)
self.assertEqual(
evelinks.dotlan_alliance_url(self.my_alliance),
dotlan.alliance_url(self.my_alliance.alliance_name),
)
self.assertEqual(
evelinks.dotlan_alliance_url(None),
''
)
self.assertEqual(
evelinks.dotlan_alliance_url(self.my_character.alliance_name),
dotlan.alliance_url(self.my_character.alliance_name),
)
def test_dotlan_region_url(self):
self.assertEqual(
evelinks.dotlan_region_url(self.my_region_name),
dotlan.region_url(self.my_region_name),
)
self.assertEqual(
evelinks.dotlan_region_url(None),
''
)
def test_dotlan_solar_system_url(self):
self.assertEqual(
evelinks.dotlan_solar_system_url(self.my_solar_system_name),
dotlan.solar_system_url(self.my_solar_system_name),
)
self.assertEqual(
evelinks.dotlan_solar_system_url(None),
''
)
# zkillboard
def test_zkillboard_character_url(self):
self.assertEqual(
evelinks.zkillboard_character_url(self.my_character),
zkillboard.character_url(self.my_character.character_id),
)
self.assertEqual(
evelinks.zkillboard_character_url(None),
''
)
self.assertEqual(
evelinks.zkillboard_character_url(self.my_character.character_id),
zkillboard.character_url(self.my_character.character_id),
)
def test_zkillboard_corporation_url(self):
self.assertEqual(
evelinks.zkillboard_corporation_url(self.my_character),
zkillboard.corporation_url(self.my_character.corporation_id),
)
self.assertEqual(
evelinks.zkillboard_corporation_url(self.my_corporation),
zkillboard.corporation_url(self.my_corporation.corporation_id),
)
self.assertEqual(
evelinks.zkillboard_corporation_url(None),
''
)
self.assertEqual(
evelinks.zkillboard_corporation_url(self.my_character.corporation_id),
zkillboard.corporation_url(self.my_character.corporation_id),
)
def test_zkillboard_alliance_url(self):
self.assertEqual(
evelinks.zkillboard_alliance_url(self.my_character),
zkillboard.alliance_url(self.my_character.alliance_id),
)
self.assertEqual(
evelinks.zkillboard_alliance_url(self.my_character_2),
'',
)
self.assertEqual(
evelinks.zkillboard_alliance_url(self.my_alliance),
zkillboard.alliance_url(self.my_alliance.alliance_id),
)
self.assertEqual(
evelinks.zkillboard_alliance_url(None),
''
)
self.assertEqual(
evelinks.zkillboard_alliance_url(self.my_character.alliance_id),
zkillboard.alliance_url(self.my_character.alliance_id),
)
def test_zkillboard_region_url(self):
self.assertEqual(
evelinks.zkillboard_region_url(self.my_region_id),
zkillboard.region_url(self.my_region_id),
)
self.assertEqual(
evelinks.zkillboard_region_url(None),
''
)
def test_zkillboard_solar_system_url(self):
self.assertEqual(
evelinks.zkillboard_solar_system_url(self.my_solar_system_id),
zkillboard.solar_system_url(self.my_solar_system_id),
)
self.assertEqual(
evelinks.zkillboard_solar_system_url(None),
''
)
# image URLs
def test_character_portrait_url(self):
self.assertEqual(
evelinks.character_portrait_url(123),
EveCharacter.generic_portrait_url(123)
),
self.assertEqual(
evelinks.character_portrait_url(123, 128),
EveCharacter.generic_portrait_url(123, 128)
)
self.assertEqual(
evelinks.character_portrait_url(123, 99),
''
)
self.assertEqual(
evelinks.character_portrait_url(self.my_character),
self.my_character.portrait_url()
)
self.assertEqual(
evelinks.character_portrait_url(None),
''
)
def test_corporation_logo_url(self):
self.assertEqual(
evelinks.corporation_logo_url(123),
EveCorporationInfo.generic_logo_url(123)
),
self.assertEqual(
evelinks.corporation_logo_url(123, 128),
EveCorporationInfo.generic_logo_url(123, 128)
)
self.assertEqual(
evelinks.corporation_logo_url(123, 99),
''
)
self.assertEqual(
evelinks.corporation_logo_url(self.my_corporation),
self.my_corporation.logo_url()
)
self.assertEqual(
evelinks.corporation_logo_url(self.my_character),
self.my_character.corporation_logo_url()
)
self.assertEqual(
evelinks.corporation_logo_url(None),
''
)
def test_alliance_logo_url(self):
self.assertEqual(
evelinks.alliance_logo_url(123),
EveAllianceInfo.generic_logo_url(123)
),
self.assertEqual(
evelinks.alliance_logo_url(123, 128),
EveAllianceInfo.generic_logo_url(123, 128)
)
self.assertEqual(
evelinks.alliance_logo_url(123, 99),
''
)
self.assertEqual(
evelinks.alliance_logo_url(self.my_alliance),
self.my_alliance.logo_url()
)
self.assertEqual(
evelinks.alliance_logo_url(self.my_character),
self.my_character.alliance_logo_url()
)
self.assertEqual(
evelinks.alliance_logo_url(None),
''
)
self.assertEqual(
evelinks.alliance_logo_url(self.my_character_2),
''
)

View File

@ -0,0 +1,57 @@
# this module generates profile URLs for zKillboard
from urllib.parse import urljoin, quote
from . import *
BASE_URL = 'https://zkillboard.com'
def _build_url(category: str, eve_id: int) -> str:
"""return url to profile page for an eve entity"""
if category == ESI_CATEGORY_ALLIANCE:
partial = 'alliance'
elif category == ESI_CATEGORY_CORPORATION:
partial = 'corporation'
elif category == ESI_CATEGORY_CHARACTER:
partial = 'character'
elif category == ESI_CATEGORY_REGION:
partial = 'region'
elif category == ESI_CATEGORY_SOLARSYSTEM:
partial = 'system'
else:
raise NotImplementedError(
"Not implemented yet for category:" + category
)
url = urljoin(
BASE_URL,
'{}/{}/'.format(partial, int(eve_id))
)
return url
def alliance_url(eve_id: int) -> str:
"""url for page about given alliance on zKillboard"""
return _build_url(ESI_CATEGORY_ALLIANCE, eve_id)
def character_url(eve_id: int) -> str:
"""url for page about given character on zKillboard"""
return _build_url(ESI_CATEGORY_CHARACTER, eve_id)
def corporation_url(eve_id: int) -> str:
"""url for page about given corporation on zKillboard"""
return _build_url(ESI_CATEGORY_CORPORATION, eve_id)
def region_url(eve_id: int) -> str:
"""url for page about given region on zKillboard"""
return _build_url(ESI_CATEGORY_REGION, eve_id)
def solar_system_url(eve_id: int) -> str:
return _build_url(ESI_CATEGORY_SOLARSYSTEM, eve_id)

View File

@ -0,0 +1,286 @@
# This module defines template tags for evelinks URLs and eve image URLs
#
# Many tags will work both with their respective eveonline object
# and their respective eve entity ID
#
# Example:
# character URL on evewho: {{ my_character|evewho_character_url}}
# character URL on evewho: {{ 1456384556|evewho_character_url}}
#
# For more examples see examples.html
#
# To add templatetags for additional providers just add the respective
# template functions and let them call the generic functions
from django import template
from ..models import EveCharacter, EveCorporationInfo, EveAllianceInfo
from ..evelinks import evewho, dotlan, zkillboard
register = template.Library()
_DEFAULT_IMAGE_SIZE = 32
# generic functions
def _generic_character_url(
provider: object,
obj_prop: str,
eve_obj: EveCharacter
) -> str:
"""returns character URL for given provider and object"""
my_func = getattr(provider, 'character_url')
if isinstance(eve_obj, EveCharacter):
return my_func(getattr(eve_obj, obj_prop))
elif eve_obj is None:
return ''
else:
return my_func(eve_obj)
def _generic_corporation_url(
provider: object,
obj_prop: str,
eve_obj: object
) -> str:
"""returns corporation URL for given provider and object"""
my_func = getattr(provider, 'corporation_url')
if isinstance(eve_obj, (EveCharacter, EveCorporationInfo)):
return my_func(getattr(eve_obj, obj_prop))
elif eve_obj is None:
return ''
else:
return my_func(eve_obj)
def _generic_alliance_url(
provider: object,
obj_prop: str,
eve_obj: object
) -> str:
"""returns alliance URL for given provider and object"""
my_func = getattr(provider, 'alliance_url')
if isinstance(eve_obj, EveCharacter):
if eve_obj.alliance_id:
return my_func(getattr(eve_obj, obj_prop))
else:
return ''
elif isinstance(eve_obj, EveAllianceInfo):
return my_func(getattr(eve_obj, obj_prop))
elif eve_obj is None:
return ''
else:
return my_func(eve_obj)
def _generic_evelinks_url(
provider: object,
provider_func: str,
eve_obj: object
) -> str:
"""returns evelinks URL for given provider, function and object"""
my_func = getattr(provider, provider_func)
if eve_obj is None:
return ''
else:
return my_func(eve_obj)
# evewho
@register.filter
def evewho_character_url(eve_obj: EveCharacter) -> str:
"""generates an evewho URL for the given object
Works with allianceauth.eveonline objects and eve entity IDs
Returns URL or empty string
"""
return _generic_character_url(evewho, 'character_id', eve_obj)
@register.filter
def evewho_corporation_url(eve_obj: object) -> str:
"""generates an evewho URL for the given object
Works with allianceauth.eveonline objects and eve entity IDs
Returns URL or empty string
"""
return _generic_corporation_url(evewho, 'corporation_id', eve_obj)
@register.filter
def evewho_alliance_url(eve_obj: object) -> str:
"""generates an evewho URL for the given object
Works with allianceauth.eveonline objects and eve entity IDs
Returns URL or empty string
"""
return _generic_alliance_url(evewho, 'alliance_id', eve_obj)
# dotlan
@register.filter
def dotlan_corporation_url(eve_obj: object) -> str:
"""generates a dotlan URL for the given object
Works with allianceauth.eveonline objects and eve entity names
Returns URL or empty string
"""
return _generic_corporation_url(dotlan, 'corporation_name', eve_obj)
@register.filter
def dotlan_alliance_url(eve_obj: object) -> str:
"""generates a dotlan URL for the given object
Works with allianceauth.eveonline objects and eve entity names
Returns URL or empty string
"""
return _generic_alliance_url(dotlan, 'alliance_name', eve_obj)
@register.filter
def dotlan_region_url(eve_obj: object) -> str:
"""generates a dotlan URL for the given object
Works with eve entity names
Returns URL or empty string
"""
return _generic_evelinks_url(dotlan, 'region_url', eve_obj)
@register.filter
def dotlan_solar_system_url(eve_obj: object) -> str:
"""generates a dotlan URL for the given object
Works with eve entity names
Returns URL or empty string
"""
return _generic_evelinks_url(dotlan, 'solar_system_url', eve_obj)
#zkillboard
@register.filter
def zkillboard_character_url(eve_obj: EveCharacter) -> str:
"""generates a zkillboard URL for the given object
Works with allianceauth.eveonline objects and eve entity IDs
Returns URL or empty string
"""
return _generic_character_url(zkillboard, 'character_id', eve_obj)
@register.filter
def zkillboard_corporation_url(eve_obj: object) -> str:
"""generates a zkillboard URL for the given object
Works with allianceauth.eveonline objects and eve entity IDs
Returns URL or empty string
"""
return _generic_corporation_url(zkillboard, 'corporation_id', eve_obj)
@register.filter
def zkillboard_alliance_url(eve_obj: object) -> str:
"""generates a zkillboard URL for the given object
Works with allianceauth.eveonline objects and eve entity IDs
Returns URL or empty string
"""
return _generic_alliance_url(zkillboard, 'alliance_id', eve_obj)
@register.filter
def zkillboard_region_url(eve_obj: object) -> str:
"""generates a zkillboard URL for the given object
Works with eve entity IDs
Returns URL or empty string
"""
return _generic_evelinks_url(zkillboard, 'region_url', eve_obj)
@register.filter
def zkillboard_solar_system_url(eve_obj: object) -> str:
"""generates zkillboard URL for the given object
Works with eve entity IDs
Returns URL or empty string
"""
return _generic_evelinks_url(zkillboard, 'solar_system_url', eve_obj)
# image urls
@register.filter
def character_portrait_url(
eve_obj: object,
size: int = _DEFAULT_IMAGE_SIZE
) -> str:
"""generates an image URL for the given object
Works with EveCharacter objects or character IDs
Returns URL or empty string
"""
if isinstance(eve_obj, EveCharacter):
return eve_obj.portrait_url(size)
elif eve_obj is None:
return ''
else:
try:
return EveCharacter.generic_portrait_url(eve_obj, size)
except ValueError:
return ''
@register.filter
def corporation_logo_url(
eve_obj: object,
size: int = _DEFAULT_IMAGE_SIZE
) -> str:
"""generates image URL for the given object
Works with EveCharacter, EveCorporationInfo objects or corporation IDs
Returns URL or empty string
"""
if isinstance(eve_obj, EveCorporationInfo):
return eve_obj.logo_url(size)
elif isinstance(eve_obj, EveCharacter):
return eve_obj.corporation_logo_url(size)
elif eve_obj is None:
return ''
else:
try:
return EveCorporationInfo.generic_logo_url(eve_obj, size)
except ValueError:
return ''
@register.filter
def alliance_logo_url(
eve_obj: object,
size: int = _DEFAULT_IMAGE_SIZE
) -> str:
"""generates image URL for the given object
Works with EveCharacter, EveAllianceInfo objects or alliance IDs
Returns URL or empty string
"""
if isinstance(eve_obj, EveAllianceInfo):
return eve_obj.logo_url(size)
elif isinstance(eve_obj, EveCharacter):
return eve_obj.alliance_logo_url(size)
elif eve_obj is None:
return ''
else:
try:
return EveAllianceInfo.generic_logo_url(eve_obj, size)
except ValueError:
return ''

View File

@ -0,0 +1,84 @@
<!-- This is an example template for the evelinks template tags
Needs to be called with a context containing three objects:
- EveCharacter: my_character
- EveCorporationInfo: my_corporation
- EveAllianceInfo: my_alliance
-->
{% extends 'allianceauth/base.html' %}
{% load evelinks %}
{% block page_title %}Evelinks examples{% endblock %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">Evelinks templatetags examples</h1>
<div class="col-lg-12 container">
<h2>profile URLs</h2>
<div class="rows">
<div class="col-md-4">
<h3>evewho</h3>
<p><a href="{{ my_character|evewho_character_url}}">character from character object</a></p>
<p><a href="{{ my_corporation|evewho_corporation_url}}">corporation form corporation object</a></p>
<p><a href="{{ my_character|evewho_corporation_url}}">corporation from charachter object</a></p>
<p><a href="{{ my_alliance|evewho_alliance_url}}">alliance from alliance object</a></p>
<p><a href="{{ my_character|evewho_alliance_url}}">alliance from character object</a></p>
</div>
<div class="col-md-4">
<h3>dotlan</h3>
<p><a href="{{ my_character|dotlan_corporation_url}}">corporation form character object</a></p>
<p><a href="{{ my_corporation|dotlan_corporation_url}}">corporation form corporation object</a></p>
<p><a href="{{ my_character|dotlan_alliance_url}}">alliance from character object</a></p>
<p><a href="{{ my_alliance|dotlan_alliance_url}}">alliance from alliance object</a></p>
<p><a href="{{ 'Black Rise'|dotlan_region_url}}">region from name string</a></p>
<p><a href="{{ 'Tama'|dotlan_solar_system_url}}">solar system from name string</a></p>
</div>
<div class="col-md-4">
<h3>zkillboard</h3>
<p><a href="{{ my_character|zkillboard_character_url}}">character from character object</a></p>
<p><a href="{{ my_character|zkillboard_corporation_url}}">corporation from character object</a></p>
<p><a href="{{ my_corporation|zkillboard_corporation_url}}">corporation form corporation object</a></p>
<p><a href="{{ my_character|zkillboard_alliance_url}}">alliance from character object</a></p>
<p><a href="{{ my_alliance|zkillboard_alliance_url}}">alliance from alliance object</a></p>
<p><a href="{{ 10000069|zkillboard_region_url}}">region from ID</a></p>
<p><a href="{{ 30002813|zkillboard_solar_system_url}}">solar sytem from ID</a></p>
</div>
</div>
</div>
<h2>image URLs</h2>
<div class="rows">
<div class="col-md-4">
<p>character from ID: <img src="{{ my_character.character_id|character_portrait_url:128}}"></p>
<p>character from character object: <img src="{{ my_character|character_portrait_url:128}}"></p>
</div>
<div class="col-md-4">
<p>corporation from ID: <img src="{{ my_character.corporation_id|corporation_logo_url:128}}"></p>
<p>corporation from character object: <img src="{{ my_character|corporation_logo_url:128}}"></p>
<p>corporation from corporation object: <img src="{{ my_corporation|corporation_logo_url:128}}"></p>
</div>
<div class="col-md-4">
<p>alliance from ID: <img src="{{ my_character.alliance_id|alliance_logo_url:128}}"></p>
<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 %}

View File

@ -8,8 +8,11 @@
<div class="col-lg-12"> <div class="col-lg-12">
<br> <br>
{% include 'groupmanagement/menu.html' %} {% include 'groupmanagement/menu.html' %}
<div> <div class="panel panel-default">
<h3>{{ group }} Audit Log</h3> <div class="panel-heading">
{{ group }} - {% trans 'Audit Log' %}
</div>
<div class="panel-body">
<p> All times displayed are EVE/UTC.</p> <p> All times displayed are EVE/UTC.</p>
{% if entries %} {% if entries %}
<div class="table-responsive"> <div class="table-responsive">
@ -47,6 +50,7 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div>
{% endblock %} {% endblock %}
{% block extra_javascript %} {% block extra_javascript %}
{% include 'bundles/datatables-js.html' %} {% include 'bundles/datatables-js.html' %}

View File

@ -1,6 +1,7 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load staticfiles %} {% load staticfiles %}
{% load i18n %} {% load i18n %}
{% load evelinks %}
{% block page_title %}{% trans "Group Members" %}{% endblock page_title %} {% block page_title %}{% trans "Group Members" %}{% endblock page_title %}
{% block extra_css %}{% endblock extra_css %} {% block extra_css %}{% endblock extra_css %}
@ -9,23 +10,48 @@
<div class="col-lg-12"> <div class="col-lg-12">
<br> <br>
{% include 'groupmanagement/menu.html' %} {% include 'groupmanagement/menu.html' %}
<h3>{{ group.name }} {% trans 'Members' %}</h3>
<div class="panel panel-default">
<div class="panel-heading">
{{ group.name }} - {% trans 'Members' %}
</div>
<div class="panel-body">
<div id="list" class=""> <div id="list" class="">
{% if group.user_set %} {% if group.user_set %}
<table class="table"> <table class="table">
<tr> <tr>
<th class="text-center">{% trans "User" %}</th> <th class="text-center">{% trans "Leader" %}</th>
<th class="text-center">{% trans "Portrait" %}</th>
<th class="text-center">{% trans "Character" %}</th> <th class="text-center">{% trans "Character" %}</th>
<th class="text-center">{% trans "Corp" %}</th> <th class="text-center">{% trans "Corporation" %}</th>
<th class="text-center">{% trans "Alliance" %}</th> <th class="text-center">{% trans "Alliance" %}</th>
<th class="text-center">{% trans "Action" %}</th> <th class="text-center">{% trans "Action" %}</th>
</tr> </tr>
{% for member in members %} {% for member in members %}
<tr> <tr>
<td class="text-center">{{ member.user.username }}</td> <td class="text-center">
<td class="text-center">{{ member.main_char.character_name }}</td> {% if member.is_leader %}
<td class="text-center">{{ member.main_char.corporation_name }}</td> <i class="fa fa-star"></i>
<td class="text-center">{{ member.main_char.alliance_name }}</td> {% endif %}
</td>
<td class="text-center">
<img src="{{ member.main_char|character_portrait_url:32 }}" class="img-circle">
</td>
<td class="text-center">
<a href="{{ member.main_char|evewho_character_url }}" target="_blank">
{{ member.main_char.character_name }}
</a>
</td>
<td class="text-center">
<a href="{{ member.main_char|dotlan_corporation_url }}" target="_blank">
{{ member.main_char.corporation_name }}
</a>
</td>
<td class="text-center">
<a href="{{ member.main_char|dotlan_alliance_url }}" target="_blank">
{{ member.main_char.alliance_name|default_if_none:"" }}
</a>
</td>
<td class="text-center"> <td class="text-center">
<a href="{% url 'groupmanagement:membership_remove' group.id member.user.id %}" class="btn btn-danger" <a href="{% url 'groupmanagement:membership_remove' group.id member.user.id %}" class="btn btn-danger"
title="{% trans "Remove from group" %}"> title="{% trans "Remove from group" %}">
@ -40,4 +66,6 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div>
</div>
{% endblock content %} {% endblock content %}

View File

@ -9,9 +9,12 @@
<div class="col-lg-12"> <div class="col-lg-12">
<br> <br>
{% include 'groupmanagement/menu.html' %} {% include 'groupmanagement/menu.html' %}
<div> <div class="panel panel-default">
<div class="panel-heading">
Groups
</div>
<div class="panel-body">
{% if groups %} {% if groups %}
<h3>Groups</h3>
<table class="table"> <table class="table">
<tr> <tr>
<th class="text-center">{% trans "Name" %}</th> <th class="text-center">{% trans "Name" %}</th>
@ -53,4 +56,5 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div>
{% endblock content %} {% endblock content %}

View File

@ -1,33 +1,65 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load staticfiles %} {% load staticfiles %}
{% load i18n %} {% load i18n %}
{% load evelinks %}
{% block page_title %}{% trans "Groups Management" %}{% endblock page_title %} {% block page_title %}{% trans "Groups Management" %}{% endblock page_title %}
{% block extra_css %}{% endblock extra_css %} {% block extra_css %}
<style>
.nav-tabs>li.active>a {
background-color: #ECF0F1 !important;
color: #2C3E50;
}
</style>
{% endblock extra_css %}
{% block content %} {% block content %}
<div class="col-lg-12"> <div class="col-lg-12">
<br> <br>
{% include 'groupmanagement/menu.html' %} {% include 'groupmanagement/menu.html' %}
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" href="#add">{% trans "Group Add Requests" %}</a></li> <li class="active"><a data-toggle="tab" href="#add">{% trans "Group Add Requests" %}</a></li>
<li><a data-toggle="tab" href="#leave">{% trans "Group Leave Requests" %}</a></li> <li><a data-toggle="tab" href="#leave">{% trans "Group Leave Requests" %}</a></li>
</ul> </ul>
<div class="tab-content"> <div class="tab-content">
<div id="add" class="tab-pane fade in active panel panel-default"> <div id="add" class="tab-pane fade in active panel panel-default">
<div class="panel-body"> <div class="panel-body">
{% if acceptrequests %} {% if acceptrequests %}
<table class="table"> <table class="table">
<tr> <tr>
<th class="text-center">{% trans "RequestID" %}</th> <th class="text-center">{% trans "#" %}</th>
<th class="text-center">{% trans "CharacterName" %}</th> <th class="text-center">{% trans "Portrait" %}</th>
<th class="text-center">{% trans "GroupName" %}</th> <th class="text-center">{% trans "Character" %}</th>
<th class="text-center">{% trans "Action" %}</th> <th class="text-center">{% trans "Corporation" %}</th>
<th class="text-center">{% trans "Alliance" %}</th>
<th class="text-center">{% trans "Group" %}</th>
<th class="text-center"></th>
</tr> </tr>
{% for acceptrequest in acceptrequests %} {% for acceptrequest in acceptrequests %}
<tr> <tr>
<td class="text-center">{{ acceptrequest.id }}</td> <td class="text-center">{{ acceptrequest.id }}</td>
<td class="text-center">{{ acceptrequest.main_char.character_name }}</td> <td class="text-center">
<img src="{{ acceptrequest.main_char|character_portrait_url:32 }}" class="img-circle">
</td>
<td class="text-center">
<a href="{{ acceptrequest.main_char|evewho_character_url }}" target="_blank">
{{ acceptrequest.main_char.character_name }}
</a>
</td>
<td class="text-center">
<a href="{{ acceptrequest.main_char|dotlan_corporation_url }}" target="_blank">
{{ acceptrequest.main_char.corporation_name }}
</a>
</td>
<td class="text-center">
<a href="{{ acceptrequest.main_char|dotlan_alliance_url }}" target="_blank">
{{ acceptrequest.main_char.alliance_name|default_if_none:"" }}
</a>
</td>
<td class="text-center">{{ acceptrequest.group.name }}</td> <td class="text-center">{{ acceptrequest.group.name }}</td>
<td class="text-center"> <td class="text-center">
<a href="{% url 'groupmanagement:accept_request' acceptrequest.id %}" class="btn btn-success"> <a href="{% url 'groupmanagement:accept_request' acceptrequest.id %}" class="btn btn-success">
@ -45,20 +77,41 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
<div id="leave" class="tab-pane fade panel panel-default"> <div id="leave" class="tab-pane fade panel panel-default">
<div class="panel-body"> <div class="panel-body">
{% if leaverequests %} {% if leaverequests %}
<table class="table"> <table class="table">
<tr> <tr>
<th class="text-center">{% trans "RequestID" %}</th> <th class="text-center">{% trans "#" %}</th>
<th class="text-center">{% trans "CharacterName" %}</th> <th class="text-center">{% trans "Portrait" %}</th>
<th class="text-center">{% trans "GroupName" %}</th> <th class="text-center">{% trans "Character" %}</th>
<th class="text-center">{% trans "Action" %}</th> <th class="text-center">{% trans "Corporation" %}</th>
<th class="text-center">{% trans "Alliance" %}</th>
<th class="text-center">{% trans "Group" %}</th>
<th class="text-center"></th>
</tr> </tr>
{% for leaverequest in leaverequests %} {% for leaverequest in leaverequests %}
<tr> <tr>
<td class="text-center">{{ leaverequest.id }}</td> <td class="text-center">{{ leaverequest.id }}</td>
<td class="text-center">{{ leaverequest.main_char.character_name }}</td> <td class="text-center">
<img src="{{ leaverequest.main_char|character_portrait_url:32 }}" class="img-circle">
</td>
<td class="text-center">
<a href="{{ leaverequest.main_char|evewho_character_url }}" target="_blank">
{{ leaverequest.main_char.character_name }}
</a>
</td>
<td class="text-center">
<a href="{{ leaverequest.main_char|dotlan_corporation_url }}" target="_blank">
{{ leaverequest.main_char.corporation_name }}
</a>
</td>
<td class="text-center">
<a href="{{ leaverequest.main_char|dotlan_alliance_url }}" target="_blank">
{{ leaverequest.main_char.alliance_name|default_if_none:"" }}
</a>
</td>
<td class="text-center">{{ leaverequest.group.name }}</td> <td class="text-center">{{ leaverequest.group.name }}</td>
<td class="text-center"> <td class="text-center">
<a href="{% url 'groupmanagement:leave_accept_request' leaverequest.id %}" class="btn btn-success"> <a href="{% url 'groupmanagement:leave_accept_request' leaverequest.id %}" class="btn btn-success">
@ -76,6 +129,7 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{% endblock content %} {% endblock content %}

View File

@ -3,7 +3,8 @@
{% load navactive %} {% load navactive %}
<nav class="navbar navbar-default"> <nav class="navbar navbar-default">
<div class="container-fluid"> <div class="container-fluid">
<div class="navbar-header"> <div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">{% trans "Toggle navigation" %}</span> <span class="sr-only">{% trans "Toggle navigation" %}</span>
@ -11,17 +12,19 @@
<span class="icon-bar"></span> <span class="icon-bar"></span>
<span class="icon-bar"></span> <span class="icon-bar"></span>
</button> </button>
<a class="navbar-brand" href="#">{% trans "Group Management" %}</a> <a class="navbar-brand" href="">{% trans "Group Management" %}</a>
</div> </div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li class="{% navactive request 'auth_group_management' %}"> <li class="{% navactive request 'groupmanagement:management' %}">
<a href="{% url 'groupmanagement:management' %}">{% trans "Group Requests" %}</a> <a href="{% url 'groupmanagement:management' %}">{% trans "Group Requests" %}</a>
</li> </li>
<li class="{% navactive request 'auth_group_membership auth_group_membership_list' %}"> <li class="{% renavactive request '^/group/membership/' %}">
<a href="{% url 'groupmanagement:membership' %}">{% trans "Group Membership" %}</a> <a href="{% url 'groupmanagement:membership' %}">{% trans "Group Membership" %}</a>
</li> </li>
</ul> </ul>
</div> </div>
</div>
</div>
</nav> </nav>

View File

@ -96,32 +96,47 @@ def group_membership_audit(request, group_id):
@login_required @login_required
@user_passes_test(GroupManager.can_manage_groups) @user_passes_test(GroupManager.can_manage_groups)
def group_membership_list(request, group_id): def group_membership_list(request, group_id):
logger.debug("group_membership_list called by user %s for group id %s" % (request.user, group_id)) logger.debug(
"group_membership_list called by user %s "
"for group id %s" % (request.user, group_id)
)
group = get_object_or_404(Group, id=group_id) group = get_object_or_404(Group, id=group_id)
try: try:
# Check its a joinable group i.e. not corp or internal # Check its a joinable group i.e. not corp or internal
# And the user has permission to manage it # And the user has permission to manage it
if not GroupManager.check_internal_group(group) or not GroupManager.can_manage_group(request.user, group): if (not GroupManager.check_internal_group(group)
logger.warning("User %s attempted to view the membership of group %s but permission was denied" % or not GroupManager.can_manage_group(request.user, group)
(request.user, group_id)) ):
logger.warning(
"User %s attempted to view the membership of group %s "
"but permission was denied" % (request.user, group_id)
)
raise PermissionDenied raise PermissionDenied
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise Http404("Group does not exist") raise Http404("Group does not exist")
group_leaders = group.authgroup.group_leaders.all()
members = list() members = list()
for member in \
for member in group.user_set.select_related('profile').all().order_by('username'): group.user_set\
.all()\
.select_related('profile')\
.order_by('profile__main_character__character_name'):
members.append({ members.append({
'user': member, 'user': member,
'main_char': member.profile.main_character 'main_char': member.profile.main_character,
'is_leader': member in group_leaders
}) })
render_items = {'group': group, 'members': members} render_items = {'group': group, 'members': members}
return render(request, 'groupmanagement/groupmembers.html', context=render_items) return render(
request, 'groupmanagement/groupmembers.html',
context=render_items
)
@login_required @login_required

View File

@ -1,4 +1,5 @@
{% load i18n %} {% load i18n %}
{% load evelinks %}
{% block content %} {% block content %}
<table class="table"> <table class="table">
@ -23,7 +24,7 @@
<td class="text-center">{{ ops.operation_name }}</td> <td class="text-center">{{ ops.operation_name }}</td>
<td class="text-center">{{ ops.doctrine }}</td> <td class="text-center">{{ ops.doctrine }}</td>
<td class="text-center"> <td class="text-center">
<a href="http://evemaps.dotlan.net/system/{{ ops.system }}">{{ ops.system }}</a> <a href="{{ ops.system|dotlan_solar_system_url }}">{{ ops.system }}</a>
</td> </td>
<td class="text-center" nowrap>{{ ops.start | date:"Y-m-d H:i" }}</td> <td class="text-center" nowrap>{{ ops.start | date:"Y-m-d H:i" }}</td>
<td class="text-center" nowrap><div id="localtime{{ ops.id }}"></div><div id="countdown{{ ops.id }}"></div></td> <td class="text-center" nowrap><div id="localtime{{ ops.id }}"></div><div id="countdown{{ ops.id }}"></div></td>

View File

@ -2,6 +2,7 @@
{% load staticfiles %} {% load staticfiles %}
{% load i18n %} {% load i18n %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
{% load evelinks %}
{% block page_title %}{% trans "Structure Timer Management" %}{% endblock page_title %} {% block page_title %}{% trans "Structure Timer Management" %}{% endblock page_title %}
{% block extra_css %}{% endblock extra_css %} {% block extra_css %}{% endblock extra_css %}
@ -61,7 +62,7 @@
{% endif %} {% endif %}
</td> </td>
<td class="text-center"><a <td class="text-center"><a
href="http://evemaps.dotlan.net/system/{{ timer.system }}">{{ timer.system }} {{ timer.planet_moon }} </a> href="{{ timer.system|dotlan_solar_system_url }}">{{ timer.system }} {{ timer.planet_moon }} </a>
</td> </td>
<td class="text-center"> <td class="text-center">
{% if timer.structure == "POCO" %} {% if timer.structure == "POCO" %}
@ -220,7 +221,7 @@
{% endif %} {% endif %}
</td> </td>
<td class="text-center"> <td class="text-center">
<a href="http://evemaps.dotlan.net/system/{{ timer.system }}">{{ timer.system }} {{ timer.planet_moon }}</a> <a href="{{ timer.system|dotlan_solar_system_url }}">{{ timer.system }} {{ timer.planet_moon }}</a>
</td> </td>
<td class="text-center"> <td class="text-center">
{% if timer.structure == "POCO" %} {% if timer.structure == "POCO" %}
@ -381,7 +382,7 @@
{% endif %} {% endif %}
</td> </td>
<td class="text-center"> <td class="text-center">
<a href="http://evemaps.dotlan.net/system/{{ timer.system }}">{{ timer.system }} {{ timer.planet_moon }}</a> <a href="{{ timer.system|dotlan_solar_system_url }}">{{ timer.system }} {{ timer.planet_moon }}</a>
</td> </td>
<td class="text-center"> <td class="text-center">
{% if timer.structure == "POCO" %} {% if timer.structure == "POCO" %}