mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2026-02-04 14:16:21 +01:00
Compare commits
89 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08e9676760 | ||
|
|
15ae737522 | ||
|
|
50ec9e563e | ||
|
|
cb40649f8b | ||
|
|
bccead0881 | ||
|
|
35ae710624 | ||
|
|
75de4518f2 | ||
|
|
bfcdfea6c8 | ||
|
|
471553fa88 | ||
|
|
db59f5f69b | ||
|
|
1b5413646e | ||
|
|
0337d2517c | ||
|
|
87e6eb9688 | ||
|
|
7b8c246ef8 | ||
|
|
a268a8980a | ||
|
|
3b516c338e | ||
|
|
9952685805 | ||
|
|
2f59c8df22 | ||
|
|
6cd0a42791 | ||
|
|
4c42153bfd | ||
|
|
603bd9c37c | ||
|
|
87c0c3ac73 | ||
|
|
8a91e7f6ac | ||
|
|
281dbdbb01 | ||
|
|
8980d8d32f | ||
|
|
9d6cf9a62e | ||
|
|
0fabb2b368 | ||
|
|
9801ca0314 | ||
|
|
fd86b26b39 | ||
|
|
b0dbef1587 | ||
|
|
a6e60bc23b | ||
|
|
137e8a876d | ||
|
|
fe9538253f | ||
|
|
edda2c248e | ||
|
|
62275639e3 | ||
|
|
d0c68b82f4 | ||
|
|
78b5953bdf | ||
|
|
25e565b099 | ||
|
|
1fe0f78ad7 | ||
|
|
fc8b68156f | ||
|
|
b47cd197ce | ||
|
|
3943426c4c | ||
|
|
08a9bd42a3 | ||
|
|
b2ff339efe | ||
|
|
c604131e04 | ||
|
|
f17607f126 | ||
|
|
94e455a57b | ||
|
|
3c9149db4a | ||
|
|
96cc615c07 | ||
|
|
cd1f4a1c2b | ||
|
|
e0f99a42db | ||
|
|
3506e417d4 | ||
|
|
36197e2212 | ||
|
|
fc5f42d01e | ||
|
|
e26d3767e0 | ||
|
|
046b37c76a | ||
|
|
925ff3e116 | ||
|
|
e5ede4f7b6 | ||
|
|
ded9301527 | ||
|
|
bd1ed6ff73 | ||
|
|
feb65980d4 | ||
|
|
e81d75a782 | ||
|
|
ff305d13ae | ||
|
|
8bcbc1a779 | ||
|
|
3874aa6fee | ||
|
|
103e9f3a11 | ||
|
|
d02c25f421 | ||
|
|
228af38a4a | ||
|
|
051a48885c | ||
|
|
6bcdc6052f | ||
|
|
af3527e64f | ||
|
|
17ef3dd07a | ||
|
|
1f165ecd2a | ||
|
|
70d1d450a9 | ||
|
|
b667892698 | ||
|
|
dc11add0e9 | ||
|
|
cb429a0b88 | ||
|
|
b51039cfc0 | ||
|
|
eadd959d95 | ||
|
|
1856e03d88 | ||
|
|
7dcfa622a3 | ||
|
|
64251b9b3c | ||
|
|
6b073dd5fc | ||
|
|
0911fabfb2 | ||
|
|
050d3f5e63 | ||
|
|
bbe3f78ad1 | ||
|
|
8204c18895 | ||
|
|
b91c788897 | ||
|
|
1d20a3029f |
@@ -41,7 +41,7 @@ test-3.8-all:
|
||||
|
||||
deploy_production:
|
||||
stage: deploy
|
||||
image: python:3.6-stretch
|
||||
image: python:3.8-buster
|
||||
|
||||
before_script:
|
||||
- pip install twine
|
||||
|
||||
@@ -18,10 +18,6 @@ formats: all
|
||||
|
||||
# Optionally set the version of Python and requirements required to build your docs
|
||||
python:
|
||||
version: 3.7
|
||||
install:
|
||||
- method: pip
|
||||
path: .
|
||||
extra_requirements:
|
||||
- testing
|
||||
system_packages: true
|
||||
version: 3.7
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
@@ -36,7 +36,7 @@ Main features:
|
||||
|
||||
- Can be easily extended with additional services and apps. Many are provided by the community and can be found here: [Community Creations](https://gitlab.com/allianceauth/community-creations)
|
||||
|
||||
- Chinese :cn:, English :us:, German :de: and Spanish :es: localization
|
||||
- English :flag_gb:, Chinese :flag_cn:, German :flag_de:, Spanish :flag_es:, Korean :flag_kr: and Russian :flag_ru: localization
|
||||
|
||||
For further details about AA - including an installation guide and a full list of included services and plugin apps - please see the [official documentation](http://allianceauth.rtfd.io).
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# This will make sure the app is always imported when
|
||||
# Django starts so that shared_task will use this app.
|
||||
|
||||
__version__ = '2.7.4'
|
||||
__version__ = '2.8.1'
|
||||
__title__ = 'Alliance Auth'
|
||||
__url__ = 'https://gitlab.com/allianceauth/allianceauth'
|
||||
NAME = '%s v%s' % (__title__, __version__)
|
||||
|
||||
@@ -100,7 +100,7 @@ class UserProfileInline(admin.StackedInline):
|
||||
formset.get_form_kwargs = get_kwargs
|
||||
return formset
|
||||
|
||||
def has_add_permission(self, request):
|
||||
def has_add_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
def has_delete_permission(self, request, obj=None):
|
||||
@@ -549,7 +549,7 @@ class PermissionAdmin(admin.ModelAdmin):
|
||||
def admin_name(obj):
|
||||
return str(obj)
|
||||
|
||||
def has_add_permission(self, request):
|
||||
def has_add_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
def has_delete_permission(self, request, obj=None):
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
from allianceauth.authentication.models import User
|
||||
class RegistrationForm(forms.Form):
|
||||
email = forms.EmailField(label=_('Email'), max_length=254, required=True)
|
||||
|
||||
class _meta:
|
||||
model = User
|
||||
|
||||
@@ -10,5 +10,5 @@ urlpatterns = [
|
||||
url(r'^register/$', views.RegistrationView.as_view(), name='registration_register'),
|
||||
url(r'^register/complete/$', views.registration_complete, name='registration_complete'),
|
||||
url(r'^register/closed/$', views.registration_closed, name='registration_disallowed'),
|
||||
url(r'', include('registration.auth_urls')),
|
||||
url(r'', include('django.contrib.auth.urls')),
|
||||
]
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Dashboard" %}{% endblock %}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{% load staticfiles %}
|
||||
{% extends 'public/base.html' %}
|
||||
{% load static %}
|
||||
{% load bootstrap %}
|
||||
{% load i18n %}
|
||||
{% extends 'public/base.html' %}
|
||||
{% block page_title %}Registration{% endblock %}
|
||||
{% block extra_include %}
|
||||
{% include 'bundles/bootstrap-css.html' %}
|
||||
|
||||
@@ -6,7 +6,7 @@ from django.contrib.auth import login, authenticate
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.models import User
|
||||
from django.core import signing
|
||||
from django.urls import reverse
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.shortcuts import redirect, render
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
@@ -14,12 +14,12 @@ from allianceauth.eveonline.models import EveCharacter
|
||||
from esi.decorators import token_required
|
||||
from esi.models import Token
|
||||
|
||||
from registration.backends.hmac.views import (
|
||||
from django_registration.backends.activation.views import (
|
||||
RegistrationView as BaseRegistrationView,
|
||||
ActivationView as BaseActivationView,
|
||||
REGISTRATION_SALT
|
||||
)
|
||||
from registration.signals import user_registered
|
||||
from django_registration.signals import user_registered
|
||||
|
||||
from .models import CharacterOwnership
|
||||
from .forms import RegistrationForm
|
||||
@@ -134,11 +134,14 @@ def sso_login(request, token):
|
||||
# Step 2
|
||||
class RegistrationView(BaseRegistrationView):
|
||||
form_class = RegistrationForm
|
||||
success_url = 'authentication:dashboard'
|
||||
template_name = "public/register.html"
|
||||
email_body_template = "registration/activation_email.txt"
|
||||
email_subject_template = "registration/activation_email_subject.txt"
|
||||
success_url = reverse_lazy('registration_complete')
|
||||
|
||||
def get_success_url(self, user):
|
||||
if not getattr(settings, 'REGISTRATION_VERIFY_EMAIL', True):
|
||||
return 'authentication:dashboard', (), {}
|
||||
return reverse_lazy('authentication:dashboard')
|
||||
return super().get_success_url(user)
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
@@ -176,6 +179,9 @@ class RegistrationView(BaseRegistrationView):
|
||||
|
||||
# Step 3
|
||||
class ActivationView(BaseActivationView):
|
||||
template_name = "registration/activate.html"
|
||||
success_url = reverse_lazy('registration_activation_complete')
|
||||
|
||||
def validate_key(self, activation_key):
|
||||
try:
|
||||
dump = signing.loads(activation_key, salt=REGISTRATION_SALT,
|
||||
@@ -207,5 +213,5 @@ def activation_complete(request):
|
||||
|
||||
|
||||
def registration_closed(request):
|
||||
messages.error(request, _('Registraion of new accounts it not allowed at this time.'))
|
||||
messages.error(request, _('Registration of new accounts is not allowed at this time.'))
|
||||
return redirect('authentication:login')
|
||||
|
||||
@@ -7,6 +7,8 @@ from jsonschema.exceptions import RefResolutionError
|
||||
from django.conf import settings
|
||||
from esi.clients import esi_client_factory
|
||||
|
||||
from allianceauth import __version__
|
||||
|
||||
|
||||
SWAGGER_SPEC_PATH = os.path.join(os.path.dirname(
|
||||
os.path.abspath(__file__)), 'swagger.json'
|
||||
@@ -166,7 +168,7 @@ class EveSwaggerProvider(EveProvider):
|
||||
else:
|
||||
try:
|
||||
self._client = esi_client_factory(
|
||||
token=token, spec_file=SWAGGER_SPEC_PATH
|
||||
token=token, spec_file=SWAGGER_SPEC_PATH, app_info_text=("allianceauth v" + __version__)
|
||||
)
|
||||
except (HTTPError, RefResolutionError):
|
||||
logger.exception(
|
||||
@@ -182,7 +184,7 @@ class EveSwaggerProvider(EveProvider):
|
||||
def client(self):
|
||||
if self._client is None:
|
||||
self._client = esi_client_factory(
|
||||
token=self._token, spec_file=SWAGGER_SPEC_PATH
|
||||
token=self._token, spec_file=SWAGGER_SPEC_PATH, app_info_text=("allianceauth v" + __version__)
|
||||
)
|
||||
return self._client
|
||||
|
||||
|
||||
@@ -5,35 +5,96 @@ from .models import EveAllianceInfo
|
||||
from .models import EveCharacter
|
||||
from .models import EveCorporationInfo
|
||||
|
||||
from . import providers
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
TASK_PRIORITY = 7
|
||||
CHUNK_SIZE = 500
|
||||
|
||||
|
||||
def chunks(lst, n):
|
||||
"""Yield successive n-sized chunks from lst."""
|
||||
for i in range(0, len(lst), n):
|
||||
yield lst[i:i + n]
|
||||
|
||||
|
||||
@shared_task
|
||||
def update_corp(corp_id):
|
||||
"""Update given corporation from ESI"""
|
||||
EveCorporationInfo.objects.update_corporation(corp_id)
|
||||
|
||||
|
||||
@shared_task
|
||||
def update_alliance(alliance_id):
|
||||
"""Update given alliance from ESI"""
|
||||
EveAllianceInfo.objects.update_alliance(alliance_id).populate_alliance()
|
||||
|
||||
|
||||
@shared_task
|
||||
def update_character(character_id):
|
||||
"""Update given character from ESI"""
|
||||
EveCharacter.objects.update_character(character_id)
|
||||
|
||||
|
||||
@shared_task
|
||||
def run_model_update():
|
||||
"""Update all alliances, corporations and characters from ESI"""
|
||||
|
||||
# update existing corp models
|
||||
for corp in EveCorporationInfo.objects.all().values('corporation_id'):
|
||||
update_corp.apply_async(args=[corp['corporation_id']], priority=TASK_PRIORITY)
|
||||
update_corp.apply_async(
|
||||
args=[corp['corporation_id']], priority=TASK_PRIORITY
|
||||
)
|
||||
|
||||
# update existing alliance models
|
||||
for alliance in EveAllianceInfo.objects.all().values('alliance_id'):
|
||||
update_alliance.apply_async(args=[alliance['alliance_id']], priority=TASK_PRIORITY)
|
||||
update_alliance.apply_async(
|
||||
args=[alliance['alliance_id']], priority=TASK_PRIORITY
|
||||
)
|
||||
|
||||
#update existing character models
|
||||
for character in EveCharacter.objects.all().values('character_id'):
|
||||
update_character.apply_async(args=[character['character_id']], priority=TASK_PRIORITY)
|
||||
# update existing character models
|
||||
character_ids = EveCharacter.objects.all().values_list('character_id', flat=True)
|
||||
for character_ids_chunk in chunks(character_ids, CHUNK_SIZE):
|
||||
affiliations_raw = providers.provider.client.Character\
|
||||
.post_characters_affiliation(characters=character_ids_chunk).result()
|
||||
character_names = providers.provider.client.Universe\
|
||||
.post_universe_names(ids=character_ids_chunk).result()
|
||||
|
||||
affiliations = {
|
||||
affiliation.get('character_id'): affiliation
|
||||
for affiliation in affiliations_raw
|
||||
}
|
||||
# add character names to affiliations
|
||||
for character in character_names:
|
||||
character_id = character.get('id')
|
||||
if character_id in affiliations:
|
||||
affiliations[character_id]['name'] = character.get('name')
|
||||
|
||||
# fetch current characters
|
||||
characters = EveCharacter.objects.filter(character_id__in=character_ids_chunk)\
|
||||
.values('character_id', 'corporation_id', 'alliance_id', 'character_name')
|
||||
|
||||
for character in characters:
|
||||
character_id = character.get('character_id')
|
||||
if character_id in affiliations:
|
||||
affiliation = affiliations[character_id]
|
||||
|
||||
corp_changed = (
|
||||
character.get('corporation_id') != affiliation.get('corporation_id')
|
||||
)
|
||||
|
||||
alliance_id = character.get('alliance_id')
|
||||
if not alliance_id:
|
||||
alliance_id = None
|
||||
alliance_changed = alliance_id != affiliation.get('alliance_id')
|
||||
|
||||
name_changed = False
|
||||
fetched_name = affiliation.get('name', False)
|
||||
if fetched_name:
|
||||
name_changed = character.get('character_name') != fetched_name
|
||||
|
||||
if corp_changed or alliance_changed or name_changed:
|
||||
update_character.apply_async(
|
||||
args=[character.get('character_id')], priority=TASK_PRIORITY
|
||||
)
|
||||
|
||||
@@ -592,3 +592,12 @@ class TestEveSwaggerProvider(TestCase):
|
||||
self.assertTrue(mock_esi_client_factory.called)
|
||||
self.assertIsNotNone(my_provider._client)
|
||||
self.assertEqual(my_client, 'my_client')
|
||||
|
||||
@patch(MODULE_PATH + '.__version__', '1.0.0')
|
||||
def test_user_agent_header(self):
|
||||
my_provider = EveSwaggerProvider()
|
||||
my_client = my_provider.client
|
||||
operation = my_client.Status.get_status()
|
||||
self.assertEqual(
|
||||
operation.future.request.headers['User-Agent'], 'allianceauth v1.0.0'
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import patch, Mock
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
@@ -44,55 +44,202 @@ class TestTasks(TestCase):
|
||||
mock_EveCharacter.objects.update_character.call_args[0][0], 42
|
||||
)
|
||||
|
||||
@patch('allianceauth.eveonline.tasks.update_character')
|
||||
@patch('allianceauth.eveonline.tasks.update_alliance')
|
||||
@patch('allianceauth.eveonline.tasks.update_corp')
|
||||
def test_run_model_update(
|
||||
self,
|
||||
mock_update_corp,
|
||||
mock_update_alliance,
|
||||
mock_update_character,
|
||||
):
|
||||
|
||||
@patch('allianceauth.eveonline.tasks.update_character')
|
||||
@patch('allianceauth.eveonline.tasks.update_alliance')
|
||||
@patch('allianceauth.eveonline.tasks.update_corp')
|
||||
@patch('allianceauth.eveonline.providers.provider')
|
||||
@patch('allianceauth.eveonline.tasks.CHUNK_SIZE', 2)
|
||||
class TestRunModelUpdate(TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
EveCorporationInfo.objects.all().delete()
|
||||
EveAllianceInfo.objects.all().delete()
|
||||
EveCharacter.objects.all().delete()
|
||||
|
||||
|
||||
EveCorporationInfo.objects.create(
|
||||
corporation_id=2345,
|
||||
corporation_name='corp.name',
|
||||
corporation_ticker='corp.ticker',
|
||||
corporation_ticker='c.c.t',
|
||||
member_count=10,
|
||||
alliance=None,
|
||||
)
|
||||
EveAllianceInfo.objects.create(
|
||||
alliance_id=3456,
|
||||
alliance_name='alliance.name',
|
||||
alliance_ticker='alliance.ticker',
|
||||
executor_corp_id='78910',
|
||||
alliance_ticker='a.t',
|
||||
executor_corp_id=5,
|
||||
)
|
||||
EveCharacter.objects.create(
|
||||
character_id=1,
|
||||
character_name='character.name1',
|
||||
corporation_id=2345,
|
||||
corporation_name='character.corp.name',
|
||||
corporation_ticker='c.c.t', # max 5 chars
|
||||
alliance_id=None
|
||||
)
|
||||
EveCharacter.objects.create(
|
||||
character_id=1234,
|
||||
character_name='character.name',
|
||||
corporation_id=2345,
|
||||
character_id=2,
|
||||
character_name='character.name2',
|
||||
corporation_id=9876,
|
||||
corporation_name='character.corp.name',
|
||||
corporation_ticker='c.c.t', # max 5 chars
|
||||
alliance_id=3456,
|
||||
alliance_name='character.alliance.name',
|
||||
)
|
||||
EveCharacter.objects.create(
|
||||
character_id=3,
|
||||
character_name='character.name3',
|
||||
corporation_id=9876,
|
||||
corporation_name='character.corp.name',
|
||||
corporation_ticker='c.c.t', # max 5 chars
|
||||
alliance_id=3456,
|
||||
alliance_name='character.alliance.name',
|
||||
)
|
||||
EveCharacter.objects.create(
|
||||
character_id=4,
|
||||
character_name='character.name4',
|
||||
corporation_id=9876,
|
||||
corporation_name='character.corp.name',
|
||||
corporation_ticker='c.c.t', # max 5 chars
|
||||
alliance_id=3456,
|
||||
alliance_name='character.alliance.name',
|
||||
)
|
||||
"""
|
||||
EveCharacter.objects.create(
|
||||
character_id=5,
|
||||
character_name='character.name5',
|
||||
corporation_id=9876,
|
||||
corporation_name='character.corp.name',
|
||||
corporation_ticker='c.c.t', # max 5 chars
|
||||
alliance_id=3456,
|
||||
alliance_name='character.alliance.name',
|
||||
)
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.affiliations = [
|
||||
{'character_id': 1, 'corporation_id': 5},
|
||||
{'character_id': 2, 'corporation_id': 9876, 'alliance_id': 3456},
|
||||
{'character_id': 3, 'corporation_id': 9876, 'alliance_id': 7456},
|
||||
{'character_id': 4, 'corporation_id': 9876, 'alliance_id': 3456}
|
||||
]
|
||||
self.names = [
|
||||
{'id': 1, 'name': 'character.name1'},
|
||||
{'id': 2, 'name': 'character.name2'},
|
||||
{'id': 3, 'name': 'character.name3'},
|
||||
{'id': 4, 'name': 'character.name4_new'}
|
||||
]
|
||||
|
||||
def test_normal_run(
|
||||
self,
|
||||
mock_provider,
|
||||
mock_update_corp,
|
||||
mock_update_alliance,
|
||||
mock_update_character,
|
||||
):
|
||||
def get_affiliations(characters: list):
|
||||
response = [x for x in self.affiliations if x['character_id'] in characters]
|
||||
mock_operator = Mock(**{'result.return_value': response})
|
||||
return mock_operator
|
||||
|
||||
def get_names(ids: list):
|
||||
response = [x for x in self.names if x['id'] in ids]
|
||||
mock_operator = Mock(**{'result.return_value': response})
|
||||
return mock_operator
|
||||
|
||||
mock_provider.client.Character.post_characters_affiliation.side_effect \
|
||||
= get_affiliations
|
||||
|
||||
mock_provider.client.Universe.post_universe_names.side_effect = get_names
|
||||
|
||||
run_model_update()
|
||||
|
||||
self.assertEqual(
|
||||
mock_provider.client.Character.post_characters_affiliation.call_count, 2
|
||||
)
|
||||
self.assertEqual(
|
||||
mock_provider.client.Universe.post_universe_names.call_count, 2
|
||||
)
|
||||
|
||||
# character 1 has changed corp
|
||||
# character 2 no change
|
||||
# character 3 has changed alliance
|
||||
# character 4 has changed name
|
||||
self.assertEqual(mock_update_corp.apply_async.call_count, 1)
|
||||
self.assertEqual(
|
||||
int(mock_update_corp.apply_async.call_args[1]['args'][0]), 2345
|
||||
)
|
||||
|
||||
self.assertEqual(mock_update_alliance.apply_async.call_count, 1)
|
||||
self.assertEqual(
|
||||
int(mock_update_alliance.apply_async.call_args[1]['args'][0]), 3456
|
||||
)
|
||||
)
|
||||
characters_updated = {
|
||||
x[1]['args'][0] for x in mock_update_character.apply_async.call_args_list
|
||||
}
|
||||
excepted = {1, 3, 4}
|
||||
self.assertSetEqual(characters_updated, excepted)
|
||||
|
||||
def test_ignore_character_not_in_affiliations(
|
||||
self,
|
||||
mock_provider,
|
||||
mock_update_corp,
|
||||
mock_update_alliance,
|
||||
mock_update_character,
|
||||
):
|
||||
def get_affiliations(characters: list):
|
||||
response = [x for x in self.affiliations if x['character_id'] in characters]
|
||||
mock_operator = Mock(**{'result.return_value': response})
|
||||
return mock_operator
|
||||
|
||||
def get_names(ids: list):
|
||||
response = [x for x in self.names if x['id'] in ids]
|
||||
mock_operator = Mock(**{'result.return_value': response})
|
||||
return mock_operator
|
||||
|
||||
del self.affiliations[0]
|
||||
|
||||
mock_provider.client.Character.post_characters_affiliation.side_effect \
|
||||
= get_affiliations
|
||||
|
||||
mock_provider.client.Universe.post_universe_names.side_effect = get_names
|
||||
|
||||
self.assertEqual(mock_update_character.apply_async.call_count, 1)
|
||||
self.assertEqual(
|
||||
int(mock_update_character.apply_async.call_args[1]['args'][0]), 1234
|
||||
)
|
||||
run_model_update()
|
||||
characters_updated = {
|
||||
x[1]['args'][0] for x in mock_update_character.apply_async.call_args_list
|
||||
}
|
||||
excepted = {3, 4}
|
||||
self.assertSetEqual(characters_updated, excepted)
|
||||
|
||||
def test_ignore_character_not_in_names(
|
||||
self,
|
||||
mock_provider,
|
||||
mock_update_corp,
|
||||
mock_update_alliance,
|
||||
mock_update_character,
|
||||
):
|
||||
def get_affiliations(characters: list):
|
||||
response = [x for x in self.affiliations if x['character_id'] in characters]
|
||||
mock_operator = Mock(**{'result.return_value': response})
|
||||
return mock_operator
|
||||
|
||||
def get_names(ids: list):
|
||||
response = [x for x in self.names if x['id'] in ids]
|
||||
mock_operator = Mock(**{'result.return_value': response})
|
||||
return mock_operator
|
||||
|
||||
del self.names[3]
|
||||
|
||||
mock_provider.client.Character.post_characters_affiliation.side_effect \
|
||||
= get_affiliations
|
||||
|
||||
mock_provider.client.Universe.post_universe_names.side_effect = get_names
|
||||
|
||||
run_model_update()
|
||||
characters_updated = {
|
||||
x[1]['args'][0] for x in mock_update_character.apply_async.call_args_list
|
||||
}
|
||||
excepted = {1, 3}
|
||||
self.assertSetEqual(characters_updated, excepted)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Create Fatlink" %}{% endblock page_title %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% block page_title %}{% trans "Fatlink view" %}{% endblock page_title %}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Personal fatlink statistics" %}{% endblock page_title %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Personal fatlink statistics" %}{% endblock page_title %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Fatlink Corp Statistics" %}{% endblock page_title %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Fatlink statistics" %}{% endblock page_title %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Fatlink view" %}{% endblock page_title %}
|
||||
|
||||
@@ -41,7 +41,7 @@ class AuthGroupInlineAdmin(admin.StackedInline):
|
||||
kwargs["queryset"] = Group.objects.order_by(Lower('name'))
|
||||
return super().formfield_for_manytomany(db_field, request, **kwargs)
|
||||
|
||||
def has_add_permission(self, request):
|
||||
def has_add_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
def has_delete_permission(self, request, obj=None):
|
||||
|
||||
43
allianceauth/groupmanagement/auth_hooks.py
Normal file
43
allianceauth/groupmanagement/auth_hooks.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from allianceauth.services.hooks import MenuItemHook, UrlHook
|
||||
from allianceauth import hooks
|
||||
|
||||
from . import urls
|
||||
from .managers import GroupManager
|
||||
|
||||
|
||||
class GroupManagementMenuItem(MenuItemHook):
|
||||
""" This class ensures only authorized users will see the menu entry """
|
||||
|
||||
def __init__(self):
|
||||
# setup menu entry for sidebar
|
||||
MenuItemHook.__init__(
|
||||
self,
|
||||
text=_("Group Management"),
|
||||
classes="fas fa-users-cog fa-fw",
|
||||
url_name="groupmanagement:management",
|
||||
order=50,
|
||||
navactive=[
|
||||
"groupmanagement:management", # group requests view
|
||||
"groupmanagement:membership", # group membership view
|
||||
"groupmanagement:audit_log", # group audit log view
|
||||
],
|
||||
)
|
||||
|
||||
def render(self, request):
|
||||
if GroupManager.can_manage_groups(request.user):
|
||||
app_count = GroupManager.pending_requests_count_for_user(request.user)
|
||||
self.count = app_count if app_count and app_count > 0 else None
|
||||
return MenuItemHook.render(self, request)
|
||||
return ""
|
||||
|
||||
|
||||
@hooks.register("menu_item_hook")
|
||||
def register_menu():
|
||||
return GroupManagementMenuItem()
|
||||
|
||||
|
||||
@hooks.register("url_hook")
|
||||
def register_urls():
|
||||
return UrlHook(urls, "group", r"^groups/")
|
||||
@@ -4,6 +4,7 @@ from django.contrib.auth.models import Group, User
|
||||
from django.db.models import Q, QuerySet
|
||||
|
||||
from allianceauth.authentication.models import State
|
||||
from .models import GroupRequest
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -101,3 +102,18 @@ class GroupManager:
|
||||
if user.is_authenticated:
|
||||
return cls.has_management_permission(user) or cls.get_group_leaders_groups(user).filter(pk=group.pk).exists()
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def pending_requests_count_for_user(cls, user: User) -> int:
|
||||
"""Returns the number of pending group requests for the given user"""
|
||||
|
||||
if cls.has_management_permission(user):
|
||||
return GroupRequest.objects.filter(status="pending").count()
|
||||
else:
|
||||
return (
|
||||
GroupRequest.objects
|
||||
.filter(status="pending")
|
||||
.filter(group__authgroup__group_leaders__exact=user)
|
||||
.select_related("group__authgroup__group_leaders")
|
||||
.count()
|
||||
)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.1.1 on 2020-09-18 14:12
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('groupmanagement', '0013_fix_requestlog_date_field'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='requestlog',
|
||||
name='request_type',
|
||||
field=models.BooleanField(null=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,22 @@
|
||||
# Generated by Django 3.1.2 on 2020-10-25 11:09
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("groupmanagement", "0014_auto_20200918_1412"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="authgroup",
|
||||
name="description",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Short description <i>(max. 512 characters)</i> of the group shown to users.",
|
||||
max_length=512,
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -4,7 +4,6 @@ from django.db import models
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from allianceauth.authentication.models import State
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class GroupRequest(models.Model):
|
||||
@@ -26,7 +25,7 @@ class GroupRequest(models.Model):
|
||||
|
||||
|
||||
class RequestLog(models.Model):
|
||||
request_type = models.NullBooleanField(default=0)
|
||||
request_type = models.BooleanField(null=True)
|
||||
group = models.ForeignKey(Group, on_delete=models.CASCADE)
|
||||
request_info = models.CharField(max_length=254)
|
||||
action = models.BooleanField(default=0)
|
||||
@@ -108,7 +107,7 @@ class AuthGroup(models.Model):
|
||||
help_text="States listed here will have the ability to join this group provided "
|
||||
"they have the proper permissions.")
|
||||
|
||||
description = models.CharField(max_length=512, blank=True, help_text="Description of the group shown to users.")
|
||||
description = models.TextField(max_length=512, blank=True, help_text="Short description <i>(max. 512 characters)</i> of the group shown to users.")
|
||||
|
||||
def __str__(self):
|
||||
return self.group.name
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{{ group }} {% trans "Audit Log" %}{% endblock page_title %}
|
||||
@@ -8,65 +8,73 @@
|
||||
<div class="col-lg-12">
|
||||
<br>
|
||||
{% include 'groupmanagement/menu.html' %}
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
{{ group }} - {% trans 'Audit Log' %}
|
||||
{{ group }} - {% trans "Audit Log" %}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
<a class="btn btn-default" href="{% url 'groupmanagement:membership' %}" role="button">
|
||||
{% trans "Back" %}
|
||||
</a>
|
||||
</p>
|
||||
</p>
|
||||
|
||||
{% if entries %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped" id="log-entries">
|
||||
<thead>
|
||||
<th class="text-center" scope="col">{% trans "Date/Time" %}</th>
|
||||
<th class="text-center" scope="col">{% trans "Requestor" %}</th>
|
||||
<th class="text-center" scope="col">{% trans "Character" %}</th>
|
||||
<th class="text-center" scope="col">{% trans "Corporation" %}</th>
|
||||
<th class="text-center" scope="col">{% trans "Type" %}</th>
|
||||
<th class="text-center" scope="col">{% trans "Action" %}</th>
|
||||
<th class="text-center" scope="col">{% trans "Actor" %}</th>
|
||||
<th scope="col">{% trans "Date/Time" %}</th>
|
||||
<th scope="col">{% trans "Requestor" %}</th>
|
||||
<th scope="col">{% trans "Character" %}</th>
|
||||
<th scope="col">{% trans "Corporation" %}</th>
|
||||
<th scope="col">{% trans "Type" %}</th>
|
||||
<th scope="col">{% trans "Action" %}</th>
|
||||
<th scope="col">{% trans "Actor" %}</th>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for entry in entries %}
|
||||
<tr>
|
||||
<td class="text-center">{{ entry.date|date:"Y-M-d H:i" }}</td>
|
||||
<td class="text-center">{{ entry.requestor }}</td>
|
||||
<td class="text-center">{{ entry.req_char }}</td>
|
||||
<td class="text-center">{{ entry.req_char.corporation_name }}</td>
|
||||
<td class="text-center">{{ entry.type_to_str }}</td>
|
||||
<td>{{ entry.date|date:"Y-M-d, H:i" }}</td>
|
||||
<td>{{ entry.requestor }}</td>
|
||||
<td>{{ entry.req_char }}</td>
|
||||
<td>{{ entry.req_char.corporation_name }}</td>
|
||||
<td>{{ entry.type_to_str }}</td>
|
||||
|
||||
{% if entry.request_type is None %}
|
||||
<td class="text-center"> Removed</td>
|
||||
<td>{% trans "Removed" %}</td>
|
||||
{% else %}
|
||||
<td class="text-center">{{ entry.action_to_str }}</td>
|
||||
<td>{{ entry.action_to_str }}</td>
|
||||
{% endif %}
|
||||
<td class="text-center">{{ entry.request_actor }}</td>
|
||||
|
||||
<td>{{ entry.request_actor }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p class="text-muted">
|
||||
All times displayed are EVE/UTC.
|
||||
{% trans "All times displayed are EVE/UTC." %}
|
||||
</p>
|
||||
</div>
|
||||
{% else %}
|
||||
{% else %}
|
||||
<div class="clearfix"></div>
|
||||
<br>
|
||||
<div class="alert alert-warning text-center">
|
||||
<div class="alert alert-warning text-center">
|
||||
{% trans "No entries found for this group." %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_javascript %}
|
||||
{% include 'bundles/datatables-js.html' %}
|
||||
<script type="text/javascript" src="{% static 'js/filterDropDown/filterDropDown.min.js' %}"></script>
|
||||
{% include 'bundles/moment-js.html' with locale=True %}
|
||||
<script type="application/javascript" src="{% static 'js/filterDropDown/filterDropDown.min.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
@@ -74,12 +82,30 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_script %}
|
||||
$.fn.dataTable.moment = function(format, locale) {
|
||||
var types = $.fn.dataTable.ext.type;
|
||||
|
||||
// Add type detection
|
||||
types.detect.unshift(function(d) {
|
||||
return moment(d, format, locale, true).isValid() ?
|
||||
'moment-'+format :
|
||||
null;
|
||||
});
|
||||
|
||||
// Add sorting method - use an integer for the sorting
|
||||
types.order[ 'moment-'+format+'-pre' ] = function(d) {
|
||||
return moment(d, format, locale, true).unix();
|
||||
};
|
||||
};
|
||||
|
||||
$(document).ready(function(){
|
||||
$.fn.dataTable.moment('YYYY-MMM-D, HH:mm');
|
||||
|
||||
$('#log-entries').DataTable({
|
||||
order: [[ 0, 'desc' ], [ 1, 'asc' ] ],
|
||||
order: [[0, 'desc'], [1, 'asc']],
|
||||
filterDropDown:
|
||||
{
|
||||
columns: [
|
||||
columns: [
|
||||
{
|
||||
idx: 1
|
||||
},
|
||||
@@ -104,4 +130,3 @@
|
||||
});
|
||||
});
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load evelinks %}
|
||||
|
||||
@@ -9,38 +9,35 @@
|
||||
<div class="col-lg-12">
|
||||
<br>
|
||||
{% include 'groupmanagement/menu.html' %}
|
||||
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
{{ group.name }} - {% trans 'Members' %}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
<a class="btn btn-default" href="{% url 'groupmanagement:membership' %}" role="button">
|
||||
{% trans "Back" %}
|
||||
</a>
|
||||
</p>
|
||||
{% if group.user_set %}
|
||||
</p>
|
||||
|
||||
{% if group.user_set %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-aa" id="tab_group_members">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-right">{% trans "Portrait" %}</th>
|
||||
<th class="text-center">{% trans "Character" %}</th>
|
||||
<th class="text-center">{% trans "Organization" %}</th>
|
||||
<th class="text-center"></th>
|
||||
<tr>
|
||||
<th>{% trans "Character" %}</th>
|
||||
<th>{% trans "Organization" %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for member in members %}
|
||||
<tr>
|
||||
<td class="text-right">
|
||||
{% if member.is_leader %}
|
||||
<i class="fas fa-star"></i>
|
||||
{% endif %}
|
||||
<img src="{{ member.main_char|character_portrait_url:32 }}" class="img-circle">
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<tr>
|
||||
<td>
|
||||
<img src="{{ member.main_char|character_portrait_url:32 }}" class="img-circle" style="margin-right: 1rem;">
|
||||
{% if member.main_char %}
|
||||
<a href="{{ member.main_char|evewho_character_url }}" target="_blank">
|
||||
{{ member.main_char.character_name }}
|
||||
@@ -48,28 +45,36 @@
|
||||
{% else %}
|
||||
{{ member.user.username }}
|
||||
{% endif %}
|
||||
|
||||
{% if member.is_leader %}
|
||||
<i class="fas fa-star" title="{% trans "Group leader" %}" style="margin-left: 1rem;"></i>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
|
||||
<td>
|
||||
{% if member.main_char %}
|
||||
<a href="{{ member.main_char|dotlan_corporation_url }}" target="_blank">
|
||||
{{ member.main_char.corporation_name }}
|
||||
</a><br>
|
||||
{{ member.main_char.alliance_name|default_if_none:"" }}
|
||||
{% else %}
|
||||
(unknown)
|
||||
{% trans "(unknown)" %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<a href="{% url 'groupmanagement:membership_remove' group.id member.user.id %}" class="btn btn-danger"
|
||||
title="{% trans "Remove from group" %}">
|
||||
<i class="glyphicon glyphicon-remove"></i>
|
||||
</td>
|
||||
|
||||
<td class="text-right">
|
||||
<a href="{% url 'groupmanagement:membership_remove' group.id member.user.id %}" class="btn btn-danger" title="{% trans "Remove from group" %}">
|
||||
<i class="glyphicon glyphicon-remove"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="text-muted"><i class="fas fa-star"></i>: Group leader</p>
|
||||
|
||||
<p class="text-muted">
|
||||
<i class="fas fa-star"></i>: {% trans "Group leader" %}
|
||||
</p>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">
|
||||
@@ -77,7 +82,7 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
@@ -93,10 +98,13 @@
|
||||
{% block extra_script %}
|
||||
$(document).ready(function(){
|
||||
$('#tab_group_members').DataTable({
|
||||
order: [ [ 1, "asc" ] ],
|
||||
order: [[0, "asc"]],
|
||||
columnDefs: [
|
||||
{ "sortable": false, "targets": [0, 3] },
|
||||
{
|
||||
"sortable": false,
|
||||
"targets": [2]
|
||||
},
|
||||
]
|
||||
});
|
||||
});
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Groups Membership" %}{% endblock page_title %}
|
||||
@@ -9,31 +9,36 @@
|
||||
<div class="col-lg-12">
|
||||
<br>
|
||||
{% include 'groupmanagement/menu.html' %}
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
{% trans "Groups" %}
|
||||
</div>
|
||||
|
||||
<div class="panel-body">
|
||||
{% if groups %}
|
||||
{% if groups %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-aa">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">{% trans "Name" %}</th>
|
||||
<th class="text-center">{% trans "Description" %}</th>
|
||||
<th class="text-center">{% trans "Status" %}</th>
|
||||
<th class="text-center">{% trans "Member Count" %}</th>
|
||||
<th class="text-center"></th>
|
||||
<th>{% trans "Name" %}</th>
|
||||
<th>{% trans "Description" %}</th>
|
||||
<th>{% trans "Status" %}</th>
|
||||
<th style="white-space: nowrap;">{% trans "Member Count" %}</th>
|
||||
<th style="min-width: 170px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for group in groups %}
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
<a href="{% url 'groupmanagement:membership_list' group.id %}">{{ group.name }}</a>
|
||||
<td>
|
||||
<a href="{% url 'groupmanagement:membership' group.id %}">{{ group.name }}</a>
|
||||
</td>
|
||||
<td class="text-center">{{ group.authgroup.description }}</td>
|
||||
<td class="text-center">
|
||||
|
||||
<td>{{ group.authgroup.description|linebreaks|urlize }}</td>
|
||||
|
||||
<td>
|
||||
{% if group.authgroup.hidden %}
|
||||
<span class="label label-info">{% trans "Hidden" %}</span>
|
||||
{% elif group.authgroup.open %}
|
||||
@@ -42,21 +47,23 @@
|
||||
<span class="label label-default">{% trans "Requestable" %}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
|
||||
<td class="text-right">
|
||||
{{ group.num_members }}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<a href="{% url 'groupmanagement:membership_list' group.id %}" class="btn btn-primary"
|
||||
title="{% trans "View Members" %}">
|
||||
<i class="glyphicon glyphicon-eye-open"></i>
|
||||
|
||||
<td class="text-right">
|
||||
<a href="{% url 'groupmanagement:membership' group.id %}" class="btn btn-primary" title="{% trans "View Members" %}">
|
||||
<i class="glyphicon glyphicon-eye-open"></i>
|
||||
</a>
|
||||
|
||||
<a href="{% url "groupmanagement:audit_log" group.id %}" class="btn btn-info" title="{% trans "Audit Members" %}">
|
||||
<i class="glyphicon glyphicon-list-alt"></i>
|
||||
</a>
|
||||
|
||||
<a id="clipboard-copy" data-clipboard-text="{{ request.scheme }}://{{request.get_host}}{% url 'groupmanagement:request_add' group.id %}" class="btn btn-warning" title="{% trans "Copy Direct Join Link" %}">
|
||||
<i class="glyphicon glyphicon-copy"></i>
|
||||
</a>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -72,9 +79,11 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
{% block extra_javascript %}
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.4/clipboard.min.js"></script>
|
||||
<script>
|
||||
new ClipboardJS('#clipboard-copy');
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_javascript %}
|
||||
{% include 'bundles/clipboard-js.html' %}
|
||||
|
||||
<script>
|
||||
new ClipboardJS('#clipboard-copy');
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Available Groups" %}{% endblock page_title %}
|
||||
{% block extra_css %}{% endblock extra_css %}
|
||||
url
|
||||
|
||||
{% block content %}
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header text-center">{% trans "Available Groups" %}</h1>
|
||||
@@ -12,17 +12,18 @@ url
|
||||
<table class="table table-aa">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">{% trans "Name" %}</th>
|
||||
<th class="text-center">{% trans "Description" %}</th>
|
||||
<th class="text-center">{% trans "Action" %}</th>
|
||||
<th>{% trans "Name" %}</th>
|
||||
<th>{% trans "Description" %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for g in groups %}
|
||||
<tr>
|
||||
<td class="text-center">{{ g.group.name }}</td>
|
||||
<td class="text-center">{{ g.group.authgroup.description|urlize }}</td>
|
||||
<td class="text-center">
|
||||
<td>{{ g.group.name }}</td>
|
||||
<td>{{ g.group.authgroup.description|linebreaks|urlize }}</td>
|
||||
<td class="text-right">
|
||||
{% if g.group in user.groups.all %}
|
||||
{% if not g.request %}
|
||||
<a href="{% url 'groupmanagement:request_leave' g.group.id %}" class="btn btn-danger">
|
||||
@@ -59,5 +60,4 @@ url
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% endblock content %}
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load evelinks %}
|
||||
|
||||
{% block page_title %}{% trans "Groups Management" %}{% endblock page_title %}
|
||||
{% block extra_css %}
|
||||
<style>
|
||||
.nav-tabs>li.active>a {
|
||||
background-color: #ECF0F1 !important;
|
||||
color: #2C3E50;
|
||||
}
|
||||
</style>
|
||||
|
||||
{% 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">
|
||||
<li class="active">
|
||||
<a data-toggle="tab" href="#add">
|
||||
{% trans "Join Requests" %}
|
||||
{% trans "Join Requests" %}
|
||||
|
||||
{% if acceptrequests %}
|
||||
<span class="badge">{{ acceptrequests|length }}</span>
|
||||
{% endif %}
|
||||
@@ -31,133 +32,130 @@
|
||||
<li>
|
||||
<a data-toggle="tab" href="#leave">
|
||||
{% trans "Leave Requests" %}
|
||||
|
||||
{% if leaverequests %}
|
||||
<span class="badge">{{ leaverequests|length }}</span>
|
||||
{% endif %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
|
||||
<div class="tab-content">
|
||||
<div id="add" class="tab-pane fade in active panel panel-default">
|
||||
<div class="panel-body">
|
||||
{% if acceptrequests %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-aa">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center"></th>
|
||||
<th class="text-center">{% trans "Character" %}</th>
|
||||
<th class="text-center">{% trans "Organization" %}</th>
|
||||
<th class="text-center">{% trans "Group" %}</th>
|
||||
<th class="text-center"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for acceptrequest in acceptrequests %}
|
||||
<tr>
|
||||
<td class="text-right">
|
||||
<img src="{{ acceptrequest.main_char|character_portrait_url:32 }}" class="img-circle">
|
||||
</td>
|
||||
<td class="text-center">
|
||||
{% if acceptrequest.main_char %}
|
||||
<a href="{{ acceptrequest.main_char|evewho_character_url }}" target="_blank">
|
||||
{{ acceptrequest.main_char.character_name }}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ acceptrequest.user.username }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
{% if acceptrequest.main_char %}
|
||||
<a href="{{ acceptrequest.main_char|dotlan_corporation_url }}" target="_blank">
|
||||
{{ acceptrequest.main_char.corporation_name }}
|
||||
</a><br>
|
||||
{{ acceptrequest.main_char.alliance_name|default_if_none:"" }}
|
||||
{% else %}
|
||||
(unknown)
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-center">{{ acceptrequest.group.name }}</td>
|
||||
<td class="text-center">
|
||||
<a href="{% url 'groupmanagement:accept_request' acceptrequest.id %}" class="btn btn-success">
|
||||
{% trans "Accept" %}
|
||||
</a>
|
||||
<a href="{% url 'groupmanagement:reject_request' acceptrequest.id %}" class="btn btn-danger">
|
||||
{% trans "Reject" %}
|
||||
</a>
|
||||
</td>
|
||||
{% if acceptrequests %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-aa">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Character" %}</th>
|
||||
<th>{% trans "Organization" %}</th>
|
||||
<th>{% trans "Group" %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">{% trans "No group add requests." %}</div>
|
||||
{% endif %}
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for acceptrequest in acceptrequests %}
|
||||
<tr>
|
||||
<td>
|
||||
<img src="{{ acceptrequest.main_char|character_portrait_url:32 }}" class="img-circle" style="margin-right: 1rem;">
|
||||
{% if acceptrequest.main_char %}
|
||||
<a href="{{ acceptrequest.main_char|evewho_character_url }}" target="_blank">
|
||||
{{ acceptrequest.main_char.character_name }}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ acceptrequest.user.username }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if acceptrequest.main_char %}
|
||||
<a href="{{ acceptrequest.main_char|dotlan_corporation_url }}" target="_blank">
|
||||
{{ acceptrequest.main_char.corporation_name }}
|
||||
</a><br>
|
||||
{{ acceptrequest.main_char.alliance_name|default_if_none:"" }}
|
||||
{% else %}
|
||||
{% trans "(unknown)" %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ acceptrequest.group.name }}</td>
|
||||
<td class="text-right">
|
||||
<a href="{% url 'groupmanagement:accept_request' acceptrequest.id %}" class="btn btn-success">
|
||||
{% trans "Accept" %}
|
||||
</a>
|
||||
|
||||
<a href="{% url 'groupmanagement:reject_request' acceptrequest.id %}" class="btn btn-danger">
|
||||
{% trans "Reject" %}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">{% trans "No group add requests." %}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="leave" class="tab-pane fade panel panel-default">
|
||||
<div class="panel-body">
|
||||
{% if leaverequests %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-aa">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center"></th>
|
||||
<th class="text-center">{% trans "Character" %}</th>
|
||||
<th class="text-center">{% trans "Organization" %}</th>
|
||||
<th class="text-center">{% trans "Group" %}</th>
|
||||
<th class="text-center"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for leaverequest in leaverequests %}
|
||||
<tr>
|
||||
<td class="text-right">
|
||||
<img src="{{ leaverequest.main_char|character_portrait_url:32 }}" class="img-circle">
|
||||
</td>
|
||||
<td class="text-center">
|
||||
{% if leaverequest.main_char %}
|
||||
<a href="{{ leaverequest.main_char|evewho_character_url }}" target="_blank">
|
||||
{{ leaverequest.main_char.character_name }}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ leaverequest.user.username }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
{% if leaverequest.main_char %}
|
||||
<a href="{{ leaverequest.main_char|dotlan_corporation_url }}" target="_blank">
|
||||
{{ leaverequest.main_char.corporation_name }}
|
||||
</a><br>
|
||||
{{ leaverequest.main_char.alliance_name|default_if_none:"" }}
|
||||
{% else %}
|
||||
(unknown)
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-center">{{ leaverequest.group.name }}</td>
|
||||
<td class="text-center">
|
||||
<a href="{% url 'groupmanagement:leave_accept_request' leaverequest.id %}" class="btn btn-success">
|
||||
{% trans "Accept" %}
|
||||
</a>
|
||||
<a href="{% url 'groupmanagement:leave_reject_request' leaverequest.id %}" class="btn btn-danger">
|
||||
{% trans "Reject" %}
|
||||
</a>
|
||||
</td>
|
||||
{% if leaverequests %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-aa">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Character" %}</th>
|
||||
<th>{% trans "Organization" %}</th>
|
||||
<th>{% trans "Group" %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">{% trans "No group leave requests." %}</div>
|
||||
{% endif %}
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for leaverequest in leaverequests %}
|
||||
<tr>
|
||||
<td>
|
||||
<img src="{{ leaverequest.main_char|character_portrait_url:32 }}" class="img-circle" style="margin-right: 1rem;">
|
||||
{% if leaverequest.main_char %}
|
||||
<a href="{{ leaverequest.main_char|evewho_character_url }}" target="_blank">
|
||||
{{ leaverequest.main_char.character_name }}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ leaverequest.user.username }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if leaverequest.main_char %}
|
||||
<a href="{{ leaverequest.main_char|dotlan_corporation_url }}" target="_blank">
|
||||
{{ leaverequest.main_char.corporation_name }}
|
||||
</a><br>
|
||||
{{ leaverequest.main_char.alliance_name|default_if_none:"" }}
|
||||
{% else %}
|
||||
{% trans "(unknown)" %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ leaverequest.group.name }}</td>
|
||||
<td class="text-right">
|
||||
<a href="{% url 'groupmanagement:leave_accept_request' leaverequest.id %}" class="btn btn-success">
|
||||
{% trans "Accept" %}
|
||||
</a>
|
||||
|
||||
<a href="{% url 'groupmanagement:leave_reject_request' leaverequest.id %}" class="btn btn-danger">
|
||||
{% trans "Reject" %}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">{% trans "No group leave requests." %}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% 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">{% trans "Toggle navigation" %}</span>
|
||||
@@ -12,7 +11,7 @@
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="">{% trans "Group Management" %}</a>
|
||||
<a class="navbar-brand" href="{% url 'groupmanagement:management' %}">{% trans "Group Management" %}</a>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
@@ -20,11 +19,10 @@
|
||||
<li class="{% navactive request 'groupmanagement:management' %}">
|
||||
<a href="{% url 'groupmanagement:management' %}">{% trans "Group Requests" %}</a>
|
||||
</li>
|
||||
<li class="{% renavactive request '^/group/membership/' %}">
|
||||
<li class="{% navactive request 'groupmanagement:membership groupmanagement:audit_log' %}">
|
||||
<a href="{% url 'groupmanagement:membership' %}">{% trans "Group Membership" %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
from django import template
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
from allianceauth.groupmanagement.managers import GroupManager
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter
|
||||
def can_manage_groups(user: User) -> bool:
|
||||
"""returns True if the given user can manage groups. Returns False otherwise."""
|
||||
if not isinstance(user, User):
|
||||
return False
|
||||
return GroupManager.can_manage_groups(user)
|
||||
@@ -7,7 +7,7 @@ from django.urls import reverse
|
||||
from allianceauth.eveonline.models import EveCorporationInfo, EveAllianceInfo
|
||||
from allianceauth.tests.auth_utils import AuthUtils
|
||||
|
||||
from ..models import AuthGroup
|
||||
from ..models import GroupRequest
|
||||
from ..managers import GroupManager
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ class MockUserNotAuthenticated():
|
||||
def __init__(self):
|
||||
self.is_authenticated = False
|
||||
|
||||
|
||||
class GroupManagementVisibilityTestCase(TestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
@@ -37,22 +38,20 @@ class GroupManagementVisibilityTestCase(TestCase):
|
||||
def _refresh_user(self):
|
||||
self.user = User.objects.get(pk=self.user.pk)
|
||||
|
||||
|
||||
def test_get_group_leaders_groups(self):
|
||||
self.group1.authgroup.group_leaders.add(self.user)
|
||||
self.group2.authgroup.group_leader_groups.add(self.group1)
|
||||
self._refresh_user()
|
||||
groups = GroupManager.get_group_leaders_groups(self.user)
|
||||
|
||||
self.assertIn(self.group1, groups) #avail due to user
|
||||
self.assertNotIn(self.group2, groups) #not avail due to group
|
||||
self.assertNotIn(self.group3, groups) #not avail at all
|
||||
self.assertIn(self.group1, groups) #avail due to user
|
||||
self.assertNotIn(self.group2, groups) #not avail due to group
|
||||
self.assertNotIn(self.group3, groups) #not avail at all
|
||||
|
||||
self.user.groups.add(self.group1)
|
||||
self._refresh_user()
|
||||
groups = GroupManager.get_group_leaders_groups(self.user)
|
||||
|
||||
|
||||
def test_can_manage_group(self):
|
||||
self.group1.authgroup.group_leaders.add(self.user)
|
||||
self.user.groups.add(self.group1)
|
||||
@@ -182,7 +181,6 @@ class TestGroupManager(TestCase):
|
||||
]:
|
||||
self.assertFalse(GroupManager.joinable_group(x, member_state))
|
||||
|
||||
|
||||
def test_joinable_group_guest(self):
|
||||
guest_state = AuthUtils.get_guest_state()
|
||||
for x in [
|
||||
@@ -200,7 +198,6 @@ class TestGroupManager(TestCase):
|
||||
]:
|
||||
self.assertFalse(GroupManager.joinable_group(x, guest_state))
|
||||
|
||||
|
||||
def test_get_all_non_internal_groups(self):
|
||||
result = GroupManager.get_all_non_internal_groups()
|
||||
expected = {
|
||||
@@ -224,7 +221,7 @@ class TestGroupManager(TestCase):
|
||||
def test_get_joinable_groups_for_user_no_permission(self):
|
||||
AuthUtils.assign_state(self.user, AuthUtils.get_guest_state())
|
||||
result = GroupManager.get_joinable_groups_for_user(self.user)
|
||||
expected= {self.group_public_1, self.group_public_2}
|
||||
expected = {self.group_public_1, self.group_public_2}
|
||||
self.assertSetEqual(set(result), expected)
|
||||
|
||||
def test_get_joinable_groups_for_user_guest_w_permission_(self):
|
||||
@@ -335,3 +332,96 @@ class TestGroupManager(TestCase):
|
||||
self.assertFalse(
|
||||
GroupManager.can_manage_group(user, self.group_default)
|
||||
)
|
||||
|
||||
|
||||
class TestPendingRequestsCountForUser(TestCase):
|
||||
|
||||
def setUp(self) -> None:
|
||||
self.group_1 = Group.objects.create(name="Group 1")
|
||||
self.group_2 = Group.objects.create(name="Group 2")
|
||||
self.user_leader_1 = AuthUtils.create_member('Clark Kent')
|
||||
self.group_1.authgroup.group_leaders.add(self.user_leader_1)
|
||||
self.user_leader_2 = AuthUtils.create_member('Peter Parker')
|
||||
self.group_2.authgroup.group_leaders.add(self.user_leader_2)
|
||||
self.user_requestor = AuthUtils.create_member('Bruce Wayne')
|
||||
|
||||
def test_single_request_for_leader(self):
|
||||
# given user_leader_1 is leader of group_1
|
||||
# and user_leader_2 is leader of group_2
|
||||
# when user_requestor is requesting access to group 1
|
||||
# then return 1 for user_leader 1 and 0 for user_leader_2
|
||||
GroupRequest.objects.create(
|
||||
status="pending", user=self.user_requestor, group=self.group_1
|
||||
)
|
||||
self.assertEqual(
|
||||
GroupManager.pending_requests_count_for_user(self.user_leader_1), 1
|
||||
)
|
||||
self.assertEqual(
|
||||
GroupManager.pending_requests_count_for_user(self.user_leader_2), 0
|
||||
)
|
||||
|
||||
def test_return_none_for_none_leader(self):
|
||||
# given user_requestor is leader of no group
|
||||
# when user_requestor is requesting access to group 1
|
||||
# then return 0 for user_requestor
|
||||
GroupRequest.objects.create(
|
||||
status="pending", user=self.user_requestor, group=self.group_1
|
||||
)
|
||||
self.assertEqual(
|
||||
GroupManager.pending_requests_count_for_user(self.user_requestor), 0
|
||||
)
|
||||
|
||||
def test_single_leave_request(self):
|
||||
# given user_leader_2 is leader of group_2
|
||||
# and user_requestor is member of group 2
|
||||
# when user_requestor is requesting to leave group 2
|
||||
# then return 1 for user_leader_2
|
||||
self.user_requestor.groups.add(self.group_2)
|
||||
|
||||
GroupRequest.objects.create(
|
||||
status="pending",
|
||||
user=self.user_requestor,
|
||||
group=self.group_2,
|
||||
leave_request=True
|
||||
)
|
||||
self.assertEqual(
|
||||
GroupManager.pending_requests_count_for_user(self.user_leader_2), 1
|
||||
)
|
||||
|
||||
def test_join_and_leave_request(self):
|
||||
# given user_leader_2 is leader of group_2
|
||||
# and user_requestor is member of group 2
|
||||
# when user_requestor is requesting to leave group 2
|
||||
# and user_requestor_2 is requesting to join group 2
|
||||
# then return 2 for user_leader_2
|
||||
self.user_requestor.groups.add(self.group_2)
|
||||
user_requestor_2 = AuthUtils.create_member("Lex Luther")
|
||||
GroupRequest.objects.create(
|
||||
status="pending",
|
||||
user=user_requestor_2,
|
||||
group=self.group_2
|
||||
)
|
||||
GroupRequest.objects.create(
|
||||
status="pending",
|
||||
user=self.user_requestor,
|
||||
group=self.group_2,
|
||||
leave_request=True
|
||||
)
|
||||
self.assertEqual(
|
||||
GroupManager.pending_requests_count_for_user(self.user_leader_2), 2
|
||||
)
|
||||
|
||||
def test_single_request_for_user_with_management_perm(self):
|
||||
# given user_leader_4 which is leafer of no group
|
||||
# but has the management permissions
|
||||
# when user_requestor is requesting access to group 1
|
||||
# then return 1 for user_leader_4
|
||||
user_leader_4 = AuthUtils.create_member("Lex Luther")
|
||||
AuthUtils.add_permission_to_user_by_name("auth.group_management", user_leader_4)
|
||||
user_leader_4 = User.objects.get(pk=user_leader_4.pk)
|
||||
GroupRequest.objects.create(
|
||||
status="pending", user=self.user_requestor, group=self.group_1
|
||||
)
|
||||
self.assertEqual(
|
||||
GroupManager.pending_requests_count_for_user(self.user_leader_1), 1
|
||||
)
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.test import TestCase
|
||||
from allianceauth.tests.auth_utils import AuthUtils
|
||||
|
||||
from ..templatetags.groupmanagement import can_manage_groups
|
||||
|
||||
MODULE_PATH = 'allianceauth.groupmanagement.templatetags.groupmanagement'
|
||||
|
||||
|
||||
@patch(MODULE_PATH + '.GroupManager.can_manage_groups')
|
||||
class TestCanManageGroups(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.user = AuthUtils.create_user('Bruce Wayne')
|
||||
|
||||
def test_return_normal_result(self, mock_can_manage_groups):
|
||||
mock_can_manage_groups.return_value = True
|
||||
|
||||
self.assertTrue(can_manage_groups(self.user))
|
||||
self.assertTrue(mock_can_manage_groups.called)
|
||||
|
||||
def test_return_false_if_not_user(self, mock_can_manage_groups):
|
||||
mock_can_manage_groups.return_value = True
|
||||
|
||||
self.assertFalse(can_manage_groups('invalid'))
|
||||
self.assertFalse(mock_can_manage_groups.called)
|
||||
@@ -1,32 +1,52 @@
|
||||
from . import views
|
||||
|
||||
from django.conf.urls import include, url
|
||||
app_name = 'groupmanagement'
|
||||
from django.conf.urls import url
|
||||
|
||||
app_name = "groupmanagement"
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^groups/', views.groups_view, name='groups'),
|
||||
url(r'^group/', include([
|
||||
url(r'^management/', views.group_management,
|
||||
name='management'),
|
||||
url(r'^membership/$', views.group_membership,
|
||||
name='membership'),
|
||||
url(r'^membership/(\w+)/$', views.group_membership_list,
|
||||
name='membership_list'),
|
||||
url(r'^membership/(\w+)/audit/$', views.group_membership_audit, name="audit_log"),
|
||||
url(r'^membership/(\w+)/remove/(\w+)/$', views.group_membership_remove,
|
||||
name='membership_remove'),
|
||||
url(r'^request_add/(\w+)', views.group_request_add,
|
||||
name='request_add'),
|
||||
url(r'^request/accept/(\w+)', views.group_accept_request,
|
||||
name='accept_request'),
|
||||
url(r'^request/reject/(\w+)', views.group_reject_request,
|
||||
name='reject_request'),
|
||||
|
||||
url(r'^request_leave/(\w+)', views.group_request_leave,
|
||||
name='request_leave'),
|
||||
url(r'leave_request/accept/(\w+)', views.group_leave_accept_request,
|
||||
name='leave_accept_request'),
|
||||
url(r'^leave_request/reject/(\w+)', views.group_leave_reject_request,
|
||||
name='leave_reject_request'),
|
||||
])),
|
||||
# groups
|
||||
url(r"^groups/$", views.groups_view, name="groups"),
|
||||
url(r"^group/request/join/(\w+)/$", views.group_request_add, name="request_add"),
|
||||
url(
|
||||
r"^group/request/leave/(\w+)/$", views.group_request_leave, name="request_leave"
|
||||
),
|
||||
# group management
|
||||
url(r"^groupmanagement/requests/$", views.group_management, name="management"),
|
||||
url(r"^groupmanagement/membership/$", views.group_membership, name="membership"),
|
||||
url(
|
||||
r"^groupmanagement/membership/(\w+)/$",
|
||||
views.group_membership_list,
|
||||
name="membership",
|
||||
),
|
||||
url(
|
||||
r"^groupmanagement/membership/(\w+)/audit-log/$",
|
||||
views.group_membership_audit,
|
||||
name="audit_log",
|
||||
),
|
||||
url(
|
||||
r"^groupmanagement/membership/(\w+)/remove/(\w+)/$",
|
||||
views.group_membership_remove,
|
||||
name="membership_remove",
|
||||
),
|
||||
url(
|
||||
r"^groupmanagement/request/join/accept/(\w+)/$",
|
||||
views.group_accept_request,
|
||||
name="accept_request",
|
||||
),
|
||||
url(
|
||||
r"^groupmanagement/request/join/reject/(\w+)/$",
|
||||
views.group_reject_request,
|
||||
name="reject_request",
|
||||
),
|
||||
url(
|
||||
r"^groupmanagement/request/leave/accept/(\w+)/$",
|
||||
views.group_leave_accept_request,
|
||||
name="leave_accept_request",
|
||||
),
|
||||
url(
|
||||
r"^groupmanagement/request/leave/reject/(\w+)/$",
|
||||
views.group_leave_reject_request,
|
||||
name="leave_reject_request",
|
||||
),
|
||||
]
|
||||
|
||||
@@ -103,7 +103,7 @@ def group_membership_list(request, group_id):
|
||||
|
||||
# Check its a joinable group i.e. not corp or internal
|
||||
# And the user has permission to manage it
|
||||
if (not GroupManager.check_internal_group(group)
|
||||
if (not GroupManager.check_internal_group(group)
|
||||
or not GroupManager.can_manage_group(request.user, group)
|
||||
):
|
||||
logger.warning(
|
||||
@@ -132,7 +132,7 @@ def group_membership_list(request, group_id):
|
||||
render_items = {'group': group, 'members': members}
|
||||
|
||||
return render(
|
||||
request, 'groupmanagement/groupmembers.html',
|
||||
request, 'groupmanagement/groupmembers.html',
|
||||
context=render_items
|
||||
)
|
||||
|
||||
@@ -166,7 +166,7 @@ def group_membership_remove(request, group_id, user_id):
|
||||
except ObjectDoesNotExist:
|
||||
messages.warning(request, _("Group does not exist"))
|
||||
|
||||
return redirect('groupmanagement:membership_list', group_id)
|
||||
return redirect('groupmanagement:membership', group_id)
|
||||
|
||||
|
||||
@login_required
|
||||
@@ -312,18 +312,18 @@ def group_leave_reject_request(request, group_request_id):
|
||||
@login_required
|
||||
def groups_view(request):
|
||||
logger.debug("groups_view called by user %s" % request.user)
|
||||
|
||||
|
||||
groups_qs = GroupManager.get_joinable_groups_for_user(
|
||||
request.user, include_hidden=False
|
||||
)
|
||||
groups_qs = groups_qs.order_by('name')
|
||||
groups = []
|
||||
for group in groups_qs:
|
||||
for group in groups_qs:
|
||||
group_request = GroupRequest.objects\
|
||||
.filter(user=request.user)\
|
||||
.filter(group=group)
|
||||
groups.append({
|
||||
'group': group,
|
||||
'group': group,
|
||||
'request': group_request[0] if group_request else None
|
||||
})
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
from allianceauth.services.hooks import MenuItemHook, UrlHook
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from allianceauth import hooks
|
||||
from allianceauth.hrapplications import urls
|
||||
from allianceauth.services.hooks import MenuItemHook, UrlHook
|
||||
|
||||
from . import urls
|
||||
from .models import Application
|
||||
|
||||
|
||||
class ApplicationsMenu(MenuItemHook):
|
||||
@@ -12,6 +15,11 @@ class ApplicationsMenu(MenuItemHook):
|
||||
'hrapplications:index',
|
||||
navactive=['hrapplications:'])
|
||||
|
||||
def render(self, request):
|
||||
app_count = Application.objects.pending_requests_count_for_user(request.user)
|
||||
self.count = app_count if app_count and app_count > 0 else None
|
||||
return MenuItemHook.render(self, request)
|
||||
|
||||
|
||||
@hooks.register('menu_item_hook')
|
||||
def register_menu():
|
||||
|
||||
25
allianceauth/hrapplications/managers.py
Normal file
25
allianceauth/hrapplications/managers.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from django.contrib.auth.models import User
|
||||
from django.db import models
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class ApplicationManager(models.Manager):
|
||||
|
||||
def pending_requests_count_for_user(self, user: User) -> Optional[int]:
|
||||
"""Returns the number of pending group requests for the given user"""
|
||||
if user.is_superuser:
|
||||
return self.filter(approved__isnull=True).count()
|
||||
elif user.has_perm("auth.human_resources"):
|
||||
main_character = user.profile.main_character
|
||||
if main_character:
|
||||
return (
|
||||
self
|
||||
.select_related("form__corp")
|
||||
.filter(form__corp__corporation_id=main_character.corporation_id)
|
||||
.filter(approved__isnull=True)
|
||||
.count()
|
||||
)
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.1.1 on 2020-09-18 14:12
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('hrapplications', '0006_remove_legacy_models'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='application',
|
||||
name='approved',
|
||||
field=models.BooleanField(blank=True, default=None, null=True),
|
||||
),
|
||||
]
|
||||
@@ -2,8 +2,9 @@ from django.contrib.auth.models import User
|
||||
from django.db import models
|
||||
from sortedm2m.fields import SortedManyToManyField
|
||||
|
||||
from allianceauth.eveonline.models import EveCharacter
|
||||
from allianceauth.eveonline.models import EveCorporationInfo
|
||||
from allianceauth.eveonline.models import EveCharacter, EveCorporationInfo
|
||||
|
||||
from .managers import ApplicationManager
|
||||
|
||||
|
||||
class ApplicationQuestion(models.Model):
|
||||
@@ -22,6 +23,7 @@ class ApplicationChoice(models.Model):
|
||||
def __str__(self):
|
||||
return self.choice_text
|
||||
|
||||
|
||||
class ApplicationForm(models.Model):
|
||||
questions = SortedManyToManyField(ApplicationQuestion)
|
||||
corp = models.OneToOneField(EveCorporationInfo, on_delete=models.CASCADE)
|
||||
@@ -33,11 +35,13 @@ class ApplicationForm(models.Model):
|
||||
class Application(models.Model):
|
||||
form = models.ForeignKey(ApplicationForm, on_delete=models.CASCADE, related_name='applications')
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='applications')
|
||||
approved = models.NullBooleanField(blank=True, null=True, default=None)
|
||||
approved = models.BooleanField(blank=True, null=True, default=None)
|
||||
reviewer = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True)
|
||||
reviewer_character = models.ForeignKey(EveCharacter, on_delete=models.SET_NULL, blank=True, null=True)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
objects = ApplicationManager()
|
||||
|
||||
def __str__(self):
|
||||
return str(self.user) + " Application To " + str(self.form)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Choose a Corp" %}{% endblock page_title %}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Apply To" %} {{ corp.corporation_name }}{% endblock page_title %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "HR Application Management" %}{% endblock page_title %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}HR Application Management{% endblock page_title %}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load bootstrap %}
|
||||
{% load i18n %}
|
||||
|
||||
|
||||
@@ -1 +1,103 @@
|
||||
# Create your tests here.
|
||||
from django.contrib.auth.models import User
|
||||
from django.test import TestCase
|
||||
|
||||
from allianceauth.eveonline.models import EveCorporationInfo
|
||||
from allianceauth.tests.auth_utils import AuthUtils
|
||||
|
||||
from .models import Application, ApplicationForm, ApplicationQuestion, ApplicationChoice
|
||||
|
||||
|
||||
class TestApplicationManagersPendingRequestsCountForUser(TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.corporation_1 = EveCorporationInfo.objects.create(
|
||||
corporation_id=2001, corporation_name="Wayne Tech", member_count=42
|
||||
)
|
||||
self.corporation_2 = EveCorporationInfo.objects.create(
|
||||
corporation_id=2011, corporation_name="Lex Corp", member_count=666
|
||||
)
|
||||
question = ApplicationQuestion.objects.create(title="Dummy Question")
|
||||
ApplicationChoice.objects.create(question=question, choice_text="yes")
|
||||
ApplicationChoice.objects.create(question=question, choice_text="no")
|
||||
self.form_corporation_1 = ApplicationForm.objects.create(
|
||||
corp=self.corporation_1
|
||||
)
|
||||
self.form_corporation_1.questions.add(question)
|
||||
self.form_corporation_2 = ApplicationForm.objects.create(
|
||||
corp=self.corporation_2
|
||||
)
|
||||
self.form_corporation_2.questions.add(question)
|
||||
|
||||
self.user_requestor = AuthUtils.create_member("Peter Parker")
|
||||
|
||||
self.user_manager = AuthUtils.create_member("Bruce Wayne")
|
||||
AuthUtils.add_main_character_2(
|
||||
self.user_manager,
|
||||
self.user_manager.username,
|
||||
1001,
|
||||
self.corporation_1.corporation_id,
|
||||
self.corporation_1.corporation_name,
|
||||
)
|
||||
AuthUtils.add_permission_to_user_by_name(
|
||||
"auth.human_resources", self.user_manager
|
||||
)
|
||||
self.user_manager = User.objects.get(pk=self.user_manager.pk)
|
||||
|
||||
def test_no_pending_application(self):
|
||||
# given manager of corporation 1 has permission
|
||||
# when no application is pending for corporation 1
|
||||
# return 0
|
||||
self.assertEqual(
|
||||
Application.objects.pending_requests_count_for_user(self.user_manager), 0
|
||||
)
|
||||
|
||||
def test_single_pending_application(self):
|
||||
# given manager of corporation 1 has permission
|
||||
# when 1 application is pending for corporation 1
|
||||
# return 1
|
||||
Application.objects.create(
|
||||
form=self.form_corporation_1, user=self.user_requestor
|
||||
)
|
||||
self.assertEqual(
|
||||
Application.objects.pending_requests_count_for_user(self.user_manager), 1
|
||||
)
|
||||
|
||||
def test_user_has_no_permission(self):
|
||||
# given user has no permission
|
||||
# when 1 application is pending
|
||||
# return None
|
||||
self.assertIsNone(
|
||||
Application.objects.pending_requests_count_for_user(self.user_requestor)
|
||||
)
|
||||
|
||||
def test_two_pending_applications_for_different_corporations_normal_manager(self):
|
||||
# given manager of corporation 1 has permission
|
||||
# when 1 application is pending for corporation 1
|
||||
# and 1 application is pending for corporation 2
|
||||
# return 1
|
||||
Application.objects.create(
|
||||
form=self.form_corporation_1, user=self.user_requestor
|
||||
)
|
||||
Application.objects.create(
|
||||
form=self.form_corporation_2, user=self.user_requestor
|
||||
)
|
||||
self.assertEqual(
|
||||
Application.objects.pending_requests_count_for_user(self.user_manager), 1
|
||||
)
|
||||
|
||||
def test_two_pending_applications_for_different_corporations_manager_is_super(self):
|
||||
# given manager of corporation 1 has permission
|
||||
# when 1 application is pending for corporation 1
|
||||
# and 1 application is pending for corporation 2
|
||||
# return 1
|
||||
Application.objects.create(
|
||||
form=self.form_corporation_1, user=self.user_requestor
|
||||
)
|
||||
Application.objects.create(
|
||||
form=self.form_corporation_2, user=self.user_requestor
|
||||
)
|
||||
superuser = User.objects.create_superuser(
|
||||
"Superman", "superman@example.com", "password"
|
||||
)
|
||||
self.assertEqual(
|
||||
Application.objects.pending_requests_count_for_user(superuser), 2
|
||||
)
|
||||
|
||||
Binary file not shown.
@@ -6,16 +6,16 @@
|
||||
# Translators:
|
||||
# Erik Kalkoken <erik.kalkoken@gmail.com>, 2020
|
||||
# Joel Falknau <ozirascal@gmail.com>, 2020
|
||||
# Rounon Dax <rounon.dax@terra-nanotech.de>, 2020
|
||||
# Peter Pfeufer <rounon.dax@terra-nanotech.de>, 2020
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-07-29 04:56+0000\n"
|
||||
"POT-Creation-Date: 2020-10-11 03:43+0000\n"
|
||||
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
||||
"Last-Translator: Rounon Dax <rounon.dax@terra-nanotech.de>, 2020\n"
|
||||
"Last-Translator: Peter Pfeufer <rounon.dax@terra-nanotech.de>, 2020\n"
|
||||
"Language-Team: German (https://www.transifex.com/alliance-auth/teams/107430/de/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -28,7 +28,7 @@ msgid "A main character is required to perform that action. Add one below."
|
||||
msgstr ""
|
||||
"Für diese Aktion wird ein Hauptcharacter benötigt. Bitte füge einen hinzu."
|
||||
|
||||
#: allianceauth/authentication/forms.py:6
|
||||
#: allianceauth/authentication/forms.py:5
|
||||
msgid "Email"
|
||||
msgstr "E-Mail"
|
||||
|
||||
@@ -44,7 +44,7 @@ msgstr "Dein Nutzerstatus ist nun %(state)s"
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:5
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:8
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:12
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:11
|
||||
msgid "Dashboard"
|
||||
msgstr "Dashboard"
|
||||
|
||||
@@ -168,11 +168,11 @@ msgstr ""
|
||||
msgid "Unable to authenticate as the selected character."
|
||||
msgstr "Authentifizierung mit dem ausgewählten Charakter nicht möglich."
|
||||
|
||||
#: allianceauth/authentication/views.py:148
|
||||
#: allianceauth/authentication/views.py:146
|
||||
msgid "Registration token has expired."
|
||||
msgstr "Token zur Registrierung ist abgelaufen."
|
||||
|
||||
#: allianceauth/authentication/views.py:200
|
||||
#: allianceauth/authentication/views.py:201
|
||||
msgid ""
|
||||
"Sent confirmation email. Please follow the link to confirm your email "
|
||||
"address."
|
||||
@@ -180,12 +180,12 @@ msgstr ""
|
||||
"Bestätigungsmail gesendet. Bitte folge dem Link in der E-Mail zur "
|
||||
"Bestätigung."
|
||||
|
||||
#: allianceauth/authentication/views.py:205
|
||||
#: allianceauth/authentication/views.py:206
|
||||
msgid "Confirmed your email address. Please login to continue."
|
||||
msgstr ""
|
||||
"Deine E-Mail Adresse wurde bestätigt. Bitte log Dich ein um fortzufahren."
|
||||
|
||||
#: allianceauth/authentication/views.py:210
|
||||
#: allianceauth/authentication/views.py:211
|
||||
msgid "Registraion of new accounts it not allowed at this time."
|
||||
msgstr "Registrierung von neuen Konten ist zur Zeit nicht erlaubt."
|
||||
|
||||
@@ -552,6 +552,11 @@ msgstr "Flottenteilnahme registriert."
|
||||
msgid "FAT link has expired."
|
||||
msgstr "FAT-Link ist abgelaufen."
|
||||
|
||||
#: allianceauth/groupmanagement/auth_hooks.py:16
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
||||
msgid "Group Management"
|
||||
msgstr "Gruppenverwaltung"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
|
||||
msgid "Audit Log"
|
||||
@@ -624,7 +629,7 @@ msgstr "Gruppenmitgliedschaft"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
|
||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:17
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:16
|
||||
msgid "Groups"
|
||||
msgstr "Gruppen"
|
||||
|
||||
@@ -638,7 +643,7 @@ msgstr "Beschreibung"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:27
|
||||
#: allianceauth/srp/templates/srp/data.html:97
|
||||
#: allianceauth/srp/templates/srp/data.html:98
|
||||
msgid "Status"
|
||||
msgstr "Status"
|
||||
|
||||
@@ -738,11 +743,6 @@ msgstr "Keine Gruppenaustrittsanfragen"
|
||||
msgid "Toggle navigation"
|
||||
msgstr "Toggle Navigation"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:25
|
||||
msgid "Group Management"
|
||||
msgstr "Gruppenverwaltung"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
|
||||
msgid "Group Requests"
|
||||
msgstr "Gruppenanfragen"
|
||||
@@ -825,7 +825,7 @@ msgstr "Du hast Dich bereits für diese Gruppe beworben."
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:144
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:38
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:20
|
||||
#: allianceauth/srp/templates/srp/data.html:125
|
||||
#: allianceauth/srp/templates/srp/data.html:134
|
||||
#: allianceauth/srp/templates/srp/management.html:81
|
||||
msgid "Pending"
|
||||
msgstr "Beantragt"
|
||||
@@ -852,7 +852,7 @@ msgstr "Du hast bereits ein ausstehendes Austrittsgesuch für diese Gruppe."
|
||||
msgid "Applied to leave group %(group)s."
|
||||
msgstr "Austrittsgesuch für Gruppe %(group)s gesendet."
|
||||
|
||||
#: allianceauth/hrapplications/auth_hooks.py:10
|
||||
#: allianceauth/hrapplications/auth_hooks.py:13
|
||||
msgid "Applications"
|
||||
msgstr "Bewerbungen"
|
||||
|
||||
@@ -909,7 +909,7 @@ msgstr "Benutzername"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:131
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:28
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:75
|
||||
#: allianceauth/srp/templates/srp/data.html:99
|
||||
#: allianceauth/srp/templates/srp/data.html:100
|
||||
#: allianceauth/srp/templates/srp/management.html:46
|
||||
msgid "Actions"
|
||||
msgstr "Aktionen"
|
||||
@@ -919,7 +919,7 @@ msgstr "Aktionen"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:147
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:40
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:16
|
||||
#: allianceauth/srp/templates/srp/data.html:117
|
||||
#: allianceauth/srp/templates/srp/data.html:126
|
||||
msgid "Approved"
|
||||
msgstr "Akzeptiert"
|
||||
|
||||
@@ -927,7 +927,7 @@ msgstr "Akzeptiert"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:104
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:149
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:42
|
||||
#: allianceauth/srp/templates/srp/data.html:121
|
||||
#: allianceauth/srp/templates/srp/data.html:130
|
||||
msgid "Rejected"
|
||||
msgstr "Abgelehnt"
|
||||
|
||||
@@ -1033,7 +1033,7 @@ msgstr "Ungelesen"
|
||||
|
||||
#: allianceauth/notifications/templates/notifications/list.html:18
|
||||
msgid "Read"
|
||||
msgstr "Lesen"
|
||||
msgstr "Gelesen"
|
||||
|
||||
#: allianceauth/notifications/templates/notifications/list.html:22
|
||||
msgid "Mark All Read"
|
||||
@@ -1310,11 +1310,11 @@ msgstr "Passwort"
|
||||
msgid "Password must be at least 8 characters long."
|
||||
msgstr "Passwort muss mindestens 8 Zeichen lang sein"
|
||||
|
||||
#: allianceauth/services/modules/discord/models.py:224
|
||||
#: allianceauth/services/modules/discord/models.py:225
|
||||
msgid "Discord Account Disabled"
|
||||
msgstr "Discord Konto deaktiviert"
|
||||
|
||||
#: allianceauth/services/modules/discord/models.py:226
|
||||
#: allianceauth/services/modules/discord/models.py:227
|
||||
msgid ""
|
||||
"Your Discord account was disabeled automatically by Auth. If you think this "
|
||||
"was a mistake, please contact an admin."
|
||||
@@ -1628,7 +1628,7 @@ msgstr "Dienst"
|
||||
msgid "Domain"
|
||||
msgstr "Domain"
|
||||
|
||||
#: allianceauth/srp/auth_hooks.py:9
|
||||
#: allianceauth/srp/auth_hooks.py:12
|
||||
msgid "Ship Replacement"
|
||||
msgstr "Schiffserstattung"
|
||||
|
||||
@@ -1642,7 +1642,7 @@ msgstr "Flottenzeit"
|
||||
msgid "Fleet Doctrine"
|
||||
msgstr "Flottendoktrin"
|
||||
|
||||
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:89
|
||||
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:90
|
||||
msgid "Additional Info"
|
||||
msgstr "Zusätzliche Info"
|
||||
|
||||
@@ -1671,65 +1671,65 @@ msgstr "SRP-Flotte erstellen"
|
||||
msgid "Give this link to the line members"
|
||||
msgstr "Gib diesen Link an Deine Piloten weiter"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:48
|
||||
#: allianceauth/srp/templates/srp/data.html:49
|
||||
msgid "SRP Fleet Data"
|
||||
msgstr "SRP-Flotte Daten"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:53
|
||||
#: allianceauth/srp/templates/srp/data.html:54
|
||||
msgid "Mark Incomplete"
|
||||
msgstr "Als unvollständig markieren"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:57
|
||||
#: allianceauth/srp/templates/srp/data.html:58
|
||||
msgid "Mark Completed"
|
||||
msgstr "Als vollständig markieren"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:69
|
||||
#: allianceauth/srp/templates/srp/data.html:145
|
||||
#: allianceauth/srp/templates/srp/data.html:70
|
||||
#: allianceauth/srp/templates/srp/data.html:156
|
||||
msgid "Total Losses:"
|
||||
msgstr "Verluste insgesamt:"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:70
|
||||
#: allianceauth/srp/templates/srp/data.html:146
|
||||
#: allianceauth/srp/templates/srp/data.html:71
|
||||
#: allianceauth/srp/templates/srp/data.html:157
|
||||
#: allianceauth/srp/templates/srp/management.html:30
|
||||
msgid "Total ISK Cost:"
|
||||
msgstr "ISK-Kosten insgesamt:"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:78
|
||||
#: allianceauth/srp/templates/srp/data.html:154
|
||||
#: allianceauth/srp/templates/srp/data.html:79
|
||||
#: allianceauth/srp/templates/srp/data.html:165
|
||||
msgid "Are you sure you want to delete SRP requests?"
|
||||
msgstr "Bist Du sicher das Du SRP Anfragen löschen willst?"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:87
|
||||
#: allianceauth/srp/templates/srp/data.html:88
|
||||
msgid "Pilot Name"
|
||||
msgstr "Name des Piloten"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:88
|
||||
#: allianceauth/srp/templates/srp/data.html:89
|
||||
msgid "Killboard Link"
|
||||
msgstr "Killboard Link"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:90
|
||||
#: allianceauth/srp/templates/srp/data.html:91
|
||||
msgid "Ship Type"
|
||||
msgstr "Schiffstyp"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:91
|
||||
#: allianceauth/srp/templates/srp/data.html:92
|
||||
msgid "Killboard Loss Amt"
|
||||
msgstr "Summe Killboard Verluste"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:92
|
||||
#: allianceauth/srp/templates/srp/data.html:93
|
||||
msgid "SRP ISK Cost"
|
||||
msgstr "SRP ISK-Kosten"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:93
|
||||
#: allianceauth/srp/templates/srp/data.html:94
|
||||
msgid "Click value to edit Enter to save & next ESC to cancel"
|
||||
msgstr ""
|
||||
"Klicke auf den Wert um diesen zu bearbeiten, Enter zum Speichern und um zum "
|
||||
"nächsten Wert zu springen, ESC zum Beenden."
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:96
|
||||
#: allianceauth/srp/templates/srp/data.html:97
|
||||
msgid "Post Time"
|
||||
msgstr "Veröffentlichungszeit"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:163
|
||||
#: allianceauth/srp/templates/srp/data.html:174
|
||||
msgid "No SRP requests for this fleet."
|
||||
msgstr "Keine SRP Anfragen für diese Flotte."
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-07-29 04:56+0000\n"
|
||||
"POT-Creation-Date: 2020-10-01 02:59+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -22,7 +22,7 @@ msgstr ""
|
||||
msgid "A main character is required to perform that action. Add one below."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/forms.py:6
|
||||
#: allianceauth/authentication/forms.py:5
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
@@ -38,7 +38,7 @@ msgstr ""
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:5
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:8
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:12
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:11
|
||||
msgid "Dashboard"
|
||||
msgstr ""
|
||||
|
||||
@@ -154,22 +154,22 @@ msgstr ""
|
||||
msgid "Unable to authenticate as the selected character."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/views.py:148
|
||||
#: allianceauth/authentication/views.py:146
|
||||
msgid "Registration token has expired."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/views.py:200
|
||||
#: allianceauth/authentication/views.py:201
|
||||
msgid ""
|
||||
"Sent confirmation email. Please follow the link to confirm your email "
|
||||
"address."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/views.py:205
|
||||
#: allianceauth/authentication/views.py:206
|
||||
msgid "Confirmed your email address. Please login to continue."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/views.py:210
|
||||
msgid "Registraion of new accounts it not allowed at this time."
|
||||
#: allianceauth/authentication/views.py:211
|
||||
msgid "Registration of new accounts is not allowed at this time."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/corputils/auth_hooks.py:10
|
||||
@@ -535,6 +535,11 @@ msgstr ""
|
||||
msgid "FAT link has expired."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/groupmanagement/auth_hooks.py:16
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
||||
msgid "Group Management"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
|
||||
msgid "Audit Log"
|
||||
@@ -607,7 +612,7 @@ msgstr ""
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
|
||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:17
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:16
|
||||
msgid "Groups"
|
||||
msgstr ""
|
||||
|
||||
@@ -621,7 +626,7 @@ msgstr ""
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:27
|
||||
#: allianceauth/srp/templates/srp/data.html:97
|
||||
#: allianceauth/srp/templates/srp/data.html:98
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
@@ -721,11 +726,6 @@ msgstr ""
|
||||
msgid "Toggle navigation"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:25
|
||||
msgid "Group Management"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
|
||||
msgid "Group Requests"
|
||||
msgstr ""
|
||||
@@ -804,7 +804,7 @@ msgstr ""
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:144
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:38
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:20
|
||||
#: allianceauth/srp/templates/srp/data.html:125
|
||||
#: allianceauth/srp/templates/srp/data.html:128
|
||||
#: allianceauth/srp/templates/srp/management.html:81
|
||||
msgid "Pending"
|
||||
msgstr ""
|
||||
@@ -831,7 +831,7 @@ msgstr ""
|
||||
msgid "Applied to leave group %(group)s."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/hrapplications/auth_hooks.py:10
|
||||
#: allianceauth/hrapplications/auth_hooks.py:13
|
||||
msgid "Applications"
|
||||
msgstr ""
|
||||
|
||||
@@ -888,7 +888,7 @@ msgstr ""
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:131
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:28
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:75
|
||||
#: allianceauth/srp/templates/srp/data.html:99
|
||||
#: allianceauth/srp/templates/srp/data.html:100
|
||||
#: allianceauth/srp/templates/srp/management.html:46
|
||||
msgid "Actions"
|
||||
msgstr ""
|
||||
@@ -898,7 +898,7 @@ msgstr ""
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:147
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:40
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:16
|
||||
#: allianceauth/srp/templates/srp/data.html:117
|
||||
#: allianceauth/srp/templates/srp/data.html:120
|
||||
msgid "Approved"
|
||||
msgstr ""
|
||||
|
||||
@@ -906,7 +906,7 @@ msgstr ""
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:104
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:149
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:42
|
||||
#: allianceauth/srp/templates/srp/data.html:121
|
||||
#: allianceauth/srp/templates/srp/data.html:124
|
||||
msgid "Rejected"
|
||||
msgstr ""
|
||||
|
||||
@@ -1289,13 +1289,13 @@ msgstr ""
|
||||
msgid "Password must be at least 8 characters long."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/services/modules/discord/models.py:224
|
||||
#: allianceauth/services/modules/discord/models.py:225
|
||||
msgid "Discord Account Disabled"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/services/modules/discord/models.py:226
|
||||
#: allianceauth/services/modules/discord/models.py:227
|
||||
msgid ""
|
||||
"Your Discord account was disabeled automatically by Auth. If you think this "
|
||||
"Your Discord account was disabled automatically by Auth. If you think this "
|
||||
"was a mistake, please contact an admin."
|
||||
msgstr ""
|
||||
|
||||
@@ -1595,7 +1595,7 @@ msgstr ""
|
||||
msgid "Domain"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/srp/auth_hooks.py:9
|
||||
#: allianceauth/srp/auth_hooks.py:12
|
||||
msgid "Ship Replacement"
|
||||
msgstr ""
|
||||
|
||||
@@ -1607,7 +1607,7 @@ msgstr ""
|
||||
msgid "Fleet Doctrine"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:89
|
||||
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:90
|
||||
msgid "Additional Info"
|
||||
msgstr ""
|
||||
|
||||
@@ -1636,63 +1636,63 @@ msgstr ""
|
||||
msgid "Give this link to the line members"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:48
|
||||
#: allianceauth/srp/templates/srp/data.html:49
|
||||
msgid "SRP Fleet Data"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:53
|
||||
#: allianceauth/srp/templates/srp/data.html:54
|
||||
msgid "Mark Incomplete"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:57
|
||||
#: allianceauth/srp/templates/srp/data.html:58
|
||||
msgid "Mark Completed"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:69
|
||||
#: allianceauth/srp/templates/srp/data.html:145
|
||||
#: allianceauth/srp/templates/srp/data.html:70
|
||||
#: allianceauth/srp/templates/srp/data.html:150
|
||||
msgid "Total Losses:"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:70
|
||||
#: allianceauth/srp/templates/srp/data.html:146
|
||||
#: allianceauth/srp/templates/srp/data.html:71
|
||||
#: allianceauth/srp/templates/srp/data.html:151
|
||||
#: allianceauth/srp/templates/srp/management.html:30
|
||||
msgid "Total ISK Cost:"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:78
|
||||
#: allianceauth/srp/templates/srp/data.html:154
|
||||
#: allianceauth/srp/templates/srp/data.html:79
|
||||
#: allianceauth/srp/templates/srp/data.html:159
|
||||
msgid "Are you sure you want to delete SRP requests?"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:87
|
||||
#: allianceauth/srp/templates/srp/data.html:88
|
||||
msgid "Pilot Name"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:88
|
||||
#: allianceauth/srp/templates/srp/data.html:89
|
||||
msgid "Killboard Link"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:90
|
||||
#: allianceauth/srp/templates/srp/data.html:91
|
||||
msgid "Ship Type"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:91
|
||||
#: allianceauth/srp/templates/srp/data.html:92
|
||||
msgid "Killboard Loss Amt"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:92
|
||||
#: allianceauth/srp/templates/srp/data.html:93
|
||||
msgid "SRP ISK Cost"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:93
|
||||
#: allianceauth/srp/templates/srp/data.html:94
|
||||
msgid "Click value to edit Enter to save & next ESC to cancel"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:96
|
||||
#: allianceauth/srp/templates/srp/data.html:97
|
||||
msgid "Post Time"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:163
|
||||
#: allianceauth/srp/templates/srp/data.html:168
|
||||
msgid "No SRP requests for this fleet."
|
||||
msgstr ""
|
||||
|
||||
|
||||
Binary file not shown.
@@ -4,17 +4,17 @@
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
# Translators:
|
||||
# Joel Falknau <ozirascal@gmail.com>, 2020
|
||||
# frank1210 <francolopez_16@hotmail.com>, 2020
|
||||
# Joel Falknau <ozirascal@gmail.com>, 2020
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-05-08 00:57+0000\n"
|
||||
"POT-Creation-Date: 2020-10-11 03:43+0000\n"
|
||||
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
||||
"Last-Translator: frank1210 <francolopez_16@hotmail.com>, 2020\n"
|
||||
"Last-Translator: Joel Falknau <ozirascal@gmail.com>, 2020\n"
|
||||
"Language-Team: Spanish (https://www.transifex.com/alliance-auth/teams/107430/es/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -27,59 +27,57 @@ msgid "A main character is required to perform that action. Add one below."
|
||||
msgstr ""
|
||||
"Un personaje principal es requerido para completar esta accion. Agregue uno"
|
||||
|
||||
#: allianceauth/authentication/forms.py:6
|
||||
#: allianceauth/authentication/forms.py:5
|
||||
msgid "Email"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: allianceauth/authentication/models.py:76
|
||||
msgid "State Changed"
|
||||
msgstr "Estado Cambiado"
|
||||
|
||||
#: allianceauth/authentication/models.py:77
|
||||
#: allianceauth/authentication/models.py:78
|
||||
#, python-format
|
||||
msgid "Your user state has been changed to %(state)s"
|
||||
msgstr "Tu estado de usuario fue cambiado a %(state)s"
|
||||
msgid "State changed to: %s"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/models.py:79
|
||||
#, python-format
|
||||
msgid "Your user's state is now: %(state)s"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:5
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:8
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:10
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:11
|
||||
msgid "Dashboard"
|
||||
msgstr "Pagina Principal"
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:17
|
||||
#: allianceauth/corputils/templates/corputils/corpstats.html:116
|
||||
#: allianceauth/corputils/templates/corputils/search.html:16
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:22
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:83
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:128
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:25
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:32
|
||||
msgid "Main Character"
|
||||
msgstr "Personaje Principal"
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:18
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" Main Character (State: %(state)s)\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:77
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:81
|
||||
msgid "No main character set."
|
||||
msgstr "No se ha seleccionado un personaje principal."
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:84
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:88
|
||||
msgid "Add Character"
|
||||
msgstr "Agregar Personaje"
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:88
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:92
|
||||
msgid "Change Main"
|
||||
msgstr "Cambiar Personaje Principal"
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:97
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:101
|
||||
msgid "Group Memberships"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:117
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:121
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:41
|
||||
msgid "Characters"
|
||||
msgstr "Personajes"
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:125
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:129
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
|
||||
@@ -88,13 +86,13 @@ msgstr "Personajes"
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:126
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:130
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:23
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:46
|
||||
msgid "Corp"
|
||||
msgstr "Corporación"
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:127
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:131
|
||||
#: allianceauth/corputils/templates/corputils/corpstats.html:77
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:47
|
||||
msgid "Alliance"
|
||||
@@ -163,24 +161,24 @@ msgstr ""
|
||||
msgid "Unable to authenticate as the selected character."
|
||||
msgstr "Imposible validar con el personaje seleccionado."
|
||||
|
||||
#: allianceauth/authentication/views.py:148
|
||||
#: allianceauth/authentication/views.py:146
|
||||
msgid "Registration token has expired."
|
||||
msgstr "El token de registracion expiro."
|
||||
|
||||
#: allianceauth/authentication/views.py:200
|
||||
#: allianceauth/authentication/views.py:201
|
||||
msgid ""
|
||||
"Sent confirmation email. Please follow the link to confirm your email "
|
||||
"address."
|
||||
msgstr ""
|
||||
"Confirmacion de mail enviada. Por favor siga el enlace para confirmar "
|
||||
|
||||
#: allianceauth/authentication/views.py:205
|
||||
#: allianceauth/authentication/views.py:206
|
||||
msgid "Confirmed your email address. Please login to continue."
|
||||
msgstr ""
|
||||
"Se ha confirmado su direccion de mail. Por favor igrese su token para "
|
||||
"continuar."
|
||||
|
||||
#: allianceauth/authentication/views.py:210
|
||||
#: allianceauth/authentication/views.py:211
|
||||
msgid "Registraion of new accounts it not allowed at this time."
|
||||
msgstr "Registracion de nuevas cuentas no es permitido por el momento."
|
||||
|
||||
@@ -231,8 +229,8 @@ msgstr "Ultima Actualizacion:"
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:37
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:96
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
|
||||
msgid "Character"
|
||||
msgstr "Personaje"
|
||||
|
||||
@@ -254,6 +252,16 @@ msgstr "Corporacion"
|
||||
msgid "Killboard"
|
||||
msgstr "Killboard"
|
||||
|
||||
#: allianceauth/corputils/templates/corputils/corpstats.html:116
|
||||
#: allianceauth/corputils/templates/corputils/search.html:16
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:22
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:83
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:128
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:25
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:32
|
||||
msgid "Main Character"
|
||||
msgstr "Personaje Principal"
|
||||
|
||||
#: allianceauth/corputils/templates/corputils/corpstats.html:117
|
||||
#: allianceauth/corputils/templates/corputils/search.html:17
|
||||
msgid "Main Corporation"
|
||||
@@ -538,6 +546,11 @@ msgstr "Participacion de flota registrada."
|
||||
msgid "FAT link has expired."
|
||||
msgstr "Enlace de participacion expirado."
|
||||
|
||||
#: allianceauth/groupmanagement/auth_hooks.py:16
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
||||
msgid "Group Management"
|
||||
msgstr "Manejo de Grupo"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
|
||||
msgid "Audit Log"
|
||||
@@ -590,8 +603,8 @@ msgid "Portrait"
|
||||
msgstr "Retrato"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:38
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:97
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
|
||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
|
||||
msgid "Organization"
|
||||
msgstr ""
|
||||
@@ -610,7 +623,7 @@ msgstr "Membresia de grupos"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
|
||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:15
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:16
|
||||
msgid "Groups"
|
||||
msgstr "Grupos"
|
||||
|
||||
@@ -624,7 +637,7 @@ msgstr "Descripcion"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:27
|
||||
#: allianceauth/srp/templates/srp/data.html:97
|
||||
#: allianceauth/srp/templates/srp/data.html:98
|
||||
msgid "Status"
|
||||
msgstr "Estado"
|
||||
|
||||
@@ -654,7 +667,7 @@ msgid "Audit Members"
|
||||
msgstr "Auditar Miembros"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
|
||||
msgid "Copy Direrct Join Link"
|
||||
msgid "Copy Direct Join Link"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68
|
||||
@@ -686,37 +699,37 @@ msgstr "No hay grupos disponibles"
|
||||
msgid "Groups Management"
|
||||
msgstr "Manejo de Grupos"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:23
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:25
|
||||
msgid "Join Requests"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:24
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:33
|
||||
msgid "Leave Requests"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:39
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:98
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
|
||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
|
||||
#: allianceauth/services/modules/openfire/forms.py:6
|
||||
msgid "Group"
|
||||
msgstr "Grupo"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:71
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:130
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:85
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:144
|
||||
msgid "Accept"
|
||||
msgstr "Aceptar"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:74
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:133
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:147
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:85
|
||||
msgid "Reject"
|
||||
msgstr "Rechazar"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:83
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:97
|
||||
msgid "No group add requests."
|
||||
msgstr "No hay solicitudes de ingreso."
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:142
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:156
|
||||
msgid "No group leave requests."
|
||||
msgstr "No hay solicitudes paradejar el grupo."
|
||||
|
||||
@@ -724,11 +737,6 @@ msgstr "No hay solicitudes paradejar el grupo."
|
||||
msgid "Toggle navigation"
|
||||
msgstr "Navegacion"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:23
|
||||
msgid "Group Management"
|
||||
msgstr "Manejo de Grupo"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
|
||||
msgid "Group Requests"
|
||||
msgstr "Solicitudes de Grupo"
|
||||
@@ -737,26 +745,26 @@ msgstr "Solicitudes de Grupo"
|
||||
msgid "Group Membership"
|
||||
msgstr "Membresia de Grupo"
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:166
|
||||
#: allianceauth/groupmanagement/views.py:162
|
||||
#, python-format
|
||||
msgid "Removed user %(user)s from group %(group)s."
|
||||
msgstr "El usuario %(user)s fue removido del grupo %(group)s"
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:168
|
||||
#: allianceauth/groupmanagement/views.py:164
|
||||
msgid "User does not exist in that group"
|
||||
msgstr "El usuario no existe en ese grupos"
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:171
|
||||
#: allianceauth/groupmanagement/views.py:167
|
||||
msgid "Group does not exist"
|
||||
msgstr "El grupo no existe"
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:198
|
||||
#: allianceauth/groupmanagement/views.py:194
|
||||
#, python-format
|
||||
msgid "Accepted application from %(mainchar)s to %(group)s."
|
||||
msgstr "Solicitud aceptada de %(mainchar)s a %(group)s"
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:205
|
||||
#: allianceauth/groupmanagement/views.py:238
|
||||
#: allianceauth/groupmanagement/views.py:201
|
||||
#: allianceauth/groupmanagement/views.py:234
|
||||
#, python-format
|
||||
msgid ""
|
||||
"An unhandled error occurred while processing the application from "
|
||||
@@ -765,79 +773,79 @@ msgstr ""
|
||||
"Ocurrio un error cuando se intento procesar la informacion de %(mainchar)s "
|
||||
"al grupo %(group)s."
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:231
|
||||
#: allianceauth/groupmanagement/views.py:227
|
||||
#, python-format
|
||||
msgid "Rejected application from %(mainchar)s to %(group)s."
|
||||
msgstr "Se rechazo la solicitud de %(mainchar)s al grupo %(group)s."
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:267
|
||||
#: allianceauth/groupmanagement/views.py:263
|
||||
#, python-format
|
||||
msgid "Accepted application from %(mainchar)s to leave %(group)s."
|
||||
msgstr "Se acepto la solicitud de %(mainchar)s para dejar el grupo %(group)s."
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:273
|
||||
#: allianceauth/groupmanagement/views.py:307
|
||||
#: allianceauth/groupmanagement/views.py:269
|
||||
#: allianceauth/groupmanagement/views.py:303
|
||||
#, python-format
|
||||
msgid ""
|
||||
"An unhandled error occurred while processing the application from "
|
||||
"%(mainchar)s to leave %(group)s."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:300
|
||||
#: allianceauth/groupmanagement/views.py:296
|
||||
#, python-format
|
||||
msgid "Rejected application from %(mainchar)s to leave %(group)s."
|
||||
msgstr ""
|
||||
"Se rechazo la solicitud de %(mainchar)s para dejar el grupo %(group)s."
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:346
|
||||
#: allianceauth/groupmanagement/views.py:358
|
||||
#: allianceauth/groupmanagement/views.py:342
|
||||
#: allianceauth/groupmanagement/views.py:354
|
||||
msgid "You cannot join that group"
|
||||
msgstr "No puedes unirte a ese grupo"
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:352
|
||||
#: allianceauth/groupmanagement/views.py:348
|
||||
msgid "You are already a member of that group."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:367
|
||||
#: allianceauth/groupmanagement/views.py:363
|
||||
msgid "You already have a pending application for that group."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:370
|
||||
#: allianceauth/groupmanagement/views.py:408
|
||||
#: allianceauth/groupmanagement/views.py:366
|
||||
#: allianceauth/groupmanagement/views.py:404
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:37
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:72
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:99
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:144
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:38
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:20
|
||||
#: allianceauth/srp/templates/srp/data.html:125
|
||||
#: allianceauth/srp/templates/srp/data.html:134
|
||||
#: allianceauth/srp/templates/srp/management.html:81
|
||||
msgid "Pending"
|
||||
msgstr "Pendiente"
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:376
|
||||
#: allianceauth/groupmanagement/views.py:372
|
||||
#, python-format
|
||||
msgid "Applied to group %(group)s."
|
||||
msgstr "Solicitud enviada al grupo %(group)s."
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:387
|
||||
#: allianceauth/groupmanagement/views.py:383
|
||||
msgid "You cannot leave that group"
|
||||
msgstr "No puedes dejar el grupos"
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:392
|
||||
#: allianceauth/groupmanagement/views.py:388
|
||||
msgid "You are not a member of that group"
|
||||
msgstr "No eres miembro de ese grupo"
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:401
|
||||
#: allianceauth/groupmanagement/views.py:397
|
||||
msgid "You already have a pending leave request for that group."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:414
|
||||
#: allianceauth/groupmanagement/views.py:410
|
||||
#, python-format
|
||||
msgid "Applied to leave group %(group)s."
|
||||
msgstr "Solicitaste dejar el grupo %(group)s."
|
||||
|
||||
#: allianceauth/hrapplications/auth_hooks.py:10
|
||||
#: allianceauth/hrapplications/auth_hooks.py:13
|
||||
msgid "Applications"
|
||||
msgstr "Solicitudes"
|
||||
|
||||
@@ -894,7 +902,7 @@ msgstr "Usuario"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:131
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:28
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:75
|
||||
#: allianceauth/srp/templates/srp/data.html:99
|
||||
#: allianceauth/srp/templates/srp/data.html:100
|
||||
#: allianceauth/srp/templates/srp/management.html:46
|
||||
msgid "Actions"
|
||||
msgstr "Acciones"
|
||||
@@ -904,7 +912,7 @@ msgstr "Acciones"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:147
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:40
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:16
|
||||
#: allianceauth/srp/templates/srp/data.html:117
|
||||
#: allianceauth/srp/templates/srp/data.html:126
|
||||
msgid "Approved"
|
||||
msgstr "Aprovado"
|
||||
|
||||
@@ -912,7 +920,7 @@ msgstr "Aprovado"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:104
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:149
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:42
|
||||
#: allianceauth/srp/templates/srp/data.html:121
|
||||
#: allianceauth/srp/templates/srp/data.html:130
|
||||
msgid "Rejected"
|
||||
msgstr "Rechazado"
|
||||
|
||||
@@ -1295,22 +1303,49 @@ msgstr "Contraseña"
|
||||
msgid "Password must be at least 8 characters long."
|
||||
msgstr "La contraseña tiene que tener 8 caracteres de largo minimo"
|
||||
|
||||
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:23
|
||||
#: allianceauth/services/modules/discord/models.py:225
|
||||
msgid "Discord Account Disabled"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/services/modules/discord/models.py:227
|
||||
msgid ""
|
||||
"Your Discord account was disabeled automatically by Auth. If you think this "
|
||||
"was a mistake, please contact an admin."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:18
|
||||
msgid "Join the Discord server"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:22
|
||||
msgid "Leave- and rejoin the Discord Server (Reset)"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:25
|
||||
msgid "Leave the Discord server"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:32
|
||||
msgid "Link Discord Server"
|
||||
msgstr "Enlace a servidor de Discord"
|
||||
|
||||
#: allianceauth/services/modules/discord/views.py:26
|
||||
#: allianceauth/services/modules/discord/views.py:30
|
||||
msgid "Deactivated Discord account."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/services/modules/discord/views.py:29
|
||||
#: allianceauth/services/modules/discord/views.py:41
|
||||
#: allianceauth/services/modules/discord/views.py:65
|
||||
#: allianceauth/services/modules/discord/views.py:36
|
||||
#: allianceauth/services/modules/discord/views.py:59
|
||||
msgid "An error occurred while processing your Discord account."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/services/modules/discord/views.py:62
|
||||
msgid "Activated Discord account."
|
||||
#: allianceauth/services/modules/discord/views.py:102
|
||||
msgid "Your Discord account has been successfully activated."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/services/modules/discord/views.py:108
|
||||
msgid ""
|
||||
"An error occurred while trying to activate your Discord account. Please try "
|
||||
"again."
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/services/modules/discourse/views.py:37
|
||||
@@ -1575,7 +1610,7 @@ msgstr "Servicio"
|
||||
msgid "Domain"
|
||||
msgstr "Dominio"
|
||||
|
||||
#: allianceauth/srp/auth_hooks.py:9
|
||||
#: allianceauth/srp/auth_hooks.py:12
|
||||
msgid "Ship Replacement"
|
||||
msgstr "Reemplazo de Nave"
|
||||
|
||||
@@ -1589,7 +1624,7 @@ msgstr "Hora de flota"
|
||||
msgid "Fleet Doctrine"
|
||||
msgstr "Doctrina"
|
||||
|
||||
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:89
|
||||
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:90
|
||||
msgid "Additional Info"
|
||||
msgstr "Informacion Adicional"
|
||||
|
||||
@@ -1618,63 +1653,63 @@ msgstr "Crear SRP"
|
||||
msgid "Give this link to the line members"
|
||||
msgstr "Entregar este enlace a los miembros"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:48
|
||||
#: allianceauth/srp/templates/srp/data.html:49
|
||||
msgid "SRP Fleet Data"
|
||||
msgstr "Informacion de SRP de la flota"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:53
|
||||
#: allianceauth/srp/templates/srp/data.html:54
|
||||
msgid "Mark Incomplete"
|
||||
msgstr "Marcar como Incompleto"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:57
|
||||
#: allianceauth/srp/templates/srp/data.html:58
|
||||
msgid "Mark Completed"
|
||||
msgstr "Marcar como Completo"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:69
|
||||
#: allianceauth/srp/templates/srp/data.html:145
|
||||
#: allianceauth/srp/templates/srp/data.html:70
|
||||
#: allianceauth/srp/templates/srp/data.html:156
|
||||
msgid "Total Losses:"
|
||||
msgstr "Perdidas Totales:"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:70
|
||||
#: allianceauth/srp/templates/srp/data.html:146
|
||||
#: allianceauth/srp/templates/srp/data.html:71
|
||||
#: allianceauth/srp/templates/srp/data.html:157
|
||||
#: allianceauth/srp/templates/srp/management.html:30
|
||||
msgid "Total ISK Cost:"
|
||||
msgstr "Costo Total:"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:78
|
||||
#: allianceauth/srp/templates/srp/data.html:154
|
||||
#: allianceauth/srp/templates/srp/data.html:79
|
||||
#: allianceauth/srp/templates/srp/data.html:165
|
||||
msgid "Are you sure you want to delete SRP requests?"
|
||||
msgstr "Estas seguro que quiere borrar las solicitudes de SRP"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:87
|
||||
#: allianceauth/srp/templates/srp/data.html:88
|
||||
msgid "Pilot Name"
|
||||
msgstr "Nombre del Piloto"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:88
|
||||
#: allianceauth/srp/templates/srp/data.html:89
|
||||
msgid "Killboard Link"
|
||||
msgstr "Enlace de la Muerte"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:90
|
||||
#: allianceauth/srp/templates/srp/data.html:91
|
||||
msgid "Ship Type"
|
||||
msgstr "Tipo"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:91
|
||||
#: allianceauth/srp/templates/srp/data.html:92
|
||||
msgid "Killboard Loss Amt"
|
||||
msgstr "Monto de la perdida en ZKB"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:92
|
||||
#: allianceauth/srp/templates/srp/data.html:93
|
||||
msgid "SRP ISK Cost"
|
||||
msgstr "Costo del SRP"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:93
|
||||
#: allianceauth/srp/templates/srp/data.html:94
|
||||
msgid "Click value to edit Enter to save & next ESC to cancel"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:96
|
||||
#: allianceauth/srp/templates/srp/data.html:97
|
||||
msgid "Post Time"
|
||||
msgstr "Tiempo"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:163
|
||||
#: allianceauth/srp/templates/srp/data.html:174
|
||||
msgid "No SRP requests for this fleet."
|
||||
msgstr "No hay solicitudes de SRP para esta flota."
|
||||
|
||||
@@ -1866,32 +1901,30 @@ msgid "Current"
|
||||
msgstr "Actual"
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:40
|
||||
msgid "Latest Major"
|
||||
msgstr "Ultimo Importante"
|
||||
msgid "Latest Stable"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:46
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:56
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:66
|
||||
msgid "Update available"
|
||||
msgstr "Actualizacion Disponible"
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:50
|
||||
msgid "Latest Minor"
|
||||
msgstr "Ultimo no importante"
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:51
|
||||
msgid "Latest Pre-Release"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:60
|
||||
msgid "Latest Patch"
|
||||
msgstr "Ultimo Parche"
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:57
|
||||
msgid "Pre-Release available"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:73
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:65
|
||||
msgid "Task Queue"
|
||||
msgstr "Cola de Tareas"
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:90
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:82
|
||||
msgid "Error retrieving task queue length"
|
||||
msgstr "Error al conseguir la cola de tareas"
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:92
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:84
|
||||
#, python-format
|
||||
msgid "%(tasks)s task"
|
||||
msgid_plural "%(tasks)s tasks"
|
||||
|
||||
BIN
allianceauth/locale/fr_FR/LC_MESSAGES/django.mo
Normal file
BIN
allianceauth/locale/fr_FR/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
2083
allianceauth/locale/fr_FR/LC_MESSAGES/django.po
Normal file
2083
allianceauth/locale/fr_FR/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
allianceauth/locale/ja/LC_MESSAGES/django.mo
Normal file
BIN
allianceauth/locale/ja/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
2057
allianceauth/locale/ja/LC_MESSAGES/django.po
Normal file
2057
allianceauth/locale/ja/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -4,19 +4,19 @@
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
# Translators:
|
||||
# Lahty <js03js70@gmail.com>, 2020
|
||||
# Kim Hyundong <khd1226543@gmail.com>, 2020
|
||||
# Seowon Jung <seowon@hawaii.edu>, 2020
|
||||
# None None <khd1226543@gmail.com>, 2020
|
||||
# Olgeda Choi <undead.choi@gmail.com>, 2020
|
||||
# Seowon Jung <seowon@hawaii.edu>, 2020
|
||||
# Lahty <js03js70@gmail.com>, 2020
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-05-08 00:57+0000\n"
|
||||
"POT-Creation-Date: 2020-10-11 03:43+0000\n"
|
||||
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
||||
"Last-Translator: Olgeda Choi <undead.choi@gmail.com>, 2020\n"
|
||||
"Last-Translator: Lahty <js03js70@gmail.com>, 2020\n"
|
||||
"Language-Team: Korean (Korea) (https://www.transifex.com/alliance-auth/teams/107430/ko_KR/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -28,59 +28,60 @@ msgstr ""
|
||||
msgid "A main character is required to perform that action. Add one below."
|
||||
msgstr "해당 기능을 수행하려면 주 캐릭터가 요구됨. 아래에 하나를 추가하시오."
|
||||
|
||||
#: allianceauth/authentication/forms.py:6
|
||||
#: allianceauth/authentication/forms.py:5
|
||||
msgid "Email"
|
||||
msgstr "이메일"
|
||||
|
||||
#: allianceauth/authentication/models.py:76
|
||||
msgid "State Changed"
|
||||
msgstr "상태 변경됨"
|
||||
|
||||
#: allianceauth/authentication/models.py:77
|
||||
#: allianceauth/authentication/models.py:78
|
||||
#, python-format
|
||||
msgid "Your user state has been changed to %(state)s"
|
||||
msgstr "사용자의 상태가 %(state)s변경됨"
|
||||
msgid "State changed to: %s"
|
||||
msgstr "상태가 %s로 변경됐습니다."
|
||||
|
||||
#: allianceauth/authentication/models.py:79
|
||||
#, python-format
|
||||
msgid "Your user's state is now: %(state)s"
|
||||
msgstr "사용자의 상태는 %(state)s입니다."
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:5
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:8
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:10
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:11
|
||||
msgid "Dashboard"
|
||||
msgstr "대시보드"
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:17
|
||||
#: allianceauth/corputils/templates/corputils/corpstats.html:116
|
||||
#: allianceauth/corputils/templates/corputils/search.html:16
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:22
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:83
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:128
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:25
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:32
|
||||
msgid "Main Character"
|
||||
msgstr "주 캐릭터"
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:18
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" Main Character (State: %(state)s)\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" 메인 캐릭터 (상태: %(state)s)\n"
|
||||
" "
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:77
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:81
|
||||
msgid "No main character set."
|
||||
msgstr "주 캐릭터가 지정되지 않음"
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:84
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:88
|
||||
msgid "Add Character"
|
||||
msgstr "캐릭터 추가"
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:88
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:92
|
||||
msgid "Change Main"
|
||||
msgstr "주 캐릭터 변경"
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:97
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:101
|
||||
msgid "Group Memberships"
|
||||
msgstr "그룹 멤버쉽"
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:117
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:121
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:41
|
||||
msgid "Characters"
|
||||
msgstr "캐릭터"
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:125
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:129
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:73
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:22
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groups.html:15
|
||||
@@ -89,13 +90,13 @@ msgstr "캐릭터"
|
||||
msgid "Name"
|
||||
msgstr "이름"
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:126
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:130
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:23
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:46
|
||||
msgid "Corp"
|
||||
msgstr "콥"
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:127
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:131
|
||||
#: allianceauth/corputils/templates/corputils/corpstats.html:77
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:47
|
||||
msgid "Alliance"
|
||||
@@ -151,32 +152,32 @@ msgstr "주 캐릭터가 %(char)s로 변경됨"
|
||||
#: allianceauth/authentication/views.py:89
|
||||
#, python-format
|
||||
msgid "Added %(name)s to your account."
|
||||
msgstr "%(name)s을(를) 계정에 추가함"
|
||||
msgstr "계정에 %(name)s를 추가했습니다."
|
||||
|
||||
#: allianceauth/authentication/views.py:91
|
||||
#, python-format
|
||||
msgid "Failed to add %(name)s to your account: they already have an account."
|
||||
msgstr "%(name)s을(를) 계정에 추가하는데 실패함. 이미 추가되어있음."
|
||||
msgstr "계정에 %(name)s를 추가하지 못했습니다. 이미 추가된 계정입니다."
|
||||
|
||||
#: allianceauth/authentication/views.py:130
|
||||
msgid "Unable to authenticate as the selected character."
|
||||
msgstr "선택한 캐릭터로 인증을 수행할 수 없음"
|
||||
|
||||
#: allianceauth/authentication/views.py:148
|
||||
#: allianceauth/authentication/views.py:146
|
||||
msgid "Registration token has expired."
|
||||
msgstr "등록토큰 만료"
|
||||
|
||||
#: allianceauth/authentication/views.py:200
|
||||
#: allianceauth/authentication/views.py:201
|
||||
msgid ""
|
||||
"Sent confirmation email. Please follow the link to confirm your email "
|
||||
"address."
|
||||
msgstr "확인 메일 전송됨. 다음 링크를 눌러 이메일 주소를 확인하세요."
|
||||
|
||||
#: allianceauth/authentication/views.py:205
|
||||
#: allianceauth/authentication/views.py:206
|
||||
msgid "Confirmed your email address. Please login to continue."
|
||||
msgstr "이메일 주소가 확인되었습니다. 로그인 해주세요."
|
||||
|
||||
#: allianceauth/authentication/views.py:210
|
||||
#: allianceauth/authentication/views.py:211
|
||||
msgid "Registraion of new accounts it not allowed at this time."
|
||||
msgstr "현재 새로운 계정 등록은 받지않습니다."
|
||||
|
||||
@@ -227,8 +228,8 @@ msgstr "마지막 업데이트"
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:28
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:27
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:37
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:96
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:51
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:110
|
||||
msgid "Character"
|
||||
msgstr "캐릭터"
|
||||
|
||||
@@ -250,6 +251,16 @@ msgstr "콥"
|
||||
msgid "Killboard"
|
||||
msgstr "킬보드"
|
||||
|
||||
#: allianceauth/corputils/templates/corputils/corpstats.html:116
|
||||
#: allianceauth/corputils/templates/corputils/search.html:16
|
||||
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:22
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:83
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:128
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:25
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:32
|
||||
msgid "Main Character"
|
||||
msgstr "주 캐릭터"
|
||||
|
||||
#: allianceauth/corputils/templates/corputils/corpstats.html:117
|
||||
#: allianceauth/corputils/templates/corputils/search.html:17
|
||||
msgid "Main Corporation"
|
||||
@@ -531,6 +542,11 @@ msgstr "플릿 참여 등록됨"
|
||||
msgid "FAT link has expired."
|
||||
msgstr "플릿활동추적 링크 기한만료"
|
||||
|
||||
#: allianceauth/groupmanagement/auth_hooks.py:16
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
||||
msgid "Group Management"
|
||||
msgstr "그룹 관리"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
|
||||
msgid "Audit Log"
|
||||
@@ -583,8 +599,8 @@ msgid "Portrait"
|
||||
msgstr "포트레잇"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:30
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:38
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:97
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:52
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:111
|
||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:23
|
||||
msgid "Organization"
|
||||
msgstr "조직"
|
||||
@@ -603,7 +619,7 @@ msgstr "그룹 멤버쉽"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
|
||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:15
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:16
|
||||
msgid "Groups"
|
||||
msgstr "그룹"
|
||||
|
||||
@@ -617,7 +633,7 @@ msgstr "설명"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:27
|
||||
#: allianceauth/srp/templates/srp/data.html:97
|
||||
#: allianceauth/srp/templates/srp/data.html:98
|
||||
msgid "Status"
|
||||
msgstr "상태"
|
||||
|
||||
@@ -647,8 +663,8 @@ msgid "Audit Members"
|
||||
msgstr "멤버 검사"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:56
|
||||
msgid "Copy Direrct Join Link"
|
||||
msgstr ""
|
||||
msgid "Copy Direct Join Link"
|
||||
msgstr "직접 참여 링크 복사"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:68
|
||||
msgid "No groups to list."
|
||||
@@ -679,37 +695,37 @@ msgstr "사용 가능한 그룹 없음."
|
||||
msgid "Groups Management"
|
||||
msgstr "그룹 관리"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:23
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:25
|
||||
msgid "Join Requests"
|
||||
msgstr "가입 요청"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:24
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:33
|
||||
msgid "Leave Requests"
|
||||
msgstr "탈퇴 요청"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:39
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:98
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:53
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
|
||||
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
|
||||
#: allianceauth/services/modules/openfire/forms.py:6
|
||||
msgid "Group"
|
||||
msgstr "그룹"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:71
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:130
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:85
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:144
|
||||
msgid "Accept"
|
||||
msgstr "수락"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:74
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:133
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:147
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:85
|
||||
msgid "Reject"
|
||||
msgstr "거절"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:83
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:97
|
||||
msgid "No group add requests."
|
||||
msgstr "가입 요청 없음"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:142
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:156
|
||||
msgid "No group leave requests."
|
||||
msgstr "탈퇴 요청 없음"
|
||||
|
||||
@@ -717,11 +733,6 @@ msgstr "탈퇴 요청 없음"
|
||||
msgid "Toggle navigation"
|
||||
msgstr "네비게이션 전환"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:23
|
||||
msgid "Group Management"
|
||||
msgstr "그룹 관리"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
|
||||
msgid "Group Requests"
|
||||
msgstr "그룹 요청"
|
||||
@@ -730,104 +741,104 @@ msgstr "그룹 요청"
|
||||
msgid "Group Membership"
|
||||
msgstr "그룹 멤버쉽"
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:166
|
||||
#: allianceauth/groupmanagement/views.py:162
|
||||
#, python-format
|
||||
msgid "Removed user %(user)s from group %(group)s."
|
||||
msgstr "유저 %(user)s이(가) %(group)s에서 제거됨."
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:168
|
||||
#: allianceauth/groupmanagement/views.py:164
|
||||
msgid "User does not exist in that group"
|
||||
msgstr "유저가 해당 그룹에 존재하지 않음."
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:171
|
||||
#: allianceauth/groupmanagement/views.py:167
|
||||
msgid "Group does not exist"
|
||||
msgstr "그룹이 존재하지 않음."
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:198
|
||||
#: allianceauth/groupmanagement/views.py:194
|
||||
#, python-format
|
||||
msgid "Accepted application from %(mainchar)s to %(group)s."
|
||||
msgstr "%(mainchar)s의 %(group)s 그룹 신청 수락"
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:205
|
||||
#: allianceauth/groupmanagement/views.py:238
|
||||
#: allianceauth/groupmanagement/views.py:201
|
||||
#: allianceauth/groupmanagement/views.py:234
|
||||
#, python-format
|
||||
msgid ""
|
||||
"An unhandled error occurred while processing the application from "
|
||||
"%(mainchar)s to %(group)s."
|
||||
msgstr "%(mainchar)s의 %(group)s 그룹 신청을 처리하는 중 알 수 없는 에러 발생"
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:231
|
||||
#: allianceauth/groupmanagement/views.py:227
|
||||
#, python-format
|
||||
msgid "Rejected application from %(mainchar)s to %(group)s."
|
||||
msgstr "%(mainchar)s의 %(group)s 그룹 신청 거절"
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:267
|
||||
#: allianceauth/groupmanagement/views.py:263
|
||||
#, python-format
|
||||
msgid "Accepted application from %(mainchar)s to leave %(group)s."
|
||||
msgstr "%(mainchar)s의 %(group)s 그룹 탈퇴 수락"
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:273
|
||||
#: allianceauth/groupmanagement/views.py:307
|
||||
#: allianceauth/groupmanagement/views.py:269
|
||||
#: allianceauth/groupmanagement/views.py:303
|
||||
#, python-format
|
||||
msgid ""
|
||||
"An unhandled error occurred while processing the application from "
|
||||
"%(mainchar)s to leave %(group)s."
|
||||
msgstr "%(mainchar)s의 %(group)s 그룹 탈퇴를 처리하는 중 알 수 없는 에러 발생"
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:300
|
||||
#: allianceauth/groupmanagement/views.py:296
|
||||
#, python-format
|
||||
msgid "Rejected application from %(mainchar)s to leave %(group)s."
|
||||
msgstr "%(mainchar)s의 %(group)s 그룹 탈퇴 거절"
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:346
|
||||
#: allianceauth/groupmanagement/views.py:358
|
||||
#: allianceauth/groupmanagement/views.py:342
|
||||
#: allianceauth/groupmanagement/views.py:354
|
||||
msgid "You cannot join that group"
|
||||
msgstr "해당 그룹에 참여할 수 없습니다."
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:352
|
||||
#: allianceauth/groupmanagement/views.py:348
|
||||
msgid "You are already a member of that group."
|
||||
msgstr "이미 해당 그룹에 가입되어 있습니다."
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:367
|
||||
#: allianceauth/groupmanagement/views.py:363
|
||||
msgid "You already have a pending application for that group."
|
||||
msgstr "해당 그룹에 대한 참여신청이 보류되었습니다."
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:370
|
||||
#: allianceauth/groupmanagement/views.py:408
|
||||
#: allianceauth/groupmanagement/views.py:366
|
||||
#: allianceauth/groupmanagement/views.py:404
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:37
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:72
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:99
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:144
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:38
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:20
|
||||
#: allianceauth/srp/templates/srp/data.html:125
|
||||
#: allianceauth/srp/templates/srp/data.html:134
|
||||
#: allianceauth/srp/templates/srp/management.html:81
|
||||
msgid "Pending"
|
||||
msgstr "보류 중"
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:376
|
||||
#: allianceauth/groupmanagement/views.py:372
|
||||
#, python-format
|
||||
msgid "Applied to group %(group)s."
|
||||
msgstr "%(group)s그룹에 지원하였음."
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:387
|
||||
#: allianceauth/groupmanagement/views.py:383
|
||||
msgid "You cannot leave that group"
|
||||
msgstr "해당 그룹을 떠날 수 없습니다."
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:392
|
||||
#: allianceauth/groupmanagement/views.py:388
|
||||
msgid "You are not a member of that group"
|
||||
msgstr "해당그룹의 멤버가 아닙니다."
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:401
|
||||
#: allianceauth/groupmanagement/views.py:397
|
||||
msgid "You already have a pending leave request for that group."
|
||||
msgstr "해당 그룹의 탈퇴 신청이 접수된 상태입니다."
|
||||
|
||||
#: allianceauth/groupmanagement/views.py:414
|
||||
#: allianceauth/groupmanagement/views.py:410
|
||||
#, python-format
|
||||
msgid "Applied to leave group %(group)s."
|
||||
msgstr "%(group)s그룹의 탈퇴가 신청됨."
|
||||
|
||||
#: allianceauth/hrapplications/auth_hooks.py:10
|
||||
#: allianceauth/hrapplications/auth_hooks.py:13
|
||||
msgid "Applications"
|
||||
msgstr "지원"
|
||||
|
||||
@@ -884,7 +895,7 @@ msgstr "사용자명"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:131
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:28
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:75
|
||||
#: allianceauth/srp/templates/srp/data.html:99
|
||||
#: allianceauth/srp/templates/srp/data.html:100
|
||||
#: allianceauth/srp/templates/srp/management.html:46
|
||||
msgid "Actions"
|
||||
msgstr "활동"
|
||||
@@ -894,7 +905,7 @@ msgstr "활동"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:147
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:40
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:16
|
||||
#: allianceauth/srp/templates/srp/data.html:117
|
||||
#: allianceauth/srp/templates/srp/data.html:126
|
||||
msgid "Approved"
|
||||
msgstr "승인"
|
||||
|
||||
@@ -902,7 +913,7 @@ msgstr "승인"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:104
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:149
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:42
|
||||
#: allianceauth/srp/templates/srp/data.html:121
|
||||
#: allianceauth/srp/templates/srp/data.html:130
|
||||
msgid "Rejected"
|
||||
msgstr "거절"
|
||||
|
||||
@@ -1285,23 +1296,50 @@ msgstr "비밀번호"
|
||||
msgid "Password must be at least 8 characters long."
|
||||
msgstr "비밀번호는 8글자 이상이어야 합니다."
|
||||
|
||||
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:23
|
||||
#: allianceauth/services/modules/discord/models.py:225
|
||||
msgid "Discord Account Disabled"
|
||||
msgstr "디스코드 계정 비활성화"
|
||||
|
||||
#: allianceauth/services/modules/discord/models.py:227
|
||||
msgid ""
|
||||
"Your Discord account was disabeled automatically by Auth. If you think this "
|
||||
"was a mistake, please contact an admin."
|
||||
msgstr "Auth에 의해 자동으로 디스코드 계정이 비활성화됐습니다. 원치 않는 사항일 경우, 관리자에게 문의해 주세요."
|
||||
|
||||
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:18
|
||||
msgid "Join the Discord server"
|
||||
msgstr "디스코드 서버 입장"
|
||||
|
||||
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:22
|
||||
msgid "Leave- and rejoin the Discord Server (Reset)"
|
||||
msgstr "디스코드 서버를 나가고 다시 입장하기 (리셋)"
|
||||
|
||||
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:25
|
||||
msgid "Leave the Discord server"
|
||||
msgstr "디스코드 서버 나가기"
|
||||
|
||||
#: allianceauth/services/modules/discord/templates/services/discord/discord_service_ctrl.html:32
|
||||
msgid "Link Discord Server"
|
||||
msgstr "디스코드 서버 링크"
|
||||
|
||||
#: allianceauth/services/modules/discord/views.py:26
|
||||
#: allianceauth/services/modules/discord/views.py:30
|
||||
msgid "Deactivated Discord account."
|
||||
msgstr "디스코드 계정 해제 완료"
|
||||
|
||||
#: allianceauth/services/modules/discord/views.py:29
|
||||
#: allianceauth/services/modules/discord/views.py:41
|
||||
#: allianceauth/services/modules/discord/views.py:65
|
||||
#: allianceauth/services/modules/discord/views.py:36
|
||||
#: allianceauth/services/modules/discord/views.py:59
|
||||
msgid "An error occurred while processing your Discord account."
|
||||
msgstr "디스코드 계정 처리 중 오류가 발생했습니다."
|
||||
|
||||
#: allianceauth/services/modules/discord/views.py:62
|
||||
msgid "Activated Discord account."
|
||||
msgstr "디스코드 계정 활성화 완료"
|
||||
#: allianceauth/services/modules/discord/views.py:102
|
||||
msgid "Your Discord account has been successfully activated."
|
||||
msgstr "디스코드 계정과 성공적으로 연동됐습니다."
|
||||
|
||||
#: allianceauth/services/modules/discord/views.py:108
|
||||
msgid ""
|
||||
"An error occurred while trying to activate your Discord account. Please try "
|
||||
"again."
|
||||
msgstr "디스코드 계정 연동 중 오류가 발생했습니다. 다시 시도해 주세요."
|
||||
|
||||
#: allianceauth/services/modules/discourse/views.py:37
|
||||
msgid "You are not authorized to access Discourse."
|
||||
@@ -1565,7 +1603,7 @@ msgstr "서드파티"
|
||||
msgid "Domain"
|
||||
msgstr "도메인"
|
||||
|
||||
#: allianceauth/srp/auth_hooks.py:9
|
||||
#: allianceauth/srp/auth_hooks.py:12
|
||||
msgid "Ship Replacement"
|
||||
msgstr "SRP"
|
||||
|
||||
@@ -1579,7 +1617,7 @@ msgstr "플릿 시간"
|
||||
msgid "Fleet Doctrine"
|
||||
msgstr "플릿 독트린"
|
||||
|
||||
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:89
|
||||
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:90
|
||||
msgid "Additional Info"
|
||||
msgstr "추가 기재 사항"
|
||||
|
||||
@@ -1608,63 +1646,63 @@ msgstr "SRP 보상 플릿 생성"
|
||||
msgid "Give this link to the line members"
|
||||
msgstr "이 링크를 직계 멤버들에게 전달"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:48
|
||||
#: allianceauth/srp/templates/srp/data.html:49
|
||||
msgid "SRP Fleet Data"
|
||||
msgstr "SRP 보상 플릿 데이터"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:53
|
||||
#: allianceauth/srp/templates/srp/data.html:54
|
||||
msgid "Mark Incomplete"
|
||||
msgstr "표시 미완료"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:57
|
||||
#: allianceauth/srp/templates/srp/data.html:58
|
||||
msgid "Mark Completed"
|
||||
msgstr "표시 완료"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:69
|
||||
#: allianceauth/srp/templates/srp/data.html:145
|
||||
#: allianceauth/srp/templates/srp/data.html:70
|
||||
#: allianceauth/srp/templates/srp/data.html:156
|
||||
msgid "Total Losses:"
|
||||
msgstr "전체 손실:"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:70
|
||||
#: allianceauth/srp/templates/srp/data.html:146
|
||||
#: allianceauth/srp/templates/srp/data.html:71
|
||||
#: allianceauth/srp/templates/srp/data.html:157
|
||||
#: allianceauth/srp/templates/srp/management.html:30
|
||||
msgid "Total ISK Cost:"
|
||||
msgstr "전체 ISK 비용:"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:78
|
||||
#: allianceauth/srp/templates/srp/data.html:154
|
||||
#: allianceauth/srp/templates/srp/data.html:79
|
||||
#: allianceauth/srp/templates/srp/data.html:165
|
||||
msgid "Are you sure you want to delete SRP requests?"
|
||||
msgstr "SRP 보상 요청을 삭제하시겠습니까?"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:87
|
||||
#: allianceauth/srp/templates/srp/data.html:88
|
||||
msgid "Pilot Name"
|
||||
msgstr "파일럿 이름"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:88
|
||||
#: allianceauth/srp/templates/srp/data.html:89
|
||||
msgid "Killboard Link"
|
||||
msgstr "킬보드 링크"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:90
|
||||
#: allianceauth/srp/templates/srp/data.html:91
|
||||
msgid "Ship Type"
|
||||
msgstr "함선 종류"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:91
|
||||
#: allianceauth/srp/templates/srp/data.html:92
|
||||
msgid "Killboard Loss Amt"
|
||||
msgstr "킬보드상 손실 금액"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:92
|
||||
#: allianceauth/srp/templates/srp/data.html:93
|
||||
msgid "SRP ISK Cost"
|
||||
msgstr "SRP 보상 비용"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:93
|
||||
#: allianceauth/srp/templates/srp/data.html:94
|
||||
msgid "Click value to edit Enter to save & next ESC to cancel"
|
||||
msgstr "금액을 수정하려면 클릭, 저장을 하고 다음으로 가려면 엔터, 취소를 하려면 ESC를 누르세요. "
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:96
|
||||
#: allianceauth/srp/templates/srp/data.html:97
|
||||
msgid "Post Time"
|
||||
msgstr "작성 시간"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:163
|
||||
#: allianceauth/srp/templates/srp/data.html:174
|
||||
msgid "No SRP requests for this fleet."
|
||||
msgstr "이 플릿에는 SRP 보상 요청이 없습니다."
|
||||
|
||||
@@ -1856,32 +1894,30 @@ msgid "Current"
|
||||
msgstr "현재"
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:40
|
||||
msgid "Latest Major"
|
||||
msgstr "최근 주요 사항"
|
||||
msgid "Latest Stable"
|
||||
msgstr "최신 안정화 버전"
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:46
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:56
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:66
|
||||
msgid "Update available"
|
||||
msgstr "업데이트 가능"
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:50
|
||||
msgid "Latest Minor"
|
||||
msgstr "최근 기타 사항"
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:51
|
||||
msgid "Latest Pre-Release"
|
||||
msgstr "최신 사전 출시 버전"
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:60
|
||||
msgid "Latest Patch"
|
||||
msgstr "최근 패치"
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:57
|
||||
msgid "Pre-Release available"
|
||||
msgstr "사전 출시 사용 가능"
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:73
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:65
|
||||
msgid "Task Queue"
|
||||
msgstr "대기 중인 할 일"
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:90
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:82
|
||||
msgid "Error retrieving task queue length"
|
||||
msgstr "대기 중인 할 일 목록 회수 에러"
|
||||
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:92
|
||||
#: allianceauth/templates/allianceauth/admin-status/overview.html:84
|
||||
#, python-format
|
||||
msgid "%(tasks)s task"
|
||||
msgid_plural "%(tasks)s tasks"
|
||||
|
||||
@@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-07-29 04:56+0000\n"
|
||||
"POT-Creation-Date: 2020-10-11 03:43+0000\n"
|
||||
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
||||
"Last-Translator: Alexander Gess <de.alex.gess@gmail.com>, 2020\n"
|
||||
"Language-Team: Russian (https://www.transifex.com/alliance-auth/teams/107430/ru/)\n"
|
||||
@@ -25,7 +25,7 @@ msgstr ""
|
||||
msgid "A main character is required to perform that action. Add one below."
|
||||
msgstr "Необходимо указать основного персонажа. Добавим?"
|
||||
|
||||
#: allianceauth/authentication/forms.py:6
|
||||
#: allianceauth/authentication/forms.py:5
|
||||
msgid "Email"
|
||||
msgstr "Email"
|
||||
|
||||
@@ -41,7 +41,7 @@ msgstr "Статус пилота: %(state)s"
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:5
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:8
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:12
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:11
|
||||
msgid "Dashboard"
|
||||
msgstr "Панель показателей"
|
||||
|
||||
@@ -163,21 +163,21 @@ msgstr "Персонаж %(name)s уже добавлен."
|
||||
msgid "Unable to authenticate as the selected character."
|
||||
msgstr "Невозможно авторизировать этого персонажа. "
|
||||
|
||||
#: allianceauth/authentication/views.py:148
|
||||
#: allianceauth/authentication/views.py:146
|
||||
msgid "Registration token has expired."
|
||||
msgstr "Регистрационный токен просрочен."
|
||||
|
||||
#: allianceauth/authentication/views.py:200
|
||||
#: allianceauth/authentication/views.py:201
|
||||
msgid ""
|
||||
"Sent confirmation email. Please follow the link to confirm your email "
|
||||
"address."
|
||||
msgstr "Отправить подтверждающее письмо. Пожалуйста, подтвердите почту. "
|
||||
|
||||
#: allianceauth/authentication/views.py:205
|
||||
#: allianceauth/authentication/views.py:206
|
||||
msgid "Confirmed your email address. Please login to continue."
|
||||
msgstr "Подтвердите Ваш email адрес. Зайти для подтверждения. "
|
||||
|
||||
#: allianceauth/authentication/views.py:210
|
||||
#: allianceauth/authentication/views.py:211
|
||||
msgid "Registraion of new accounts it not allowed at this time."
|
||||
msgstr "Регистрация нового аккаунта сейчас невозможна."
|
||||
|
||||
@@ -548,6 +548,11 @@ msgstr "Флотовое участие зарегистрированно."
|
||||
msgid "FAT link has expired."
|
||||
msgstr "ФлАк ссылка устарела"
|
||||
|
||||
#: allianceauth/groupmanagement/auth_hooks.py:16
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
||||
msgid "Group Management"
|
||||
msgstr "Управление Группой"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
|
||||
msgid "Audit Log"
|
||||
@@ -620,7 +625,7 @@ msgstr "Участники группы"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
|
||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:17
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:16
|
||||
msgid "Groups"
|
||||
msgstr "Группы"
|
||||
|
||||
@@ -634,7 +639,7 @@ msgstr "Описание"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:27
|
||||
#: allianceauth/srp/templates/srp/data.html:97
|
||||
#: allianceauth/srp/templates/srp/data.html:98
|
||||
msgid "Status"
|
||||
msgstr "Статус"
|
||||
|
||||
@@ -734,11 +739,6 @@ msgstr "Нет групповых запросов на выход"
|
||||
msgid "Toggle navigation"
|
||||
msgstr "Проложить маршрут"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:25
|
||||
msgid "Group Management"
|
||||
msgstr "Управление Группой"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
|
||||
msgid "Group Requests"
|
||||
msgstr "Групповой запрос"
|
||||
@@ -821,7 +821,7 @@ msgstr "Вы уже подали заявку на вступление этой
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:144
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:38
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:20
|
||||
#: allianceauth/srp/templates/srp/data.html:125
|
||||
#: allianceauth/srp/templates/srp/data.html:134
|
||||
#: allianceauth/srp/templates/srp/management.html:81
|
||||
msgid "Pending"
|
||||
msgstr "Ожидание"
|
||||
@@ -848,7 +848,7 @@ msgstr "Ваш запрос находится на рассмотрении"
|
||||
msgid "Applied to leave group %(group)s."
|
||||
msgstr "Запрос на выход из группы %(group)s."
|
||||
|
||||
#: allianceauth/hrapplications/auth_hooks.py:10
|
||||
#: allianceauth/hrapplications/auth_hooks.py:13
|
||||
msgid "Applications"
|
||||
msgstr "Запросы"
|
||||
|
||||
@@ -905,7 +905,7 @@ msgstr "Пользователь"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:131
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:28
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:75
|
||||
#: allianceauth/srp/templates/srp/data.html:99
|
||||
#: allianceauth/srp/templates/srp/data.html:100
|
||||
#: allianceauth/srp/templates/srp/management.html:46
|
||||
msgid "Actions"
|
||||
msgstr "Действия"
|
||||
@@ -915,7 +915,7 @@ msgstr "Действия"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:147
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:40
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:16
|
||||
#: allianceauth/srp/templates/srp/data.html:117
|
||||
#: allianceauth/srp/templates/srp/data.html:126
|
||||
msgid "Approved"
|
||||
msgstr "Проверено"
|
||||
|
||||
@@ -923,7 +923,7 @@ msgstr "Проверено"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:104
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:149
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:42
|
||||
#: allianceauth/srp/templates/srp/data.html:121
|
||||
#: allianceauth/srp/templates/srp/data.html:130
|
||||
msgid "Rejected"
|
||||
msgstr "Отменено "
|
||||
|
||||
@@ -1306,11 +1306,11 @@ msgstr "Пароль"
|
||||
msgid "Password must be at least 8 characters long."
|
||||
msgstr "Пароль должен быть не менее 8 символов."
|
||||
|
||||
#: allianceauth/services/modules/discord/models.py:224
|
||||
#: allianceauth/services/modules/discord/models.py:225
|
||||
msgid "Discord Account Disabled"
|
||||
msgstr "Discord персонаж отключен"
|
||||
|
||||
#: allianceauth/services/modules/discord/models.py:226
|
||||
#: allianceauth/services/modules/discord/models.py:227
|
||||
msgid ""
|
||||
"Your Discord account was disabeled automatically by Auth. If you think this "
|
||||
"was a mistake, please contact an admin."
|
||||
@@ -1623,7 +1623,7 @@ msgstr "Сервис"
|
||||
msgid "Domain"
|
||||
msgstr "Домен"
|
||||
|
||||
#: allianceauth/srp/auth_hooks.py:9
|
||||
#: allianceauth/srp/auth_hooks.py:12
|
||||
msgid "Ship Replacement"
|
||||
msgstr "Замена корабля"
|
||||
|
||||
@@ -1637,7 +1637,7 @@ msgstr "Флотовое время"
|
||||
msgid "Fleet Doctrine"
|
||||
msgstr "Флотовая Доктрина"
|
||||
|
||||
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:89
|
||||
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:90
|
||||
msgid "Additional Info"
|
||||
msgstr "Дополнительная информация"
|
||||
|
||||
@@ -1666,63 +1666,63 @@ msgstr "Создать SRP Флот"
|
||||
msgid "Give this link to the line members"
|
||||
msgstr "Поделиться ссылкой с рядовыми участниками"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:48
|
||||
#: allianceauth/srp/templates/srp/data.html:49
|
||||
msgid "SRP Fleet Data"
|
||||
msgstr "SRP данные флота"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:53
|
||||
#: allianceauth/srp/templates/srp/data.html:54
|
||||
msgid "Mark Incomplete"
|
||||
msgstr "Пометить незаконченным"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:57
|
||||
#: allianceauth/srp/templates/srp/data.html:58
|
||||
msgid "Mark Completed"
|
||||
msgstr "Пометить законченным"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:69
|
||||
#: allianceauth/srp/templates/srp/data.html:145
|
||||
#: allianceauth/srp/templates/srp/data.html:70
|
||||
#: allianceauth/srp/templates/srp/data.html:156
|
||||
msgid "Total Losses:"
|
||||
msgstr "Суммарные потери:"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:70
|
||||
#: allianceauth/srp/templates/srp/data.html:146
|
||||
#: allianceauth/srp/templates/srp/data.html:71
|
||||
#: allianceauth/srp/templates/srp/data.html:157
|
||||
#: allianceauth/srp/templates/srp/management.html:30
|
||||
msgid "Total ISK Cost:"
|
||||
msgstr "Оценочная стоимость (ISK):"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:78
|
||||
#: allianceauth/srp/templates/srp/data.html:154
|
||||
#: allianceauth/srp/templates/srp/data.html:79
|
||||
#: allianceauth/srp/templates/srp/data.html:165
|
||||
msgid "Are you sure you want to delete SRP requests?"
|
||||
msgstr "Вы уверенны что хотите удалить запрос на SRP?"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:87
|
||||
#: allianceauth/srp/templates/srp/data.html:88
|
||||
msgid "Pilot Name"
|
||||
msgstr "Имя Пилота"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:88
|
||||
#: allianceauth/srp/templates/srp/data.html:89
|
||||
msgid "Killboard Link"
|
||||
msgstr "zKillBoard ссылка"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:90
|
||||
#: allianceauth/srp/templates/srp/data.html:91
|
||||
msgid "Ship Type"
|
||||
msgstr "Тип корабля"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:91
|
||||
#: allianceauth/srp/templates/srp/data.html:92
|
||||
msgid "Killboard Loss Amt"
|
||||
msgstr "потерь по zKillBoard на данный момент"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:92
|
||||
#: allianceauth/srp/templates/srp/data.html:93
|
||||
msgid "SRP ISK Cost"
|
||||
msgstr "SRP ISK Стоимость"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:93
|
||||
#: allianceauth/srp/templates/srp/data.html:94
|
||||
msgid "Click value to edit Enter to save & next ESC to cancel"
|
||||
msgstr "Нажмите на значение для редактирования и ESC для отмены"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:96
|
||||
#: allianceauth/srp/templates/srp/data.html:97
|
||||
msgid "Post Time"
|
||||
msgstr "Опубликованно"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:163
|
||||
#: allianceauth/srp/templates/srp/data.html:174
|
||||
msgid "No SRP requests for this fleet."
|
||||
msgstr "SRP запросы отсутствуют"
|
||||
|
||||
|
||||
Binary file not shown.
@@ -4,18 +4,18 @@
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
# Translators:
|
||||
# Joel Falknau <ozirascal@gmail.com>, 2020
|
||||
# Jesse . <sgeine@hotmail.com>, 2020
|
||||
# Aaron BuBu <351793078@qq.com>, 2020
|
||||
# Joel Falknau <ozirascal@gmail.com>, 2020
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-07-29 03:24+0000\n"
|
||||
"POT-Creation-Date: 2020-10-11 03:43+0000\n"
|
||||
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
|
||||
"Last-Translator: Aaron BuBu <351793078@qq.com>, 2020\n"
|
||||
"Last-Translator: Joel Falknau <ozirascal@gmail.com>, 2020\n"
|
||||
"Language-Team: Chinese Simplified (https://www.transifex.com/alliance-auth/teams/107430/zh-Hans/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -27,7 +27,7 @@ msgstr ""
|
||||
msgid "A main character is required to perform that action. Add one below."
|
||||
msgstr "只有主要角色才能执行这个操作。在下面添加一个"
|
||||
|
||||
#: allianceauth/authentication/forms.py:6
|
||||
#: allianceauth/authentication/forms.py:5
|
||||
msgid "Email"
|
||||
msgstr "电子邮箱"
|
||||
|
||||
@@ -43,7 +43,7 @@ msgstr ""
|
||||
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:5
|
||||
#: allianceauth/authentication/templates/authentication/dashboard.html:8
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:12
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:11
|
||||
msgid "Dashboard"
|
||||
msgstr "账户总览"
|
||||
|
||||
@@ -159,21 +159,21 @@ msgstr "添加%(name)s到您的账户失败:他们已经在一个账户中了"
|
||||
msgid "Unable to authenticate as the selected character."
|
||||
msgstr "无法作为选定的角色进行身份验证"
|
||||
|
||||
#: allianceauth/authentication/views.py:148
|
||||
#: allianceauth/authentication/views.py:146
|
||||
msgid "Registration token has expired."
|
||||
msgstr "注册令牌过期。"
|
||||
|
||||
#: allianceauth/authentication/views.py:200
|
||||
#: allianceauth/authentication/views.py:201
|
||||
msgid ""
|
||||
"Sent confirmation email. Please follow the link to confirm your email "
|
||||
"address."
|
||||
msgstr "已经发送了确认邮件。请按照链接确定您的电邮地址"
|
||||
|
||||
#: allianceauth/authentication/views.py:205
|
||||
#: allianceauth/authentication/views.py:206
|
||||
msgid "Confirmed your email address. Please login to continue."
|
||||
msgstr "已确认您的电邮地址。请登录以继续"
|
||||
|
||||
#: allianceauth/authentication/views.py:210
|
||||
#: allianceauth/authentication/views.py:211
|
||||
msgid "Registraion of new accounts it not allowed at this time."
|
||||
msgstr "现在不允许注册新账户。"
|
||||
|
||||
@@ -538,6 +538,11 @@ msgstr "成功注册舰队PAP"
|
||||
msgid "FAT link has expired."
|
||||
msgstr "PAP链接已过期"
|
||||
|
||||
#: allianceauth/groupmanagement/auth_hooks.py:16
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
||||
msgid "Group Management"
|
||||
msgstr "用户组管理"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:5
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:13
|
||||
msgid "Audit Log"
|
||||
@@ -610,7 +615,7 @@ msgstr "用户组成员"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html:14
|
||||
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:40
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:17
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:16
|
||||
msgid "Groups"
|
||||
msgstr "群组"
|
||||
|
||||
@@ -624,7 +629,7 @@ msgstr "描述"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:85
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:130
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:27
|
||||
#: allianceauth/srp/templates/srp/data.html:97
|
||||
#: allianceauth/srp/templates/srp/data.html:98
|
||||
msgid "Status"
|
||||
msgstr "状态"
|
||||
|
||||
@@ -724,11 +729,6 @@ msgstr "没有离开用户组的请求,小老弟你人缘可以啊?"
|
||||
msgid "Toggle navigation"
|
||||
msgstr "打开导航栏"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:15
|
||||
#: allianceauth/templates/allianceauth/side-menu.html:25
|
||||
msgid "Group Management"
|
||||
msgstr "用户组管理"
|
||||
|
||||
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:21
|
||||
msgid "Group Requests"
|
||||
msgstr "用户组请求"
|
||||
@@ -807,7 +807,7 @@ msgstr "你已经有了该组的未决申请"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:144
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:38
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:20
|
||||
#: allianceauth/srp/templates/srp/data.html:125
|
||||
#: allianceauth/srp/templates/srp/data.html:134
|
||||
#: allianceauth/srp/templates/srp/management.html:81
|
||||
msgid "Pending"
|
||||
msgstr "待定"
|
||||
@@ -834,7 +834,7 @@ msgstr "你已经有了该组的未决离开请求"
|
||||
msgid "Applied to leave group %(group)s."
|
||||
msgstr "已经离开群组%(group)s"
|
||||
|
||||
#: allianceauth/hrapplications/auth_hooks.py:10
|
||||
#: allianceauth/hrapplications/auth_hooks.py:13
|
||||
msgid "Applications"
|
||||
msgstr "申请"
|
||||
|
||||
@@ -891,7 +891,7 @@ msgstr "用户名"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:131
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:28
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:75
|
||||
#: allianceauth/srp/templates/srp/data.html:99
|
||||
#: allianceauth/srp/templates/srp/data.html:100
|
||||
#: allianceauth/srp/templates/srp/management.html:46
|
||||
msgid "Actions"
|
||||
msgstr "操作"
|
||||
@@ -901,7 +901,7 @@ msgstr "操作"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:147
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:40
|
||||
#: allianceauth/hrapplications/templates/hrapplications/view.html:16
|
||||
#: allianceauth/srp/templates/srp/data.html:117
|
||||
#: allianceauth/srp/templates/srp/data.html:126
|
||||
msgid "Approved"
|
||||
msgstr "通过"
|
||||
|
||||
@@ -909,7 +909,7 @@ msgstr "通过"
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:104
|
||||
#: allianceauth/hrapplications/templates/hrapplications/management.html:149
|
||||
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:42
|
||||
#: allianceauth/srp/templates/srp/data.html:121
|
||||
#: allianceauth/srp/templates/srp/data.html:130
|
||||
msgid "Rejected"
|
||||
msgstr "拒绝"
|
||||
|
||||
@@ -1292,11 +1292,11 @@ msgstr "密码"
|
||||
msgid "Password must be at least 8 characters long."
|
||||
msgstr "密码至少要有8个字符啊,你也太不注重安全啦"
|
||||
|
||||
#: allianceauth/services/modules/discord/models.py:224
|
||||
#: allianceauth/services/modules/discord/models.py:225
|
||||
msgid "Discord Account Disabled"
|
||||
msgstr ""
|
||||
|
||||
#: allianceauth/services/modules/discord/models.py:226
|
||||
#: allianceauth/services/modules/discord/models.py:227
|
||||
msgid ""
|
||||
"Your Discord account was disabeled automatically by Auth. If you think this "
|
||||
"was a mistake, please contact an admin."
|
||||
@@ -1599,7 +1599,7 @@ msgstr "服务"
|
||||
msgid "Domain"
|
||||
msgstr "域名"
|
||||
|
||||
#: allianceauth/srp/auth_hooks.py:9
|
||||
#: allianceauth/srp/auth_hooks.py:12
|
||||
msgid "Ship Replacement"
|
||||
msgstr "补损"
|
||||
|
||||
@@ -1613,7 +1613,7 @@ msgstr "集结时间"
|
||||
msgid "Fleet Doctrine"
|
||||
msgstr "舰队船型"
|
||||
|
||||
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:89
|
||||
#: allianceauth/srp/form.py:12 allianceauth/srp/templates/srp/data.html:90
|
||||
msgid "Additional Info"
|
||||
msgstr "其他信息"
|
||||
|
||||
@@ -1642,63 +1642,63 @@ msgstr "创建补损舰队"
|
||||
msgid "Give this link to the line members"
|
||||
msgstr "把这个链接发送给火力狗们"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:48
|
||||
#: allianceauth/srp/templates/srp/data.html:49
|
||||
msgid "SRP Fleet Data"
|
||||
msgstr "舰队补损信息"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:53
|
||||
#: allianceauth/srp/templates/srp/data.html:54
|
||||
msgid "Mark Incomplete"
|
||||
msgstr "标记为未完成"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:57
|
||||
#: allianceauth/srp/templates/srp/data.html:58
|
||||
msgid "Mark Completed"
|
||||
msgstr "标记为已完成"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:69
|
||||
#: allianceauth/srp/templates/srp/data.html:145
|
||||
#: allianceauth/srp/templates/srp/data.html:70
|
||||
#: allianceauth/srp/templates/srp/data.html:156
|
||||
msgid "Total Losses:"
|
||||
msgstr "损失总额:"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:70
|
||||
#: allianceauth/srp/templates/srp/data.html:146
|
||||
#: allianceauth/srp/templates/srp/data.html:71
|
||||
#: allianceauth/srp/templates/srp/data.html:157
|
||||
#: allianceauth/srp/templates/srp/management.html:30
|
||||
msgid "Total ISK Cost:"
|
||||
msgstr "ISK花费总额:"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:78
|
||||
#: allianceauth/srp/templates/srp/data.html:154
|
||||
#: allianceauth/srp/templates/srp/data.html:79
|
||||
#: allianceauth/srp/templates/srp/data.html:165
|
||||
msgid "Are you sure you want to delete SRP requests?"
|
||||
msgstr "老哥,你确定要删了补损请求么?"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:87
|
||||
#: allianceauth/srp/templates/srp/data.html:88
|
||||
msgid "Pilot Name"
|
||||
msgstr "玩家ID"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:88
|
||||
#: allianceauth/srp/templates/srp/data.html:89
|
||||
msgid "Killboard Link"
|
||||
msgstr "KB网链接"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:90
|
||||
#: allianceauth/srp/templates/srp/data.html:91
|
||||
msgid "Ship Type"
|
||||
msgstr "船型"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:91
|
||||
#: allianceauth/srp/templates/srp/data.html:92
|
||||
msgid "Killboard Loss Amt"
|
||||
msgstr "KB网总损失"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:92
|
||||
#: allianceauth/srp/templates/srp/data.html:93
|
||||
msgid "SRP ISK Cost"
|
||||
msgstr "补损ISK花费"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:93
|
||||
#: allianceauth/srp/templates/srp/data.html:94
|
||||
msgid "Click value to edit Enter to save & next ESC to cancel"
|
||||
msgstr "点击数值就可以编辑啦,按回车确认,按ESC取消"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:96
|
||||
#: allianceauth/srp/templates/srp/data.html:97
|
||||
msgid "Post Time"
|
||||
msgstr "发布时间"
|
||||
|
||||
#: allianceauth/srp/templates/srp/data.html:163
|
||||
#: allianceauth/srp/templates/srp/data.html:174
|
||||
msgid "No SRP requests for this fleet."
|
||||
msgstr "这次起队没有补损请求!大捷"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Notifications" %}{% endblock %}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "View Notification" %}{% endblock page_title %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% get_current_language as LANGUAGE_CODE %}
|
||||
|
||||
@@ -36,9 +36,15 @@
|
||||
{% block extra_script %}
|
||||
|
||||
$('#id_start').datetimepicker({
|
||||
lang: '{{ LANGUAGE_CODE }}',
|
||||
maskInput: true,
|
||||
format: 'Y-m-d H:i',minDate:0
|
||||
setlocale: '{{ LANGUAGE_CODE }}',
|
||||
{% if NIGHT_MODE %}
|
||||
theme: 'dark',
|
||||
{% else %}
|
||||
theme: 'default',
|
||||
{% endif %}
|
||||
mask: true,
|
||||
format: 'Y-m-d H:i',
|
||||
minDate: 0
|
||||
});
|
||||
|
||||
{% endblock extra_script %}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% get_current_language as LANGUAGE_CODE %}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
{% include 'bundles/moment-js.html' with locale=True %}
|
||||
<script src="{% static 'js/timers.js' %}"></script>
|
||||
<script type="text/javascript">
|
||||
<script type="application/javascript">
|
||||
// Data
|
||||
var timers = [
|
||||
{% for op in optimer %}
|
||||
@@ -53,7 +53,7 @@
|
||||
{% endfor %}
|
||||
];
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
<script type="application/javascript">
|
||||
|
||||
timedUpdate();
|
||||
setAllLocalTimes();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% get_current_language as LANGUAGE_CODE %}
|
||||
|
||||
@@ -44,9 +44,15 @@
|
||||
{% block extra_script %}
|
||||
|
||||
$('#id_start').datetimepicker({
|
||||
lang: '{{ LANGUAGE_CODE }}',
|
||||
maskInput: true,
|
||||
format: 'Y-m-d H:i',minDate:0
|
||||
setlocale: '{{ LANGUAGE_CODE }}',
|
||||
{% if NIGHT_MODE %}
|
||||
theme: 'dark',
|
||||
{% else %}
|
||||
theme: 'default',
|
||||
{% endif %}
|
||||
mask: true,
|
||||
format: 'Y-m-d H:i',
|
||||
minDate: 0
|
||||
});
|
||||
|
||||
{% endblock extra_script %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{{ permission.permission.codename }} - {% trans "Permissions Audit" %}{% endblock page_title %}
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
{% block extra_javascript %}
|
||||
{% include 'bundles/datatables-js.html' %}
|
||||
<script type="text/javascript" src="{% static 'js/filterDropDown/filterDropDown.min.js' %}"></script>
|
||||
<script type="application/javascript" src="{% static 'js/filterDropDown/filterDropDown.min.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Permissions Overview" %}{% endblock page_title %}
|
||||
@@ -80,7 +80,7 @@
|
||||
|
||||
{% block extra_javascript %}
|
||||
{% include 'bundles/datatables-js.html' %}
|
||||
<script type="text/javascript" src="{% static 'js/filterDropDown/filterDropDown.min.js' %}"></script>
|
||||
<script type="application/javascript" src="{% static 'js/filterDropDown/filterDropDown.min.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import os
|
||||
from celery import Celery
|
||||
from celery.app import trace
|
||||
|
||||
# set the default Django settings module for the 'celery' program.
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', '{{ project_name }}.settings.local')
|
||||
@@ -27,3 +28,6 @@ app.conf.ONCE = {
|
||||
|
||||
# Load task modules from all registered Django app configs.
|
||||
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
|
||||
|
||||
# Remove result from default log message on task success
|
||||
trace.LOG_SUCCESS = "Task %(name)s[%(id)s] succeeded in %(runtime)ss"
|
||||
|
||||
@@ -64,12 +64,12 @@ BASE_DIR = os.path.dirname(PROJECT_DIR)
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.locale.LocaleMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'django.middleware.locale.LocaleMiddleware',
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'allianceauth.urls'
|
||||
@@ -86,6 +86,8 @@ LANGUAGES = (
|
||||
('zh-hans', ugettext('Chinese Simplified')),
|
||||
('ru', ugettext('Russian')),
|
||||
('ko', ugettext('Korean')),
|
||||
('fr', ugettext('French')),
|
||||
('ja', ugettext('Japanese')),
|
||||
)
|
||||
|
||||
TEMPLATES = [
|
||||
@@ -138,6 +140,8 @@ AUTHENTICATION_BACKENDS = ['allianceauth.authentication.backends.StateBackend',
|
||||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
LANGUAGE_COOKIE_AGE = 1209600
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
@@ -45,6 +45,7 @@ DATABASES['default'] = {
|
||||
ESI_SSO_CLIENT_ID = ''
|
||||
ESI_SSO_CLIENT_SECRET = ''
|
||||
ESI_SSO_CALLBACK_URL = ''
|
||||
ESI_USER_CONTACT_EMAIL = '' # A server maintainer that CCP can contact in case of issues.
|
||||
|
||||
# By default emails are validated before new users can log in.
|
||||
# It's recommended to use a free service like SparkPost or Elastic Email to send email.
|
||||
|
||||
@@ -139,6 +139,11 @@ class MenuItemHook:
|
||||
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
|
||||
|
||||
@@ -3,7 +3,7 @@ from ..utils import clean_setting
|
||||
|
||||
# Base URL for all API calls. Must end with /.
|
||||
DISCORD_API_BASE_URL = clean_setting(
|
||||
'DISCORD_API_BASE_URL', 'https://discordapp.com/api/'
|
||||
'DISCORD_API_BASE_URL', 'https://discord.com/api/'
|
||||
)
|
||||
|
||||
# Low level connecttimeout for requests to the Discord API in seconds
|
||||
@@ -18,12 +18,12 @@ DISCORD_API_TIMEOUT_READ = clean_setting(
|
||||
|
||||
# Base authorization URL for Discord Oauth
|
||||
DISCORD_OAUTH_BASE_URL = clean_setting(
|
||||
'DISCORD_OAUTH_BASE_URL', 'https://discordapp.com/api/oauth2/authorize'
|
||||
'DISCORD_OAUTH_BASE_URL', 'https://discord.com/api/oauth2/authorize'
|
||||
)
|
||||
|
||||
# Base authorization URL for Discord Oauth
|
||||
DISCORD_OAUTH_TOKEN_URL = clean_setting(
|
||||
'DISCORD_OAUTH_TOKEN_URL', 'https://discordapp.com/api/oauth2/token'
|
||||
'DISCORD_OAUTH_TOKEN_URL', 'https://discord.com/api/oauth2/token'
|
||||
)
|
||||
|
||||
# How long the Discord guild names retrieved from the server are
|
||||
|
||||
@@ -33,7 +33,7 @@ logger = set_logger_to_file(
|
||||
)
|
||||
|
||||
MODULE_PATH = 'allianceauth.services.modules.discord.discord_client.client'
|
||||
API_BASE_URL = 'https://discordapp.com/api/'
|
||||
API_BASE_URL = 'https://discord.com/api/'
|
||||
|
||||
TEST_RETRY_AFTER = 3000
|
||||
|
||||
|
||||
@@ -211,6 +211,7 @@ class DiscordUser(models.Model):
|
||||
Return None if user does no longer exist
|
||||
"""
|
||||
try:
|
||||
_user = self.user
|
||||
client = DiscordUser.objects._bot_client(is_rate_limited=is_rate_limited)
|
||||
success = client.remove_guild_member(
|
||||
guild_id=DISCORD_GUILD_ID, user_id=self.uid
|
||||
@@ -220,31 +221,31 @@ class DiscordUser(models.Model):
|
||||
if deleted_count > 0:
|
||||
if notify_user:
|
||||
notify(
|
||||
user=self.user,
|
||||
user=_user,
|
||||
title=gettext_lazy('Discord Account Disabled'),
|
||||
message=gettext_lazy(
|
||||
'Your Discord account was disabeled automatically '
|
||||
'Your Discord account was disabled automatically '
|
||||
'by Auth. If you think this was a mistake, '
|
||||
'please contact an admin.'
|
||||
),
|
||||
level='warning'
|
||||
)
|
||||
logger.info('Account for user %s was deleted.', self.user)
|
||||
logger.info('Account for user %s was deleted.', _user)
|
||||
return True
|
||||
else:
|
||||
logger.debug('Account for user %s was already deleted.', self.user)
|
||||
logger.debug('Account for user %s was already deleted.', _user)
|
||||
return None
|
||||
|
||||
else:
|
||||
logger.warning(
|
||||
'Failed to remove user %s from the Discord server', self.user
|
||||
'Failed to remove user %s from the Discord server', _user
|
||||
)
|
||||
return False
|
||||
|
||||
except (HTTPError, ConnectionError, DiscordApiBackoff) as ex:
|
||||
if handle_api_exceptions:
|
||||
logger.exception(
|
||||
'Failed to remove user %s from Discord server: %s', self.user, ex
|
||||
'Failed to remove user %s from Discord server: %s',self.user, ex
|
||||
)
|
||||
return False
|
||||
else:
|
||||
|
||||
@@ -4,7 +4,7 @@ import re
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from hashlib import md5
|
||||
|
||||
from . import providers
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
GROUP_CACHE_MAX_AGE = getattr(settings, 'DISCOURSE_GROUP_CACHE_MAX_AGE', 2 * 60 * 60) # default 2 hours
|
||||
@@ -19,128 +19,8 @@ class DiscourseError(Exception):
|
||||
return "API execution failed.\nErrors: %s\nEndpoint: %s" % (self.errors, self.endpoint)
|
||||
|
||||
|
||||
# not exhaustive, only the ones we need
|
||||
ENDPOINTS = {
|
||||
'groups': {
|
||||
'list': {
|
||||
'path': "/groups/search.json",
|
||||
'method': 'get',
|
||||
'args': {
|
||||
'required': [],
|
||||
'optional': [],
|
||||
},
|
||||
},
|
||||
'create': {
|
||||
'path': "/admin/groups",
|
||||
'method': 'post',
|
||||
'args': {
|
||||
'required': ['name'],
|
||||
'optional': ['visible'],
|
||||
}
|
||||
},
|
||||
'add_user': {
|
||||
'path': "/admin/groups/%s/members.json",
|
||||
'method': 'put',
|
||||
'args': {
|
||||
'required': ['usernames'],
|
||||
'optional': [],
|
||||
},
|
||||
},
|
||||
'remove_user': {
|
||||
'path': "/admin/groups/%s/members.json",
|
||||
'method': 'delete',
|
||||
'args': {
|
||||
'required': ['username'],
|
||||
'optional': [],
|
||||
},
|
||||
},
|
||||
'delete': {
|
||||
'path': "/admin/groups/%s.json",
|
||||
'method': 'delete',
|
||||
'args': {
|
||||
'required': [],
|
||||
'optional': [],
|
||||
},
|
||||
},
|
||||
},
|
||||
'users': {
|
||||
'create': {
|
||||
'path': "/users",
|
||||
'method': 'post',
|
||||
'args': {
|
||||
'required': ['name', 'email', 'password', 'username'],
|
||||
'optional': ['active'],
|
||||
},
|
||||
},
|
||||
'update': {
|
||||
'path': "/users/%s.json",
|
||||
'method': 'put',
|
||||
'args': {
|
||||
'required': ['params'],
|
||||
'optional': [],
|
||||
}
|
||||
},
|
||||
'get': {
|
||||
'path': "/users/%s.json",
|
||||
'method': 'get',
|
||||
'args': {
|
||||
'required': [],
|
||||
'optional': [],
|
||||
},
|
||||
},
|
||||
'activate': {
|
||||
'path': "/admin/users/%s/activate",
|
||||
'method': 'put',
|
||||
'args': {
|
||||
'required': [],
|
||||
'optional': [],
|
||||
},
|
||||
},
|
||||
'set_email': {
|
||||
'path': "/users/%s/preferences/email",
|
||||
'method': 'put',
|
||||
'args': {
|
||||
'required': ['email'],
|
||||
'optional': [],
|
||||
},
|
||||
},
|
||||
'suspend': {
|
||||
'path': "/admin/users/%s/suspend",
|
||||
'method': 'put',
|
||||
'args': {
|
||||
'required': ['duration', 'reason'],
|
||||
'optional': [],
|
||||
},
|
||||
},
|
||||
'unsuspend': {
|
||||
'path': "/admin/users/%s/unsuspend",
|
||||
'method': 'put',
|
||||
'args': {
|
||||
'required': [],
|
||||
'optional': [],
|
||||
},
|
||||
},
|
||||
'logout': {
|
||||
'path': "/admin/users/%s/log_out",
|
||||
'method': 'post',
|
||||
'args': {
|
||||
'required': [],
|
||||
'optional': [],
|
||||
},
|
||||
},
|
||||
'external': {
|
||||
'path': "/users/by-external/%s.json",
|
||||
'method': 'get',
|
||||
'args': {
|
||||
'required': [],
|
||||
'optional': [],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class DiscourseManager:
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@@ -148,55 +28,14 @@ class DiscourseManager:
|
||||
SUSPEND_DAYS = 99999
|
||||
SUSPEND_REASON = "Disabled by auth."
|
||||
|
||||
@staticmethod
|
||||
def __exc(endpoint, *args, **kwargs):
|
||||
params = {
|
||||
'api_key': settings.DISCOURSE_API_KEY,
|
||||
'api_username': settings.DISCOURSE_API_USERNAME,
|
||||
}
|
||||
silent = kwargs.pop('silent', False)
|
||||
if args:
|
||||
endpoint['parsed_url'] = endpoint['path'] % args
|
||||
else:
|
||||
endpoint['parsed_url'] = endpoint['path']
|
||||
data = {}
|
||||
for arg in endpoint['args']['required']:
|
||||
data[arg] = kwargs[arg]
|
||||
for arg in endpoint['args']['optional']:
|
||||
if arg in kwargs:
|
||||
data[arg] = kwargs[arg]
|
||||
for arg in kwargs:
|
||||
if arg not in endpoint['args']['required'] and arg not in endpoint['args']['optional'] and not silent:
|
||||
logger.warn("Received unrecognized kwarg %s for endpoint %s" % (arg, endpoint))
|
||||
r = getattr(requests, endpoint['method'])(settings.DISCOURSE_URL + endpoint['parsed_url'], headers=params,
|
||||
json=data)
|
||||
try:
|
||||
if 'errors' in r.json() and not silent:
|
||||
logger.error("Discourse execution failed.\nEndpoint: %s\nErrors: %s" % (endpoint, r.json()['errors']))
|
||||
raise DiscourseError(endpoint, r.json()['errors'])
|
||||
if 'success' in r.json():
|
||||
if not r.json()['success'] and not silent:
|
||||
raise DiscourseError(endpoint, None)
|
||||
out = r.json()
|
||||
except ValueError:
|
||||
out = r.text
|
||||
finally:
|
||||
try:
|
||||
r.raise_for_status()
|
||||
except requests.exceptions.HTTPError as e:
|
||||
raise DiscourseError(endpoint, e.response.status_code)
|
||||
return out
|
||||
|
||||
@staticmethod
|
||||
def _get_groups():
|
||||
endpoint = ENDPOINTS['groups']['list']
|
||||
data = DiscourseManager.__exc(endpoint)
|
||||
data = providers.discourse.client.groups()
|
||||
return [g for g in data if not g['automatic']]
|
||||
|
||||
@staticmethod
|
||||
def _create_group(name):
|
||||
endpoint = ENDPOINTS['groups']['create']
|
||||
return DiscourseManager.__exc(endpoint, name=name[:20], visible=True)['basic_group']
|
||||
return providers.discourse.client.create_group(name=name[:20], visible=True)['basic_group']
|
||||
|
||||
@staticmethod
|
||||
def _generate_cache_group_name_key(name):
|
||||
@@ -234,13 +73,11 @@ class DiscourseManager:
|
||||
|
||||
@staticmethod
|
||||
def __add_user_to_group(g_id, username):
|
||||
endpoint = ENDPOINTS['groups']['add_user']
|
||||
DiscourseManager.__exc(endpoint, g_id, usernames=username)
|
||||
providers.discourse.client.add_group_member(g_id, username)
|
||||
|
||||
@staticmethod
|
||||
def __remove_user_from_group(g_id, username):
|
||||
endpoint = ENDPOINTS['groups']['remove_user']
|
||||
DiscourseManager.__exc(endpoint, g_id, username=username)
|
||||
def __remove_user_from_group(g_id, uid):
|
||||
providers.discourse.client.delete_group_member(g_id, uid)
|
||||
|
||||
@staticmethod
|
||||
def __generate_group_dict(names):
|
||||
@@ -252,39 +89,35 @@ class DiscourseManager:
|
||||
@staticmethod
|
||||
def __get_user_groups(username):
|
||||
data = DiscourseManager.__get_user(username)
|
||||
return [g['id'] for g in data['user']['groups'] if not g['automatic']]
|
||||
return [g['id'] for g in data['groups'] if not g['automatic']]
|
||||
|
||||
@staticmethod
|
||||
def __user_name_to_id(name, silent=False):
|
||||
data = DiscourseManager.__get_user(name, silent=silent)
|
||||
data = DiscourseManager.__get_user(name)
|
||||
return data['user']['id']
|
||||
|
||||
@staticmethod
|
||||
def __get_user(username, silent=False):
|
||||
endpoint = ENDPOINTS['users']['get']
|
||||
return DiscourseManager.__exc(endpoint, username, silent=silent)
|
||||
return providers.discourse.client.user(username)
|
||||
|
||||
@staticmethod
|
||||
def __activate_user(username):
|
||||
endpoint = ENDPOINTS['users']['activate']
|
||||
u_id = DiscourseManager.__user_name_to_id(username)
|
||||
DiscourseManager.__exc(endpoint, u_id)
|
||||
providers.discourse.client.activate(u_id)
|
||||
|
||||
@staticmethod
|
||||
def __update_user(username, **kwargs):
|
||||
endpoint = ENDPOINTS['users']['update']
|
||||
u_id = DiscourseManager.__user_name_to_id(username)
|
||||
DiscourseManager.__exc(endpoint, u_id, params=kwargs)
|
||||
providers.discourse.client.update_user(endpoint, u_id, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
def __create_user(username, email, password):
|
||||
endpoint = ENDPOINTS['users']['create']
|
||||
DiscourseManager.__exc(endpoint, name=username, username=username, email=email, password=password, active=True)
|
||||
providers.discourse.client.create_user(username, username, email, password)
|
||||
|
||||
@staticmethod
|
||||
def __check_if_user_exists(username):
|
||||
try:
|
||||
DiscourseManager.__user_name_to_id(username, silent=True)
|
||||
DiscourseManager.__user_name_to_id(username)
|
||||
return True
|
||||
except DiscourseError:
|
||||
return False
|
||||
@@ -292,30 +125,26 @@ class DiscourseManager:
|
||||
@staticmethod
|
||||
def __suspend_user(username):
|
||||
u_id = DiscourseManager.__user_name_to_id(username)
|
||||
endpoint = ENDPOINTS['users']['suspend']
|
||||
return DiscourseManager.__exc(endpoint, u_id, duration=DiscourseManager.SUSPEND_DAYS,
|
||||
reason=DiscourseManager.SUSPEND_REASON)
|
||||
return providers.discourse.client.suspend(u_id, DiscourseManager.SUSPEND_DAYS,
|
||||
DiscourseManager.SUSPEND_REASON)
|
||||
|
||||
@staticmethod
|
||||
def __unsuspend(username):
|
||||
u_id = DiscourseManager.__user_name_to_id(username)
|
||||
endpoint = ENDPOINTS['users']['unsuspend']
|
||||
return DiscourseManager.__exc(endpoint, u_id)
|
||||
return providers.discourse.client.unsuspend(u_id)
|
||||
|
||||
@staticmethod
|
||||
def __set_email(username, email):
|
||||
endpoint = ENDPOINTS['users']['set_email']
|
||||
return DiscourseManager.__exc(endpoint, username, email=email)
|
||||
return providers.discourse.client.update_email(username, email)
|
||||
|
||||
@staticmethod
|
||||
def __logout(u_id):
|
||||
endpoint = ENDPOINTS['users']['logout']
|
||||
return DiscourseManager.__exc(endpoint, u_id)
|
||||
return providers.discourse.client.log_out(u_id)
|
||||
|
||||
@staticmethod
|
||||
def __get_user_by_external(u_id):
|
||||
endpoint = ENDPOINTS['users']['external']
|
||||
return DiscourseManager.__exc(endpoint, u_id)
|
||||
data = providers.discourse.client.user_by_external_id(u_id)
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def __user_id_by_external_id(u_id):
|
||||
@@ -351,7 +180,9 @@ class DiscourseManager:
|
||||
logger.debug("Updating discourse user %s groups to %s" % (user, groups))
|
||||
group_dict = DiscourseManager.__generate_group_dict(groups)
|
||||
inv_group_dict = {v: k for k, v in group_dict.items()}
|
||||
username = DiscourseManager.__get_user_by_external(user.pk)['user']['username']
|
||||
discord_user = DiscourseManager.__get_user_by_external(user.pk)
|
||||
username = discord_user['username']
|
||||
uid = discord_user['id']
|
||||
user_groups = DiscourseManager.__get_user_groups(username)
|
||||
add_groups = [group_dict[x] for x in group_dict if not group_dict[x] in user_groups]
|
||||
rem_groups = [x for x in user_groups if x not in inv_group_dict]
|
||||
@@ -364,7 +195,7 @@ class DiscourseManager:
|
||||
logger.info(
|
||||
"Updating discourse user %s groups: removing %s" % (username, rem_groups))
|
||||
for g in rem_groups:
|
||||
DiscourseManager.__remove_user_from_group(g, username)
|
||||
DiscourseManager.__remove_user_from_group(g, uid)
|
||||
|
||||
@staticmethod
|
||||
def disable_user(user):
|
||||
|
||||
@@ -16,3 +16,4 @@ class DiscourseUser(models.Model):
|
||||
permissions = (
|
||||
("access_discourse", u"Can access the Discourse service"),
|
||||
)
|
||||
|
||||
|
||||
19
allianceauth/services/modules/discourse/providers.py
Normal file
19
allianceauth/services/modules/discourse/providers.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from pydiscourse import DiscourseClient
|
||||
from django.conf import settings
|
||||
|
||||
class DiscourseAPIClient():
|
||||
_client = None
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@property
|
||||
def client(self):
|
||||
if not self._client:
|
||||
self._client = DiscourseClient(
|
||||
settings.DISCOURSE_URL,
|
||||
api_username=settings.DISCOURSE_API_USERNAME,
|
||||
api_key=settings.DISCOURSE_API_KEY)
|
||||
return self._client
|
||||
|
||||
discourse = DiscourseAPIClient()
|
||||
@@ -47,7 +47,8 @@ class DiscourseTasks:
|
||||
logger.debug("Updating discourse groups for user %s" % user)
|
||||
try:
|
||||
DiscourseManager.update_groups(user)
|
||||
except:
|
||||
except Exception as e:
|
||||
logger.exception(e)
|
||||
logger.warn("Discourse group sync failed for %s, retrying in 10 mins" % user)
|
||||
raise self.retry(countdown=60 * 10)
|
||||
logger.debug("Updated user %s discourse groups." % user)
|
||||
@@ -63,3 +64,4 @@ class DiscourseTasks:
|
||||
def get_username(user):
|
||||
from .auth_hooks import DiscourseService
|
||||
return NameFormatter(DiscourseService(), user).format_name()
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.1.2 on 2020-10-11 10:09
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mumble', '0010_mumbleuser_certhash'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='mumbleuser',
|
||||
name='pwhash',
|
||||
field=models.CharField(max_length=90),
|
||||
),
|
||||
]
|
||||
@@ -63,7 +63,7 @@ class MumbleManager(models.Manager):
|
||||
|
||||
class MumbleUser(AbstractServiceModel):
|
||||
username = models.CharField(max_length=254, unique=True)
|
||||
pwhash = models.CharField(max_length=80)
|
||||
pwhash = models.CharField(max_length=90)
|
||||
hashfn = models.CharField(max_length=20, default='sha1')
|
||||
groups = models.TextField(blank=True, null=True)
|
||||
certhash = models.CharField(
|
||||
|
||||
@@ -211,4 +211,4 @@ class MumbleManagerTestCase(TestCase):
|
||||
pwhash = self.manager.gen_pwhash('test')
|
||||
|
||||
self.assertEqual(pwhash[:15], '$bcrypt-sha256$')
|
||||
self.assertEqual(len(pwhash), 75)
|
||||
self.assertEqual(len(pwhash), 83)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Jabber Broadcast" %}{% endblock page_title %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Verify Teamspeak" %}{% endblock page_title %}
|
||||
|
||||
@@ -5,7 +5,6 @@ from django.contrib.auth.models import User
|
||||
from .hooks import ServicesHook
|
||||
from celery_once import QueueOnce as BaseTask, AlreadyQueued
|
||||
from django.core.cache import cache
|
||||
from time import time
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -22,14 +21,9 @@ class DjangoBackend:
|
||||
|
||||
@staticmethod
|
||||
def raise_or_lock(key, timeout):
|
||||
now = int(time())
|
||||
result = cache.get(key)
|
||||
if result:
|
||||
remaining = int(result) - now
|
||||
if remaining > 0:
|
||||
raise AlreadyQueued(remaining)
|
||||
else:
|
||||
cache.set(key, now + timeout, timeout)
|
||||
acquired = cache.add(key=key, value="lock", timeout=timeout)
|
||||
if not acquired:
|
||||
raise AlreadyQueued(int(cache.ttl(key)))
|
||||
|
||||
@staticmethod
|
||||
def clear_lock(key):
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
{% load navactive %}
|
||||
|
||||
<li>
|
||||
<a class="{% navactive request item.navactive|join:" " %}" href="{% url item.url_name %}">
|
||||
<i class="{{ item.classes }}"></i> {% trans item.text %}
|
||||
<a class="{% navactive request item.navactive|join:' ' %}" href="{% url item.url_name %}">
|
||||
<i class="{{ item.classes }}"></i> {% trans item.text %}
|
||||
{% if item.count != None %}
|
||||
<span class="badge">{{ item.count }}</span>
|
||||
{% endif %}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Fleet Formatter Tool" %}{% endblock page_title %}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% blocktrans with service_name=view.service_name|title %}{{ service_name }} Credentials{% endblocktrans %}{% endblock page_title %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% blocktrans with service_name=view.service_name|title %}{{ service_name }} Password Change{% endblocktrans %}{% endblock page_title %}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Services Management" %}{% endblock page_title %}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
from unittest import mock
|
||||
|
||||
from celery_once import AlreadyQueued
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.test import TestCase
|
||||
|
||||
from allianceauth.tests.auth_utils import AuthUtils
|
||||
|
||||
from allianceauth.services.tasks import validate_services
|
||||
|
||||
from ..tasks import DjangoBackend
|
||||
|
||||
|
||||
class ServicesTasksTestCase(TestCase):
|
||||
def setUp(self):
|
||||
@@ -24,3 +28,46 @@ class ServicesTasksTestCase(TestCase):
|
||||
self.assertTrue(svc.validate_user.called)
|
||||
args, kwargs = svc.validate_user.call_args
|
||||
self.assertEqual(self.member, args[0]) # Assert correct user is passed to service hook function
|
||||
|
||||
|
||||
class TestDjangoBackend(TestCase):
|
||||
|
||||
TEST_KEY = "my-django-backend-test-key"
|
||||
TIMEOUT = 1800
|
||||
|
||||
def setUp(self) -> None:
|
||||
cache.delete(self.TEST_KEY)
|
||||
self.backend = DjangoBackend(dict())
|
||||
|
||||
def test_can_get_lock(self):
|
||||
"""
|
||||
when lock can be acquired
|
||||
then set it with timetout
|
||||
"""
|
||||
self.backend.raise_or_lock(self.TEST_KEY, self.TIMEOUT)
|
||||
self.assertIsNotNone(cache.get(self.TEST_KEY))
|
||||
self.assertAlmostEqual(cache.ttl(self.TEST_KEY), self.TIMEOUT, delta=2)
|
||||
|
||||
def test_when_cant_get_lock_raise_exception(self):
|
||||
"""
|
||||
when lock can bot be acquired
|
||||
then raise AlreadyQueued exception with countdown
|
||||
"""
|
||||
self.backend.raise_or_lock(self.TEST_KEY, self.TIMEOUT)
|
||||
|
||||
try:
|
||||
self.backend.raise_or_lock(self.TEST_KEY, self.TIMEOUT)
|
||||
except Exception as ex:
|
||||
self.assertIsInstance(ex, AlreadyQueued)
|
||||
self.assertAlmostEqual(ex.countdown, self.TIMEOUT, delta=2)
|
||||
|
||||
def test_can_clear_lock(self):
|
||||
"""
|
||||
when a lock exists
|
||||
then can get a new lock after clearing it
|
||||
"""
|
||||
self.backend.raise_or_lock(self.TEST_KEY, self.TIMEOUT)
|
||||
|
||||
self.backend.clear_lock(self.TEST_KEY)
|
||||
self.backend.raise_or_lock(self.TEST_KEY, self.TIMEOUT)
|
||||
self.assertIsNotNone(cache.get(self.TEST_KEY))
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
from allianceauth.services.hooks import MenuItemHook, UrlHook
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from allianceauth import hooks
|
||||
from allianceauth.services.hooks import MenuItemHook, UrlHook
|
||||
|
||||
from . import urls
|
||||
from .managers import SRPManager
|
||||
|
||||
|
||||
class SrpMenu(MenuItemHook):
|
||||
@@ -13,6 +16,8 @@ class SrpMenu(MenuItemHook):
|
||||
|
||||
def render(self, request):
|
||||
if request.user.has_perm('srp.access_srp'):
|
||||
app_count = SRPManager.pending_requests_count_for_user(request.user)
|
||||
self.count = app_count if app_count and app_count > 0 else None
|
||||
return MenuItemHook.render(self, request)
|
||||
return ''
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import logging
|
||||
import os
|
||||
|
||||
import requests
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
from allianceauth import NAME
|
||||
from allianceauth.eveonline.providers import provider
|
||||
|
||||
from .models import SrpUserRequest
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -50,3 +52,12 @@ class SRPManager:
|
||||
return ship_type, ship_value, victim_id
|
||||
else:
|
||||
raise ValueError("Invalid Kill ID or Hash.")
|
||||
|
||||
@staticmethod
|
||||
def pending_requests_count_for_user(user: User):
|
||||
"""returns the number of open SRP requests for given user
|
||||
or None if user has no permission"""
|
||||
if user.has_perm("auth.srp_management"):
|
||||
return SrpUserRequest.objects.filter(srp_status="pending").count()
|
||||
else:
|
||||
return None
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "SRP Fleet Create" %}{% endblock page_title %}
|
||||
@@ -26,7 +26,7 @@
|
||||
{% else %}
|
||||
<div class="alert alert-info" role="alert">{% blocktrans %}Give this link to the line members{% endblocktrans %}.</div>
|
||||
<div class="alert alert-info" role="alert">
|
||||
http://{{ request.get_host }}{% url 'srp:request' completed_srp_code %}</div>
|
||||
{{ request.scheme }}://{{ request.get_host }}{% url 'srp:request' completed_srp_code %}</div>
|
||||
<div class="text-center">
|
||||
<a href="{% url 'srp:management' %}" class="btn btn-primary btn-lg">{% trans "Continue" %}</a>
|
||||
</div>
|
||||
@@ -34,7 +34,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock content %}
|
||||
@@ -46,8 +45,15 @@
|
||||
{% block extra_script %}
|
||||
|
||||
$('#id_fleet_time').datetimepicker({
|
||||
maskInput: true,
|
||||
format: 'Y-m-d H:i'
|
||||
setlocale: '{{ LANGUAGE_CODE }}',
|
||||
{% if NIGHT_MODE %}
|
||||
theme: 'dark',
|
||||
{% else %}
|
||||
theme: 'default',
|
||||
{% endif %}
|
||||
mask: true,
|
||||
format: 'Y-m-d H:i',
|
||||
minDate: 0
|
||||
});
|
||||
|
||||
{% endblock extra_script %}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% load humanize %}
|
||||
{% block page_title %}Srp Fleet Data{% endblock page_title %}
|
||||
{% block extra_css %}
|
||||
{% include 'bundles/x-editable.css.html' %}
|
||||
{% include 'bundles/datatables-css.html' %}
|
||||
{% include 'bundles/x-editable.css.html' %}
|
||||
<link href="{% static 'css/checkbox.css' %}" rel="stylesheet" type="text/css">
|
||||
<style>
|
||||
.radio label, .checkbox label {
|
||||
@@ -60,7 +61,7 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
</h1>
|
||||
|
||||
|
||||
{% if srpfleetrequests %}
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
@@ -82,8 +83,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<tr>
|
||||
<table class="table srplist">
|
||||
<thead>
|
||||
<th class="text-center">{% trans "Pilot Name" %}</th>
|
||||
<th class="text-center">{% trans "Killboard Link" %}</th>
|
||||
<th class="text-center">{% trans "Additional Info" %}</th>
|
||||
@@ -98,19 +99,27 @@ ESC to cancel{% endblocktrans %}"id="blah"></i></th>
|
||||
{% if perms.auth.srp_management %}
|
||||
<th class="text-center">{% trans "Actions" %}</th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for srpfleetrequest in srpfleetrequests %}
|
||||
<tr>
|
||||
<td class="text-center">{{ srpfleetrequest.character.character_name }}</td>
|
||||
<td class="text-center">
|
||||
{% if srpfleetrequest.character.alliance.alliance_ticker %}
|
||||
{{ srpfleetrequest.character.alliance.alliance_ticker }}
|
||||
{% endif %}
|
||||
[{{ srpfleetrequest.character.corporation.corporation_ticker }}]
|
||||
{{ srpfleetrequest.character.character_name }}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<a href="{{ srpfleetrequest.killboard_link }}"
|
||||
target="_blank" class="label label-warning">Link</a>
|
||||
</td>
|
||||
<td class="text-center">{{ srpfleetrequest.additional_info }}</td>
|
||||
<td class="text-center">{{ srpfleetrequest.srp_ship_name }}</td>
|
||||
<td class="text-center">{{ srpfleetrequest.kb_total_loss | intcomma }} ISK</td>
|
||||
<td class="srp" data-name="srp_total_amount" data-type="number" data-pk="{{srpfleetrequest.id}}" data-url="{% url 'srp:request_update_amount' srpfleetrequest.id %}" data-params="{csrfmiddlewaretoken:'{{csrf_token}}'}" class="text-center">{{ srpfleetrequest.srp_total_amount | intcomma }} ISK</td>
|
||||
<td class="text-center">{{ srpfleetrequest.post_time | date:"Y-m-d H:i" }}</td>
|
||||
<td class="text-center" data-sort="{{ srpfleetrequest.kb_total_loss }}">{{ srpfleetrequest.kb_total_loss | intcomma }} ISK</td>
|
||||
<td class="srp text-center" data-name="srp_total_amount" data-type="number" data-pk="{{srpfleetrequest.id}}" data-url="{% url 'srp:request_update_amount' srpfleetrequest.id %}" data-params="{csrfmiddlewaretoken:'{{csrf_token}}'}" data-sort="{{ srpfleetrequest.srp_total_amount }}">{{ srpfleetrequest.srp_total_amount | intcomma }} ISK</td>
|
||||
<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">
|
||||
@@ -133,11 +142,13 @@ ESC to cancel{% endblocktrans %}"id="blah"></i></th>
|
||||
<input type="checkbox" name="{{srpfleetrequest.id}}">
|
||||
<span class="cr"><i class="cr-icon fas fa-check"></i></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
<tbody>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
<div class="alert alert-info" role="alert">
|
||||
@@ -168,7 +179,9 @@ ESC to cancel{% endblocktrans %}"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' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_script %}
|
||||
@@ -198,11 +211,47 @@ ESC to cancel{% endblocktrans %}"id="blah"></i></th>
|
||||
var $next = $(this).closest('tr').next().find('.editable');
|
||||
setTimeout(function() {
|
||||
$next.editable('show');
|
||||
}, 400);
|
||||
}, 400);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).ready(function(){
|
||||
$("[rel=tooltip]").tooltip({ placement: 'top'});
|
||||
});
|
||||
});
|
||||
|
||||
$.fn.dataTable.moment = function(format, locale) {
|
||||
var types = $.fn.dataTable.ext.type;
|
||||
|
||||
// Add type detection
|
||||
types.detect.unshift(function(d) {
|
||||
return moment(d, format, locale, true).isValid() ?
|
||||
'moment-'+format :
|
||||
null;
|
||||
} );
|
||||
|
||||
// Add sorting method - use an integer for the sorting
|
||||
types.order[ 'moment-'+format+'-pre' ] = function(d) {
|
||||
return moment(d, format, locale, true).unix();
|
||||
};
|
||||
};
|
||||
|
||||
$(document).ready( function(){
|
||||
$.fn.dataTable.moment('YYYY-MMM-D, HH:mm');
|
||||
|
||||
$('table.srplist').DataTable({
|
||||
"order": [[ 6, "asc" ]],
|
||||
"paging": false,
|
||||
"columnDefs": [{
|
||||
"targets": [1, 8],
|
||||
"orderable": false
|
||||
},
|
||||
{
|
||||
"targets": [4, 5],
|
||||
"type": "num"
|
||||
}]
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
{% endblock extra_script %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% load humanize %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "SRP Request" %}{% endblock page_title %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "allianceauth/base.html" %}
|
||||
{% load bootstrap %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{% trans "Update AAR Link" %}{% endblock page_title %}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user