Compare commits

...

148 Commits

Author SHA1 Message Date
Ariel Rin
e16252842a Version Bump 4.0.0a5 2023-12-26 21:40:20 +10:00
Ariel Rin
950ae34093 loosen sphinx_rtd_theme for sphinx 7 2023-12-26 21:38:04 +10:00
Ariel Rin
0ba94c53aa Two more MyST converted toctrees 2023-12-26 21:37:49 +10:00
Ariel Rin
96cc55d174 missed myst conversions 2023-12-26 21:23:37 +10:00
Ariel Rin
a9062c4389 test starting redis on RTD 2023-12-26 21:15:07 +10:00
Ariel Rin
c602cf0b00 Merge branch 'master' of gitlab.com:allianceauth/allianceauth into v4.x 2023-12-25 19:49:54 +10:00
Ariel Rin
3de988369f Merge branch 'fix-orphan-tokens' into 'master'
Fix orphan tokens and remove unused messages from backends

Closes #1391

See merge request allianceauth/allianceauth!1570
2023-12-25 09:48:15 +00:00
Ariel Rin
b28b51916c Merge branch 'aa-framework-part-2' into 'v4.x'
Alliance Auth Framework (Part 2)

See merge request allianceauth/allianceauth!1558
2023-12-25 09:46:57 +00:00
Ariel Rin
0db0978d5f Merge branch 'header-nav-improvement' into 'v4.x'
Header navigation improvements

See merge request allianceauth/allianceauth!1575
2023-12-25 09:45:19 +00:00
Ariel Rin
0531da1128 Merge branch 'middleware-menu' into 'v4.x'
swap to middleware to sync menu hooks

See merge request allianceauth/allianceauth!1573
2023-12-25 09:43:52 +00:00
Peter Pfeufer
547d047f59 Merge branch 'v4.x' into 'aa-framework-part-2'
# Conflicts:
#   allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkpersonalmonthlystatisticsview.html
#   allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html
2023-12-24 17:34:07 +00:00
Ariel Rin
5cd92e29d3 Merge branch 'whitespaces' into 'v4.x'
[REMOVE] Unnecessary whitespaces

See merge request allianceauth/allianceauth!1576
2023-12-24 11:10:06 +00:00
Peter Pfeufer
bb44194cfc [CHANGE] Moved corpstats menu and search to heaver navbar
Also:
- Sorted alts alphabetically
- Added table headers
2023-12-22 12:23:23 +01:00
Peter Pfeufer
aa1cb96c8a [REMOVE] Unnecessary whitespaces
I know, purely aesthetic, but it bugs the hell out of me …
2023-12-21 12:20:51 +01:00
Peter Pfeufer
40ae092306 [ADD] New template block for the character control icons top right
This commit adds a new template block called "header_nav_user_character_control" to the base-bs5.html file. This block is intended to display character control icons in the top right section of the navigation bar. The existing code has been modified to include this new block and rearrange the layout accordingly.

With this change it is possible to add app specific menu items to the right side as well without having to re-add the character control menu items all the time.

Thanks to @aaronkable for discussing this idea with me.
2023-12-21 02:33:11 +01:00
Peter Pfeufer
b2e70c3702 [ADD] Docu for templates and bundles 2023-12-18 01:22:55 +01:00
Peter Pfeufer
eebeb26001 [ADD] API docu 2023-12-18 00:59:36 +01:00
Peter Pfeufer
003a67224e [CHANGE] Trying a different syntax … 2023-12-18 00:30:37 +01:00
Peter Pfeufer
d3a3810456 [CHANGE] Try to use img tags instead of MD 2023-12-18 00:22:44 +01:00
Peter Pfeufer
f55008559e [CHANGE] Wrapping table in {eval-rst} 2023-12-17 23:59:15 +01:00
Peter Pfeufer
dbc19c76c5 [CHANGE] Switch to header template where ever possible
Also fixed some Bootstrap misuse
2023-12-17 23:50:13 +01:00
Peter Pfeufer
ced7972962 [FIX] Docs syntax 2023-12-17 23:50:13 +01:00
Peter Pfeufer
ad508bd880 [ADD] Page header template 2023-12-17 23:50:13 +01:00
Peter Pfeufer
5c128f2c78 [FIX] Spelling 2023-12-17 23:50:13 +01:00
Peter Pfeufer
1caaca86cf [CHANGE] Table formatted, hope that helps … 2023-12-17 23:50:13 +01:00
Peter Pfeufer
33ad1413d5 [ADD] Attempt to explain the sentinel user function
Let's see if the docs are generated properly with this
2023-12-17 23:50:13 +01:00
Peter Pfeufer
cbb5c80b94 [ADD] CSS cursor classes docs 2023-12-17 23:50:13 +01:00
Peter Pfeufer
d2edd288f9 [ADD] Some more tests 2023-12-17 23:50:13 +01:00
Peter Pfeufer
21e80f6961 [ADD] __init__.py to test … 2023-12-17 23:50:13 +01:00
Peter Pfeufer
a747951d19 [CHANGE] split it into 2 functions
- `get_main_character_from_user` to return the `EveCharacter` object
- `get_main_character_name_from_user` to return the main character name as string
2023-12-17 23:50:13 +01:00
Peter Pfeufer
4cc7135ace [ADD] get_main_character_from_user 2023-12-17 23:50:13 +01:00
Peter Pfeufer
6a990c11e6 [ADD] sentinel user and migrate fleetactivitytracking 2023-12-17 23:50:13 +01:00
Peter Pfeufer
3f47cecbfc [CHANGE] Move auth-framework.css to allianceauth.framework app 2023-12-17 23:50:13 +01:00
Peter Pfeufer
77c126ea2f [ADD] Alliance Auth Framework base app 2023-12-17 23:50:13 +01:00
Ariel Rin
8b7e57494c Merge branch 'menu-fa-cleanup' into 'v4.x'
[CHANGE] FA classes in menu hooks updated

See merge request allianceauth/allianceauth!1571
2023-12-17 03:52:09 +00:00
Ariel Rin
20fcf5efa4 Merge branch 'docs' into 'master'
Docs fixes

See merge request allianceauth/allianceauth!1569
2023-12-17 03:49:41 +00:00
Peter Pfeufer
8ff3d854ba [CHANGE] Reduce overall margin a bit while I'm at it 2023-12-12 10:27:53 +01:00
Peter Pfeufer
49ff355d50 [CHANGE] FA classes in menu hooks updated 2023-12-12 02:40:18 +01:00
colcrunch
c15b955d5e Make pre-commit happy 2023-12-11 18:37:35 -05:00
colcrunch
65e1545a66 Remove all references to messages as they are never relayed to the user. 2023-12-11 18:16:34 -05:00
colcrunch
c558a980e1 Add more detail to error message displayed on failed alt login. 2023-12-11 18:14:09 -05:00
colcrunch
bd8ef84862 Delete tokens that can not be used for logins. 2023-12-11 18:13:24 -05:00
Ariel Rin
6f670da1db Merge branches 'v4.x' and 'v4.x' of gitlab.com:allianceauth/allianceauth into v4.x 2023-12-11 22:20:38 +10:00
Ariel Rin
c558f3785f typo 2023-12-11 22:20:31 +10:00
Ariel Rin
04cdd4c64f Merge branch 'aa-services-fixes' into 'v4.x'
Template Updates (I hope I got them all)

See merge request allianceauth/allianceauth!1566
2023-12-11 12:18:51 +00:00
Ariel Rin
42e96d2f14 close the python section to fix mysql tabs/steps 2023-12-11 22:15:12 +10:00
Peter Pfeufer
00fcebd8e3 [CHANGE] Some minor cleanups 2023-12-11 11:59:32 +01:00
Peter Pfeufer
995c84481c [CHANGE] Public templates updated to BS 5 2023-12-11 11:14:17 +01:00
Peter Pfeufer
4dd42da993 [REMOVE] Unused/Undefined class 2023-12-11 10:45:27 +01:00
Peter Pfeufer
8295cc51a3 [FIX] FA icon 2023-12-11 10:40:02 +01:00
Peter Pfeufer
f7e1d7c47e [CHANGE] Token Management template updated 2023-12-11 10:35:23 +01:00
Peter Pfeufer
234191218a [FIX] Semantic headline order 2023-12-11 10:26:08 +01:00
Peter Pfeufer
de12b49527 [CHANGE] JS updated to ES8+ standard where ever possible 2023-12-10 14:56:15 +01:00
Peter Pfeufer
021b7b2edb [REMOVE] Unnecessary span 2023-12-10 14:15:51 +01:00
Peter Pfeufer
20b959f273 [FIX] Make notification bell solid again
Looks much better
2023-12-10 14:12:12 +01:00
Peter Pfeufer
e16bb2a737 [FIX] Table width and header 2023-12-10 14:06:04 +01:00
Peter Pfeufer
0a6a6e0bf9 [FIX] Datatable in permission audit templates 2023-12-10 13:56:14 +01:00
Peter Pfeufer
f0fe3929d4 [CHANGE] Update FA icons to new classes
Base Classes:
- `far` => `fa-regular`
- `fas` => `fa-solid`
- `fab` => `fa-brand`
2023-12-10 13:44:32 +01:00
Peter Pfeufer
9a62c729eb [CHANGE] Using the same FA icon for delete/remove
`<i class="fa-solid fa-trash-can"></i>`
2023-12-10 13:15:26 +01:00
Peter Pfeufer
eaedcd5bb7 [FIX] More Bootstrap class usage fixes 2023-12-09 20:14:42 +01:00
Peter Pfeufer
d742257c74 [FIX] Button class 2023-12-09 19:53:26 +01:00
Peter Pfeufer
ad92d7a916 [FIX] Groupmanagement / Index template
Somehow this got royally messed up in one of the backport merges
2023-12-09 19:35:51 +01:00
Peter Pfeufer
af22222bdf [FIX] Test test_should_not_hide_leave_requests_tab_when_there_are_open_requests 2023-12-09 19:12:21 +01:00
Peter Pfeufer
01f49bd125 [FIX] Show Leave tab when GROUPMANAGEMENT_AUTO_LEAVE = True 2023-12-09 19:07:35 +01:00
Peter Pfeufer
af5930b9d0 [FIX] Form classes 2023-12-09 18:51:56 +01:00
Peter Pfeufer
95ba19a827 [FIX] groupmanagement/index.html template 2023-12-09 18:44:35 +01:00
Peter Pfeufer
c75647301f [CHANGE] Switch to django_bootstrap5 form 2023-12-09 18:27:43 +01:00
Peter Pfeufer
adedf7534f [FIX] Use of Bootstrap classes 2023-12-09 18:24:01 +01:00
Peter Pfeufer
d0684862fe [CHANGE] Minor corrections 2023-12-09 18:14:13 +01:00
Peter Pfeufer
2440e5d2b2 [CHANGE] Switch to django_bootstrap5 forms 2023-12-09 18:13:51 +01:00
Peter Pfeufer
5f51ad4a6a [CHANGE] Use cards 2023-12-09 17:58:50 +01:00
Peter Pfeufer
0bd3acc230 [CHANGE] Moved timers table to its own template 2023-12-09 17:53:03 +01:00
Peter Pfeufer
11a32c90a8 [CHANGE] JS corrections 2023-12-09 17:20:07 +01:00
Peter Pfeufer
6f0b853a60 [CHANGE] Switch to django_bootstrap5 forms 2023-12-09 17:19:47 +01:00
Peter Pfeufer
583a6d4c7f [FIX] Tables and buttons 2023-12-09 16:51:39 +01:00
Peter Pfeufer
155494afea [CHANGE] Switch to BS5 base template 2023-12-09 16:18:17 +01:00
Peter Pfeufer
b0aa58b910 [CHANGE] Minor corrections 2023-12-09 16:08:36 +01:00
Peter Pfeufer
1adce85422 [CHANGE] Switched to django_bootstrap5 form 2023-12-09 16:01:24 +01:00
Peter Pfeufer
cd47eadcdc [REMOVE] Wrong div 2023-12-09 15:51:14 +01:00
Peter Pfeufer
247058a30f [CHANGE] Switch to BS5 base template 2023-12-09 15:38:05 +01:00
Peter Pfeufer
e0fa615e90 [CHANGE] Gylphicons to Font-Awesome 2023-12-09 15:37:39 +01:00
Peter Pfeufer
61ec67183c [REMOVE] Unnecessary <br> 2023-12-09 15:11:53 +01:00
Peter Pfeufer
4369813478 [ADD] Roles attribut to pills menu in corputils template 2023-12-09 15:11:53 +01:00
Peter Pfeufer
8bb3d35252 [CHANGE] hrapplication templates updated for BS 5 2023-12-09 15:11:53 +01:00
Peter Pfeufer
398a980fb5 [CHANGE] Switched from Glyphicons to Font Awesome icons 2023-12-09 15:11:53 +01:00
Peter Pfeufer
e14a295ce6 [CHANGE] Format and switch to BS5 base template 2023-12-09 15:11:53 +01:00
Peter Pfeufer
e0cd5c6fb9 [CHANGE] Fat templates updated (Part 1) 2023-12-09 15:11:53 +01:00
Peter Pfeufer
c37ece49d5 [CHANGE] Template renamed to better reflect what it is for 2023-12-09 15:11:53 +01:00
Peter Pfeufer
8adab8bae0 [CHANGE] Replaced Glyphicons with Fontawesome icons 2023-12-09 15:11:53 +01:00
Peter Pfeufer
a9c87bc25a [FIX] Corputils search template 2023-12-09 15:11:53 +01:00
Peter Pfeufer
a4901802c0 [REMOVE] Unnecessary div 2023-12-09 15:11:53 +01:00
Peter Pfeufer
079dcc5d28 [FIX] Tabbed navigation 2023-12-09 15:11:53 +01:00
Peter Pfeufer
10c5a8906d [FIX] Dropdown menu 2023-12-09 15:11:53 +01:00
Peter Pfeufer
e6306ea7aa [FIX] Legend in services.html template 2023-12-09 15:11:53 +01:00
Ariel Rin
20067c1133 Merge branch 'master' of gitlab.com:allianceauth/allianceauth into v4.x 2023-12-08 14:49:56 +10:00
Ariel Rin
dba3c651dc Merge branch 'py3.12' into 'v4.x'
Py3.12 test changes, drop pypy

See merge request allianceauth/allianceauth!1535
2023-12-05 13:05:19 +00:00
Ariel Rin
0b4d2b819b Py3.12 test changes, drop pypy 2023-12-05 13:05:18 +00:00
Ariel Rin
23a3dd1ab9 Merge branch 'fantabular' into 'master'
Doc Modernisation

Closes #1331

See merge request allianceauth/allianceauth!1550
2023-12-05 13:00:50 +00:00
Ariel Rin
81e5bc5337 Merge branch 'master' into 'fantabular'
# Conflicts:
#   docs/maintenance/tuning/index.md
2023-12-02 01:38:18 +00:00
Ariel Rin
7eebf4d953 Merge branch 'docker-optimizations' into 'v4.x'
Docker Healthchecks, loosen redis, NPM sqlite

See merge request allianceauth/allianceauth!1561
2023-12-02 01:37:38 +00:00
Ariel Rin
9e45d2eac7 Merge branch 'classifiers-update' into 'v4.x'
[ADD] Python 3.12 to `pyporject.toml` classifiers

See merge request allianceauth/allianceauth!1557
2023-12-02 01:35:11 +00:00
Ariel Rin
e3017f1ec7 Merge branch 'sw-version-background-fix' into 'v4.x'
[FIX] Background for "Software Version" panel

See merge request allianceauth/allianceauth!1568
2023-12-02 01:33:43 +00:00
Ariel Rin
a8ef844fe7 Merge branch 'tuning' into 'master'
Docs: Sql Tuning and python version comparison

See merge request allianceauth/allianceauth!1545
2023-12-02 01:31:52 +00:00
Ariel Rin
12709b1b56 Merge branch 'fix-custom-error-views' into 'v4.x'
Fix custom error views

See merge request allianceauth/allianceauth!1567
2023-12-02 01:30:26 +00:00
Erik Kalkoken
51ae604efd Fix custom error views 2023-12-02 01:30:26 +00:00
Ariel Rin
63071ec359 Merge branch 'v4bumps' into 'v4.x'
Bump Libraries

See merge request allianceauth/allianceauth!1564
2023-12-02 01:30:13 +00:00
Ariel Rin
0032e4a01f Merge branch 'salartarium-v4.x-patch-91342' into 'v4.x'
Remove redirect. Use stylized EVE to match article title.

See merge request allianceauth/allianceauth!1565
2023-12-02 01:28:10 +00:00
Peter Pfeufer
25ab78a41e [FIX] Background for "Software Version" panel 2023-12-01 12:16:15 +01:00
salartarium
3aa0e323d2 Remove redirect. Use stylized EVE to match article title. 2023-11-28 00:21:33 +00:00
Ariel Rin
cadbb7e61c correct redis healthcheck path 2023-11-09 20:43:12 +10:00
Ariel Rin
115263eb5a scale up logsizes 2023-11-09 20:42:45 +10:00
Ariel Rin
18fec5f614 redis healthcheck script 2023-11-09 18:54:19 +10:00
Ariel Rin
02ab064ec3 include js_template not css 2023-11-09 18:25:21 +10:00
Ariel Rin
ba25f99cb4 bump libraries 2023-11-09 18:14:01 +10:00
Ariel Rin
28fd1b07ea add log rotation 2023-11-09 18:12:36 +10:00
Ariel Rin
9ce1939040 Version Bump 3.8.0 2023-11-09 00:00:28 +10:00
Ariel Rin
322131cd4f Update source language strings 2023-11-08 23:56:16 +10:00
Ariel Rin
55e6e92da5 Merge branch 'transifex' into 'master'
Update from Transifex

See merge request allianceauth/allianceauth!1562
2023-11-08 13:48:26 +00:00
Ariel Rin
e5d29629a5 Update from Transifex 2023-11-08 13:48:26 +00:00
Ariel Rin
26e187e4c8 Merge branch 'assign-users-on-group-form' into 'master'
New Feature: Assign/remove users on group form

See merge request allianceauth/allianceauth!1543
2023-11-08 13:05:25 +00:00
Erik Kalkoken
3480c4e0e8 New Feature: Assign/remove users on group form 2023-11-08 13:05:24 +00:00
Ariel Rin
1544f097e0 Merge branch 'fix-leave-tab-for-autoleave' into 'master'
Fix leave tab for autoleave

See merge request allianceauth/allianceauth!1536
2023-11-08 13:04:27 +00:00
Erik Kalkoken
2477c31656 Fix leave tab for autoleave 2023-11-08 13:04:26 +00:00
Ariel Rin
0dc631d69e Merge branch 'master' into 'master'
Stop renaming discord nick when setting has it disabled

See merge request allianceauth/allianceauth!1540
2023-11-08 13:04:12 +00:00
Dusty Meg
2a9981cdb9 Stop renaming discord nick when setting has it disabled 2023-11-08 13:04:11 +00:00
Ariel Rin
3d92008069 use SQLite by default, leave framework for mariadb backed npm 2023-11-08 21:20:23 +10:00
Ariel Rin
59e47c24c2 loosen redis to 7 major (allow 7.2) 2023-11-08 21:19:36 +10:00
Ariel Rin
6d942555ff add healthchecks 2023-11-08 21:11:38 +10:00
Ariel Rin
004c48b8ad mild formatting changes 2023-11-08 13:45:43 +10:00
Ariel Rin
4d66b7d456 and gitlab ci update for new docs 2023-11-01 13:28:32 +10:00
Ariel Rin
77e5747a23 move tox tests to new dependency format 2023-11-01 13:15:18 +10:00
Peter Pfeufer
a9ebecdec6 [ADD] Python 3.12 to pyporject.toml classifiers 2023-10-31 22:25:39 +01:00
Ariel Rin
6118c0ddec override non compatible dark mode check css 2023-11-01 01:10:39 +10:00
Ariel Rin
ce25deeca1 minor formatting 2023-10-31 23:52:34 +10:00
Ariel Rin
60084de3db Pygments lexer name 'math' is not known 2023-10-31 23:43:52 +10:00
Ariel Rin
e16c68e255 increase anchor generation 2023-10-31 23:43:45 +10:00
Ariel Rin
bf14e9c7c3 merged back into sphinxcontrib-django 2023-10-31 23:36:42 +10:00
Ariel Rin
98e91fe207 MyST conversion 2023-10-31 23:31:41 +10:00
Aaron Kable
f7821b647f swap to middleware to sync menu hooks 2023-10-28 15:26:48 +08:00
Ariel Rin
7024552c4e remove ubuntu 1804 2023-10-27 22:20:27 +10:00
Ariel Rin
a0719e4b86 tabify 2023-10-27 22:20:11 +10:00
Ariel Rin
906c589f14 more automated upgrades 2023-10-27 22:19:28 +10:00
Ariel Rin
ffb526ab0c find and replace fixes, will introduce errors 2023-10-27 16:37:53 +10:00
Ariel Rin
b9d128259e correct path 2023-10-27 16:37:30 +10:00
Ariel Rin
13d866bd0d RST to MyST, pyproject doc dependencies, add sphinx tabs 2023-10-27 16:37:09 +10:00
Ariel Rin
ea1887b9ec mild clarifications 2023-10-26 11:26:39 +10:00
Ariel Rin
d2f8c2a42f Merge branch 'master' of gitlab.com:allianceauth/allianceauth into tuning 2023-10-26 10:49:29 +10:00
Ariel Rin
200e8f2ff1 initial sql tuning and python version comparison 2023-10-11 12:33:17 +10:00
258 changed files with 6790 additions and 4548 deletions

1
.gitignore vendored
View File

@@ -73,3 +73,4 @@ celerybeat-schedule
.flake8
.pylintrc
Makefile
alliance_auth.sqlite3

View File

@@ -99,19 +99,6 @@ test-3.11-core:
coverage_format: cobertura
path: coverage.xml
test-pvpy-core:
<<: *only-default
image: pypy:3.9-bullseye
script:
- tox -e pypy-all
artifacts:
when: always
reports:
coverage_report:
coverage_format: cobertura
path: coverage.xml
allow_failure: true
test-3.12-core:
<<: *only-default
image: python:3.12-rc-bullseye
@@ -123,7 +110,6 @@ test-3.12-core:
coverage_report:
coverage_format: cobertura
path: coverage.xml
allow_failure: true
test-3.8-all:
<<: *only-default
@@ -174,19 +160,6 @@ test-3.11-all:
path: coverage.xml
coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/'
test-pvpy-all:
<<: *only-default
image: pypy:3.9-bullseye
script:
- tox -e pypy-all
artifacts:
when: always
reports:
coverage_report:
coverage_format: cobertura
path: coverage.xml
allow_failure: true
test-3.12-all:
<<: *only-default
image: python:3.12-rc-bullseye
@@ -198,7 +171,6 @@ test-3.12-all:
coverage_report:
coverage_format: cobertura
path: coverage.xml
allow_failure: true
build-test:
stage: test

View File

@@ -7,11 +7,14 @@ version: 2
# Set the version of Python and other tools you might need
build:
os: ubuntu-20.04
os: ubuntu-22.04
apt_packages:
- redis
tools:
python: "3.8"
python: "3.11"
jobs:
post_system_dependencies:
- redis-server --daemonize yes
# Build documentation in the docs/ directory with Sphinx
sphinx:
@@ -20,7 +23,7 @@ sphinx:
# Optionally build your docs in additional formats such as PDF and ePub
formats: all
# Optionally set the version of Python and requirements required to build your docs
# Python requirements required to build your docs
python:
install:
- method: pip

View File

@@ -1,5 +1,5 @@
[main]
host = https://www.transifex.com
host = https://app.transifex.com
lang_map = zh-Hans: zh_Hans
[o:alliance-auth:p:alliance-auth:r:django-po]

View File

@@ -1,10 +0,0 @@
[main]
host = https://www.transifex.com
lang_map = zh-Hans:zh_Hans
[alliance-auth.django-po]
file_filter = allianceauth/locale/<lang>/LC_MESSAGES/django.po
minimum_perc = 0
source_file = allianceauth/locale/en/LC_MESSAGES/django.po
source_lang = en
type = PO

10
.tx/transifex.yml Normal file
View File

@@ -0,0 +1,10 @@
filters:
- filter_type: file
file_format: PO
source_file: allianceauth/locale/en/LC_MESSAGES/django.po
source_language: en
translation_files_expression: allianceauth/locale/<lang>/LC_MESSAGES/django.po
settings:
language_mapping:
zh-Hans: zh_Hans

View File

@@ -17,7 +17,7 @@ An auth system for EVE Online to help in-game organizations manage online servic
- [Documentation](http://allianceauth.rtfd.io)
- [Support](#support)
- [Release Notes](https://gitlab.com/allianceauth/allianceauth/-/releases)
- [Developer Team](#developer-team)
- [Developer Team](#development-team)
- [Contributing](#contributing)
## Overview

View File

@@ -5,7 +5,7 @@ manage online service access.
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
__version__ = '4.0.0a4'
__version__ = '4.0.0a5'
__title__ = 'Alliance Auth'
__url__ = 'https://gitlab.com/allianceauth/allianceauth'
NAME = f'{__title__} v{__version__}'

View File

@@ -2,7 +2,6 @@ import logging
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User, Permission
from django.contrib import messages
from .models import UserProfile, CharacterOwnership, OwnershipRecord
@@ -41,9 +40,7 @@ class StateBackend(ModelBackend):
if ownership.user.profile.main_character:
if ownership.user.profile.main_character.character_id == token.character_id:
return ownership.user
else: ## this is an alt, enforce main only.
if request:
messages.error("Unable to authenticate with this Character, Please log in with the main character associated with this account.")
else: # this is an alt, enforce main only.
return None
else:
logger.debug(f'{token.character_name} has changed ownership. Creating new user account.')
@@ -66,9 +63,7 @@ class StateBackend(ModelBackend):
user = records[0].user
if user.profile.main_character:
if user.profile.main_character.character_id != token.character_id:
## this is an alt, enforce main only due to trust issues in SSO.
if request:
messages.error("Unable to authenticate with this Character, Please log in with the main character associated with this account. Then add this character from the dashboard.")
# this is an alt, enforce main only due to trust issues in SSO.
return None
token.user = user

View File

@@ -1,5 +1,5 @@
{% load i18n %}
<div class="col-12 col-xl-8 align-self-stretch p-2 ps-0">
<div class="col-12 col-xl-8 align-self-stretch p-2 ps-0 pe-0 ps-xl-0 pe-xl-2">
<div class="card">
<div class="card-body">
<div class="d-flex align-items-center">

View File

@@ -1,11 +1,11 @@
{% load i18n %}
<div class="col-12 col-xl-4 align-self-stretch py-2 ps-2">
<div class="col-12 col-xl-4 align-self-stretch py-2 ps-xl-2">
<div class="card h-100">
<div class="card-body">
<h4 class="card-title text-center">{% translate "Membership" %}</h4>
<div class="card-body">
<div style="height: 300px; overflow-y:auto;">
<h6 class="text-center">{% translate "State:" %} {{ request.user.profile.state }}</h6>
<h5 class="text-center">{% translate "State:" %} {{ request.user.profile.state }}</h5>
<table class="table">
{% for group in groups %}
<tr>

View File

@@ -1,65 +1,85 @@
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}{% translate "Dashboard" %}{% endblock page_title %}
{% block page_title %}
{% translate "Token Management" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "Token Management" %}
{% endblock header_nav_brand %}
{% block content %}
<h1 class="page-header text-center">{% translate "Token Management" %}</h1>
<div>
<table class="table table-aa" id="table_tokens" style="width: 100%;">
<p class="mb-3">
{% translate "This page is a best attempt, but backups or database logs can still contain your tokens. Always revoke tokens on https://community.eveonline.com/support/third-party-applications/ where possible."|urlize %}
</p>
<table class="table" id="table_tokens" style="width: 100%;">
<thead>
<tr>
<th>{% translate "Scopes" %}</th>
<th class="text-end">{% translate "Actions" %}</th>
<th>{% translate "Character" %}</th>
</tr>
</thead>
<tbody>
{% for t in tokens %}
<tr>
<td style="white-space:initial;">{% for s in t.scopes.all %}<span class="badge bg-secondary">{{ s.name }}</span>{% endfor %}</td>
<td nowrap class="text-end">
<a href="{% url 'authentication:token_delete' t.id %}" class="btn btn-danger"><i class="fas fa-trash"></i></a>
<a href="{% url 'authentication:token_refresh' t.id %}" class="btn btn-success"><i class="fas fa-sync-alt"></i></a>
<td style="white-space:initial;">
{% for s in t.scopes.all %}
<span class="badge bg-secondary">{{ s.name }}</span>
{% endfor %}
</td>
<td nowrap class="text-end">
<a href="{% url 'authentication:token_delete' t.id %}" class="btn btn-danger"><i class="fa-solid fa-trash-can"></i></a>
<a href="{% url 'authentication:token_refresh' t.id %}" class="btn btn-success"><i class="fa-solid fa-rotate"></i></a>
</td>
<td>{{ t.character_name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% translate "This page is a best attempt, but backups or database logs can still contain your tokens. Always revoke tokens on https://community.eveonline.com/support/third-party-applications/ where possible."|urlize %}
</div>
{% endblock content %}
{% block extra_javascript %}
{% include "bundles/datatables-js-bs5.html" %}
<script>
$(document).ready(() => {
let grp = 2;
const table = $('#table_tokens').DataTable({
'columnDefs': [{orderable: false, targets: [0, 1]}, {
'visible': false,
'targets': grp
}],
'order': [[grp, 'asc']],
'drawCallback': function (settings) {
var api = this.api();
var rows = api.rows({page: 'current'}).nodes();
var last = null;
api.column(grp, {page: 'current'})
.data()
.each((group, i) => {
if (last !== group) {
$(rows).eq(i).before(`<tr class="h5 table-primary"><td colspan="3">${group}</td></tr>`);
last = group;
}
});
},
'stateSave': true
});
});
</script>
{% endblock extra_javascript %}
{% block extra_css %}
{% include "bundles/datatables-css-bs5.html" %}
{% endblock extra_css %}
{% block extra_script %}
$(document).ready(function(){
let grp = 2;
var table = $('#table_tokens').DataTable({
"columnDefs": [{ orderable: false, targets: [0,1] },{ "visible": false, "targets": grp }],
"order": [[grp, 'asc']],
"drawCallback": function (settings) {
var api = this.api();
var rows = api.rows({ page: 'current' }).nodes();
var last = null;
api.column(grp, { page: 'current' })
.data()
.each(function (group, i) {
if (last !== group) {
$(rows).eq(i).before('<tr class="info"><td colspan="3">' + group + '</td></tr>');
last = group;
}
});
},
"stateSave": true,
});
});
{% endblock extra_script %}

View File

@@ -7,7 +7,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<!-- TODO Bundle all the site specific stuff up into its own template for easy overide -->
<!-- TODO Bundle all the site specific stuff up into its own template for easy override -->
<meta property="og:title" content="{{ SITE_NAME }}">
<meta property="og:image" content="{{ SITE_URL }}{% static 'allianceauth/icons/apple-touch-icon.png' %}">
<meta property="og:description" content="Alliance Auth - An auth system for EVE Online to help in-game organizations manage online service access.">
@@ -16,8 +16,9 @@
<title>{% block title %}{% block page_title %}{% endblock page_title %} - {{ SITE_NAME }}{% endblock title %}</title>
{% include 'bundles/bootstrap-css.html' %}
{% include 'bundles/bootstrap-css-bs5.html' %}
{% include 'bundles/fontawesome.html' %}
{% block extra_include %}
{% endblock %}
@@ -30,25 +31,23 @@
background-size: cover;
}
.panel-transparent {
background: rgba(48 48 48 / 0.7);
color: #ffffff;
.card-login {
background: rgba(48 48 48 / 0.7);
color: rgb(255 255 255);
padding-bottom: 21px;
}
.panel-body {
}
#lang-select {
width: 40%;
margin-left: auto;
margin-right: auto;
}
{% block extra_style %}
{% endblock %}
</style>
</head>
<body>
<div class="container" style="margin-top:150px;">
{% block content %}

View File

@@ -1,9 +1,12 @@
{% load i18n %}
<div class="dropdown">
<form action="{% url 'set_language' %}" method="post">
{% csrf_token %}
<select onchange="this.form.submit()" class="form-control" id="lang-select" name="language">
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option lang="{{ language.code }}" value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected="selected"{% endif %}>
{{ language.name_local|capfirst }} ({{ language.code }})

View File

@@ -3,39 +3,41 @@
{% load i18n %}
{% block content %}
<div class="col-md-4 col-md-offset-4">
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.level_tag}}">{{ message }}</div>
{% endfor %}
{% endif %}
<div class="row justify-content-center">
<div class="col-md-4">
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.level_tag}}">{{ message }}</div>
{% endfor %}
{% endif %}
<div class="panel panel-default panel-transparent">
<div class="panel-body">
<div class="col-md-12">
{% block middle_box_content %}
{% endblock %}
<div class="card card-login border-secondary p-3">
<div class="card-body">
<div class="text-center">
{% block middle_box_content %}
{% endblock %}
</div>
</div>
{% include 'public/lang_select.html' %}
<p class="text-center mt-3">
{% translate "For information on SSO, ESI and security read the CCP Dev Blog" %}<br>
<a class="text-reset" href="https://www.eveonline.com/news/view/introducing-esi" target="_blank" rel="noopener noreferrer">
{% translate "Introducing ESI - A New API For EVE Online" %}
</a>
</p>
<p class="text-center">
<a class="text-reset" href="https://community.eveonline.com/support/third-party-applications/" target="_blank" rel="noopener noreferrer">
{% translate "Manage ESI Applications" %}
</a>
</p>
</div>
{% include 'public/lang_select.html' %}
<p class="text-center" style="margin-top: 2rem;">
{% translate "For information on SSO, ESI and security read the CCP Dev Blog" %}<br>
<a href="https://www.eveonline.com/article/introducing-esi" target="_blank" rel="noopener noreferrer">
{% translate "Introducing ESI - A New API For Eve Online" %}
</a>
</p>
<p class="text-center">
<a href="https://community.eveonline.com/support/third-party-applications/" target="_blank" rel="noopener noreferrer">
{% translate "Manage ESI Applications" %}
</a>
</p>
</div>
</div>
{% endblock %}
{% block extra_include %}
{% include 'bundles/bootstrap-js.html' %}
{% include 'bundles/bootstrap-js-bs5.html' %}
{% endblock %}

View File

@@ -6,9 +6,9 @@
{% block page_title %}{% translate "Registration" %}{% endblock %}
{% block extra_include %}
{% include 'bundles/bootstrap-css.html' %}
{% include 'bundles/bootstrap-css-bs5.html' %}
{% include 'bundles/fontawesome.html' %}
{% include 'bundles/bootstrap-js.html' %}
{% include 'bundles/bootstrap-js-bs5.html' %}
{% endblock %}
{% block content %}

View File

@@ -1,5 +1,7 @@
{% extends 'public/middle_box.html' %}
{% load i18n %}
{% block middle_box_content %}
<div class="alert alert-danger">{% translate 'Invalid or expired activation link.' %}</div>
{% endblock %}

View File

@@ -200,7 +200,13 @@ def sso_login(request, token):
request.session['registration_uid'] = user.pk
# Go to Step 2
return redirect('registration_register')
messages.error(request, _('Unable to authenticate as the selected character.'))
# Logging in with an alt is not allowed due to security concerns.
token.delete()
messages.error(
request,
_('Unable to authenticate as the selected character. '
'Please log in with the main character associated with this account.')
)
return redirect(settings.LOGIN_URL)

View File

@@ -10,7 +10,7 @@ class CorpStats(MenuItemHook):
MenuItemHook.__init__(
self,
_('Corporation Stats'),
'fas fa-share-alt fa-fw',
'fa-solid fa-share-nodes',
'corputils:view',
navactive=['corputils:']
)

View File

@@ -1,39 +1,62 @@
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}
{% translate "Corporation Member Data" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "Corporation Member Data" %}
{% endblock header_nav_brand %}
{% block header_nav_collapse_left %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false">
{% translate "Corporations" %}
</a>
<ul class="dropdown-menu">
{% for corpstat in available %}
<li>
<a class="dropdown-item" href="{% url 'corputils:view_corp' corpstat.corp.corporation_id %}">
{{ corpstat.corp.corporation_name }}
</a>
</li>
{% endfor %}
{% if perms.corputils.add_corpstats %}
{% if available.count >= 1 %}
<li>&nbsp;</li>
{% endif %}
<li>
<a class="dropdown-item" href="{% url 'corputils:add' %}">
{% translate "Add corporation" %}
</a>
</li>
{% endif %}
</ul>
</li>
{% endblock %}
{% block header_nav_collapse_right %}
<li class="nav-item">
<form class="navbar-form navbar-right" role="search" action="{% url 'corputils:search' %}" method="GET">
<div class="form-group">
<input
type="text"
class="form-control"
name="search_string"
placeholder="{% if search_string %}{{ search_string }}{% else %}{% translate 'Search all corporations...' %}{% endif %}"
>
</div>
</form>
</li>
{% endblock %}
{% block content %}
<div>
<h1 class="page-header text-center">{% translate "Corporation Member Data" %}</h1>
<nav class="navbar navbar-default">
<div class="container-fluid">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" id="dLabel" class="dropdown-toggle" role="button" data-toggle="dropdown" aria-haspopup="false" aria-expanded="false">{% translate "Corporations" %}<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
{% for corpstat in available %}
<li>
<a href="{% url 'corputils:view_corp' corpstat.corp.corporation_id %}">{{ corpstat.corp.corporation_name }}</a>
</li>
{% endfor %}
</ul>
</li>
{% if perms.corputils.add_corpstats %}
<li>
<a href="{% url 'corputils:add' %}">{% translate "Add" %}</a>
</li>
{% endif %}
</ul>
<form class="navbar-form navbar-right" role="search" action="{% url 'corputils:search' %}" method="GET">
<div class="form-group">
<input type="text" class="form-control" name="search_string" placeholder="{% if search_string %}{{ search_string }}{% else %}{% translate 'Search all corporations...' %}{% endif %}">
</div>
</form>
</div>
</nav>
{% block member_data %}
{% endblock member_data %}
</div>

View File

@@ -1,178 +1,233 @@
{% extends 'corputils/base.html' %}
{% load i18n %}
{% load humanize %}
{% block member_data %}
{% if corpstats %}
<div>
<table class="table">
<table class="table text-center">
<tr>
<td class="text-center col-lg-6{% if corpstats.corp.alliance %}{% else %}col-lg-offset-3{% endif %}">
<img class="ra-avatar" src="{{ corpstats.corp.logo_url_64 }}" alt="{{ corpstats.corp.corporation_name }}">
</td>
<td>
<img class="ra-avatar" src="{{ corpstats.corp.logo_url_64 }}" alt="{{ corpstats.corp.corporation_name }}">
</td>
{% if corpstats.corp.alliance %}
<td class="text-center col-lg-6">
<td>
<img class="ra-avatar" src="{{ corpstats.corp.alliance.logo_url_64 }}" alt="{{ corpstats.corp.alliance.alliance_name }}">
</td>
{% endif %}
</tr>
<tr>
<td class="text-center"><h4>{{ corpstats.corp.corporation_name }}</h4></td>
<td><p class="h4">{{ corpstats.corp.corporation_name }}</p></td>
{% if corpstats.corp.alliance %}
<td class="text-center"><h4>{{ corpstats.corp.alliance.alliance_name }}</h4></td>
<td><p class="h4">{{ corpstats.corp.alliance.alliance_name }}</p></td>
{% endif %}
</tr>
</table>
</div>
<div>
<div class="panel panel-default">
<div class="panel-heading">
<ul class="nav nav-pills pull-left">
<li class="active"><a href="#mains" data-toggle="pill">{% translate 'Mains' %} ({{ total_mains }})</a></li>
<li><a href="#members" data-toggle="pill">{% translate 'Members' %} ({{ corpstats.member_count }})</a></li>
<li><a href="#unregistered" data-toggle="pill">{% translate 'Unregistered' %} ({{ unregistered.count }})</a></li>
</ul>
<div class="pull-right hidden-xs">
{% translate "Last update:" %} {{ corpstats.last_update|naturaltime }}&nbsp;
<a class="btn btn-success" type="button" href="{% url 'corputils:update' corpstats.corp.corporation_id %}" title="Update Now">
<span class="glyphicon glyphicon-refresh"></span>
<div class="card card-default mt-4">
<div class="card-header clearfix" role="tablist">
<ul class="nav nav-pills text-right float-start">
<li class="nav-item" role="presentation">
<a
class="nav-link active"
id="mains"
data-bs-toggle="tab"
href="#tab-mains"
role="tab"
aria-controls="tab-mains"
aria-selected="true"
>
{% translate 'Mains' %} ({{ total_mains }})
</a>
</div>
<div class="clearfix"></div>
</div>
</li>
<div class="panel-body">
<div class="tab-content">
<div class="tab-pane fade in active" id="mains">
{% if mains %}
<div class="table-responsive">
<table class="table table-hover" id="table-mains">
<thead>
<li class="nav-item" role="presentation">
<a
class="nav-link"
id="members"
data-bs-toggle="tab"
href="#tab-members"
role="tab"
aria-controls="tab-members"
aria-selected="false"
>
{% translate 'Members' %} ({{ corpstats.member_count }})
</a>
</li>
<li class="nav-item">
<a
class="nav-link"
id="unregistered"
data-bs-toggle="tab"
href="#tab-unregistered"
role="tab"
aria-controls="tab-unregistered"
aria-selected="false"
>
{% translate 'Unregistered' %} ({{ unregistered.count }})
</a>
</li>
</ul>
<div class="float-end d-none d-sm-block">
{% translate "Last update:" %} {{ corpstats.last_update|naturaltime }}
<a
class="btn btn-success btn-sm ms-2"
type="button"
href="{% url 'corputils:update' corpstats.corp.corporation_id %}"
title="{% translate 'Update Now' %}"
>
<i class="fa-solid fa-rotate"></i>
</a>
</div>
</div>
<div class="card-body">
<div class="tab-content">
<div class="tab-pane fade show active" id="tab-mains" role="tabpanel" aria-labelledby="tab-mains">
{% if mains %}
<div class="table-responsive">
<table class="table table-hover" id="table-mains">
<thead>
<tr>
<th>{% translate "Main character" %}</th>
<th>{% translate "Registered characters" %}</th>
</tr>
</thead>
<tbody>
{% for id, main in mains.items %}
<tr>
<th style="height:1em;"><!-- Must have text or height to prevent clipping --></th>
<th></th>
</tr>
</thead>
<tbody>
{% for id, main in mains.items %}
<tr>
<td class="text-center" style="vertical-align:middle">
<div class="thumbnail" style="border: 0 none; box-shadow: none; background: transparent;">
<img src="{{ main.main.portrait_url_64 }}" class="img-circle" alt="{{ main.main }}">
<div class="caption text-center">
{{ main.main }}
</div>
<td class="text-center" style="vertical-align: middle;">
<div class="thumbnail" style="border: 0 none; box-shadow: none; background: transparent;">
<img src="{{ main.main.portrait_url_64 }}" class="img-circle" alt="{{ main.main }}">
<div class="caption">
{{ main.main }}
</div>
</td>
<td>
<table class="table table-hover">
{% for alt in main.alts %}
{% if forloop.first %}
<tr>
<th></th>
<th class="text-center">{% translate "Character" %}</th>
<th class="text-center">{% translate "Corporation" %}</th>
<th class="text-center">{% translate "Alliance" %}</th>
<th class="text-center"></th>
</tr>
{% endif %}
</div>
</td>
<td>
<table class="table table-hover">
{% for alt in main.alts|dictsort:"character_name" %}
{% if forloop.first %}
<tr>
<td class="text-center" style="width:5%">
<div class="thumbnail" style="border: 0 none; box-shadow: none; background: transparent;">
<img src="{{ alt.portrait_url_32 }}" class="img-circle" alt="{{ alt.character_name }}">
</div>
</td>
<td class="text-center" style="width:30%">{{ alt.character_name }}</td>
<td class="text-center" style="width:30%">{{ alt.corporation_name }}</td>
<td class="text-center" style="width:30%">{{ alt.alliance_name }}</td>
<td class="text-center" style="width:5%">
<a href="https://zkillboard.com/character/{{ alt.character_id }}/" class="badge bg-danger" target="_blank">
{% translate "Killboard" %}
</a>
</td>
<th></th>
<th>{% translate "Character" %}</th>
<th>{% translate "Corporation" %}</th>
<th>{% translate "Alliance" %}</th>
<th></th>
</tr>
{% endfor %}
</table>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</div>
<div class="tab-pane fade" id="members">
{% if members %}
<div class="table-responsive">
<table class="table table-hover" id="table-members">
<thead>
<tr>
<th></th>
<th class="text-center">{% translate "Character" %}</th>
<th class="text-center"></th>
<th class="text-center">{% translate "Main Character" %}</th>
<th class="text-center">{% translate "Main Corporation" %}</th>
<th class="text-center">{% translate "Main Alliance" %}</th>
{% endif %}
<tr>
<td style="width: 5%;">
<div class="thumbnail" style="border: 0 none; box-shadow: none; background: transparent;">
<img src="{{ alt.portrait_url_32 }}" class="img-circle" alt="{{ alt.character_name }}">
</div>
</td>
<td style="width: 30%;">{{ alt.character_name }}</td>
<td style="width: 30%;">{{ alt.corporation_name }}</td>
<td style="width: 30%;">{{ alt.alliance_name|default_if_none:"" }}</td>
<td style="width: 5%;">
<a href="https://zkillboard.com/character/{{ alt.character_id }}/" class="badge bg-danger" target="_blank">
{% translate "Killboard" %}
</a>
</td>
</tr>
{% endfor %}
</table>
</td>
</tr>
</thead>
<tbody>
{% for member in members %}
<tr>
<td><img src="{{ member.portrait_url }}" class="img-circle" alt="{{ member }}"></td>
<td class="text-center">{{ member }}</td>
<td class="text-center">
<a href="https://zkillboard.com/character/{{ member.character_id }}/" class="badge bg-danger" target="_blank">{% translate "Killboard" %}</a>
</td>
<td class="text-center">{{ member.character_ownership.user.profile.main_character.character_name }}</td>
<td class="text-center">{{ member.character_ownership.user.profile.main_character.corporation_name }}</td>
<td class="text-center">{{ member.character_ownership.user.profile.main_character.alliance_name }}</td>
</tr>
{% endfor %}
{% for member in unregistered %}
<tr class="danger">
<td><img src="{{ member.portrait_url }}" class="img-circle" alt="{{ member.character_name }}"></td>
<td class="text-center">{{ member.character_name }}</td>
<td class="text-center">
<a href="https://zkillboard.com/character/{{ member.character_id }}/" class="badge bg-danger" target="_blank">{% translate "Killboard" %}</a>
</td>
<td class="text-center"></td>
<td class="text-center"></td>
<td class="text-center"></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</div>
<div class="tab-pane fade" id="unregistered">
{% if unregistered %}
<div class="table-responsive">
<table class="table table-hover" id="table-unregistered">
<thead>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</div>
<div class="tab-pane fade" id="tab-members" role="tabpanel" aria-labelledby="tab-members">
{% if members %}
<div class="table-responsive">
<table class="table table-hover" id="table-members">
<thead>
<tr>
<th></th>
<th>{% translate "Character" %}</th>
<th></th>
<th>{% translate "Main Character" %}</th>
<th>{% translate "Main Corporation" %}</th>
<th>{% translate "Main Alliance" %}</th>
</tr>
</thead>
<tbody>
{% for member in members %}
<tr>
<th></th>
<th class="text-center">{% translate "Character" %}</th>
<th class="text-center"></th>
<td><img src="{{ member.portrait_url }}" class="img-circle" alt="{{ member }}"></td>
<td>{{ member }}</td>
<td>
<a href="https://zkillboard.com/character/{{ member.character_id }}/" class="badge bg-danger" target="_blank">{% translate "Killboard" %}</a>
</td>
<td>{{ member.character_ownership.user.profile.main_character.character_name }}</td>
<td>{{ member.character_ownership.user.profile.main_character.corporation_name }}</td>
<td>{{ member.character_ownership.user.profile.main_character.alliance_name|default_if_none:"" }}</td>
</tr>
</thead>
<tbody>
{% for member in unregistered %}
<tr class="danger">
<td><img src="{{ member.portrait_url }}" class="img-circle" alt="{{ member.character_name }}"></td>
<td class="text-center">{{ member.character_name }}</td>
<td class="text-center">
<a href="https://zkillboard.com/character/{{ member.character_id }}/" class="badge bg-danger" target="_blank">
{% translate "Killboard" %}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</div>
{% endfor %}
{% for member in unregistered %}
<tr class="table-danger">
<td><img src="{{ member.portrait_url }}" class="img-circle" alt="{{ member.character_name }}"></td>
<td>{{ member.character_name }}</td>
<td>
<a href="https://zkillboard.com/character/{{ member.character_id }}/" class="badge bg-danger" target="_blank">{% translate "Killboard" %}</a>
</td>
<td></td>
<td></td>
<td></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</div>
<div class="tab-pane fade" id="tab-unregistered" role="tabpanel" aria-labelledby="tab-unregistered">
{% if unregistered %}
<div class="table-responsive">
<table class="table table-hover" id="table-unregistered">
<thead>
<tr>
<th></th>
<th>{% translate "Character" %}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for member in unregistered %}
<tr class="table-danger">
<td><img src="{{ member.portrait_url }}" class="img-circle" alt="{{ member.character_name }}"></td>
<td>{{ member.character_name }}</td>
<td>
<a href="https://zkillboard.com/character/{{ member.character_id }}/" class="badge bg-danger" target="_blank">
{% translate "Killboard" %}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</div>
</div>
</div>
@@ -181,40 +236,41 @@
{% endblock %}
{% block extra_javascript %}
{% include 'bundles/datatables-js.html' %}
{% include 'bundles/datatables-js-bs5.html' %}
<script>
$(document).ready(() => {
$('#table-mains').DataTable({
"columnDefs": [
{ "sortable": false, "targets": [1] },
],
"stateSave": true,
"stateDuration": 0
});
$('#table-members').DataTable({
"columnDefs": [
{ "searchable": false, "targets": [0, 2] },
{ "sortable": false, "targets": [0, 2] },
],
"order": [[ 1, "asc" ]],
"stateSave": true,
"stateDuration": 0
});
$('#table-unregistered').DataTable({
"columnDefs": [
{ "searchable": false, "targets": [0, 2] },
{ "sortable": false, "targets": [0, 2] },
],
"order": [[ 1, "asc" ]],
"stateSave": true,
"stateDuration": 0
});
});
</script>
{% endblock %}
{% block extra_css %}
{% include 'bundles/datatables-css.html' %}
{% endblock %}
{% block extra_script %}
$(document).ready(function(){
$('#table-mains').DataTable({
"columnDefs": [
{ "sortable": false, "targets": [1] },
],
"stateSave": true,
"stateDuration": 0
});
$('#table-members').DataTable({
"columnDefs": [
{ "searchable": false, "targets": [0, 2] },
{ "sortable": false, "targets": [0, 2] },
],
"order": [[ 1, "asc" ]],
"stateSave": true,
"stateDuration": 0
});
$('#table-unregistered').DataTable({
"columnDefs": [
{ "searchable": false, "targets": [0, 2] },
{ "sortable": false, "targets": [0, 2] },
],
"order": [[ 1, "asc" ]],
"stateSave": true,
"stateDuration": 0
});
});
{% include 'bundles/datatables-css-bs5.html' %}
{% endblock %}

View File

@@ -1,33 +1,36 @@
{% extends "corputils/base.html" %}
{% load i18n %}
{% block member_data %}
<div class="panel panel-default">
<div class="panel-heading clearfix">
<div class="panel-title pull-left">{% translate "Search Results" %}</div>
<div class="card card-default">
<div class="card-header clearfix">
<div class="card-title">{% translate "Search Results" %}</div>
</div>
<div class="panel-body">
<div class="card-body mt-2">
<table class="table table-hover" id="table-search">
<thead>
<tr>
<th class="text-center"></th>
<th class="text-center">{% translate "Character" %}</th>
<th class="text-center">{% translate "Corporation" %}</th>
<th class="text-center">{% translate "zKillboard" %}</th>
<th class="text-center">{% translate "Main Character" %}</th>
<th class="text-center">{% translate "Main Corporation" %}</th>
<th class="text-center">{% translate "Main Alliance" %}</th>
<th></th>
<th>{% translate "Character" %}</th>
<th>{% translate "Corporation" %}</th>
<th>{% translate "zKillboard" %}</th>
<th>{% translate "Main Character" %}</th>
<th>{% translate "Main Corporation" %}</th>
<th>{% translate "Main Alliance" %}</th>
</tr>
</thead>
<tbody>
{% for result in results %}
<tr {% if not result.1.registered %}class="danger"{% endif %}>
<td class="text-center"><img src="{{ result.1.portrait_url }}" class="img-circle" alt="{{ result.1.character_name }}"></td>
<td class="text-center">{{ result.1.character_name }}</td>
<td class="text-center">{{ result.0.corp.corporation_name }}</td>
<td class="text-center"><a href="https://zkillboard.com/character/{{ result.1.character_id }}/" class="badge bg-danger" target="_blank">{% translate "Killboard" %}</a></td>
<td class="text-center">{{ result.1.main_character.character_name }}</td>
<td class="text-center">{{ result.1.main_character.corporation_name }}</td>
<td class="text-center">{{ result.1.main_character.alliance_name }}</td>
<td><img src="{{ result.1.portrait_url }}" class="img-circle" alt="{{ result.1.character_name }}"></td>
<td>{{ result.1.character_name }}</td>
<td >{{ result.0.corp.corporation_name }}</td>
<td><a href="https://zkillboard.com/character/{{ result.1.character_id }}/" class="badge bg-danger" target="_blank">{% translate "Killboard" %}</a></td>
<td>{{ result.1.main_character.character_name }}</td>
<td>{{ result.1.main_character.corporation_name }}</td>
<td>{{ result.1.main_character.alliance_name }}</td>
</tr>
{% endfor %}
</tbody>
@@ -35,17 +38,20 @@
</div>
</div>
{% endblock %}
{% block extra_javascript %}
{% include 'bundles/datatables-js.html' %}
{% endblock %}
{% block extra_css %}
{% include 'bundles/datatables-css.html' %}
{% endblock %}
{% block extra_script %}
$(document).ready(function(){
$('#table-search').DataTable({
"stateSave": true,
"stateDuration": 0
{% include 'bundles/datatables-js-bs5.html' %}
<script>
$(document).ready(() => {
$('#table-search').DataTable({
"stateSave": true,
"stateDuration": 0
});
});
});
</script>
{% endblock %}
{% block extra_css %}
{% include 'bundles/datatables-css-bs5.html' %}
{% endblock %}

View File

@@ -14,15 +14,13 @@ Needs to be called with a context containing three objects:
{% block page_title %}Evelinks Examples{% endblock page_title %}
{% block content %}
<div>
{% include "framework/header/page-header.html" with title="Evelinks templatetags examples" %}
<div class="col-lg-12">
<h1 class="page-header text-center">Evelinks templatetags examples</h1>
<div class="col-lg-12 container">
<h2>profile URLs</h2>
<div class="rows">
<div class="col-md-4">
<h3>evewho</h3>
<p><a href="{{ my_character|evewho_character_url }}">character from character object</a></p>
@@ -57,7 +55,6 @@ Needs to be called with a context containing three objects:
<h2>image URLs</h2>
<div class="rows">
<div class="col-md-4">
<p>character from ID: <img src="{{ my_character.character_id|character_portrait_url:128 }}"></p>
<p>character from character object: <img src="{{ my_character|character_portrait_url:128 }}"></p>
@@ -77,5 +74,4 @@ Needs to be called with a context containing three objects:
</div>
</div>
</div>
{% endblock content %}

View File

@@ -7,7 +7,7 @@ from allianceauth.services.hooks import UrlHook
@hooks.register('menu_item_hook')
def register_menu():
return MenuItemHook(_('Fleet Activity Tracking'), 'fas fa-users fa-fw', 'fatlink:view',
return MenuItemHook(_('Fleet Activity Tracking'), 'fa-solid fa-users', 'fatlink:view',
navactive=['fatlink:'])

View File

@@ -4,4 +4,4 @@ from django.utils.translation import gettext_lazy as _
class FatlinkForm(forms.Form):
fleet = forms.CharField(label=_("Fleet Name"), max_length=50)
duration = forms.IntegerField(label=_("Duration of fat-link"), required=True, initial=30, min_value=1, max_value=2147483647, help_text=_('minutes'))
duration = forms.IntegerField(label=_("Duration of fat-link"), required=True, initial=30, min_value=1, max_value=2147483647, help_text=_('Duration of the fat-link in minutes'))

View File

@@ -0,0 +1,26 @@
"""
Migration to AA Framework API method
"""
from django.conf import settings
from django.db import migrations, models
import allianceauth.framework.api.user
class Migration(migrations.Migration):
dependencies = [
("fleetactivitytracking", "0006_auto_20180803_0430"),
]
operations = [
migrations.AlterField(
model_name="fatlink",
name="creator",
field=models.ForeignKey(
on_delete=models.SET(allianceauth.framework.api.user.get_sentinel_user),
to=settings.AUTH_USER_MODEL
),
),
]

View File

@@ -3,10 +3,7 @@ from django.db import models
from django.utils import timezone
from allianceauth.eveonline.models import EveCharacter
def get_sentinel_user():
return User.objects.get_or_create(username='deleted')[0]
from allianceauth.framework.api.user import get_sentinel_user
class Fatlink(models.Model):

View File

@@ -1,23 +1,43 @@
{% extends 'allianceauth/base-bs5.html' %}
{% load i18n %}
{% block page_title %}
{% translate "Fleet Participation" %}
{% endblock %}
{% block header_nav_brand %}
{% translate "Fleet Activity Tracking" %}
{% endblock header_nav_brand %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "Character not found!" %}</h1>
<div class="col-lg-12 container" id="example">
<div>
{% translate "Character not found!" as page_header %}
{% include "framework/header/page-header.html" with title=page_header %}
<div class="col-lg-12 container">
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">{{ character_name }}</div>
<div class="panel-body">
<div class="card card-default">
<div class="card-header">
<div class="card-title mb-0">
{{ character_name }}
</div>
</div>
<div class="card-body">
<div class="col-lg-2 col-sm-2">
<img class="ra-avatar img-responsive" src="{{ character_portrait_url }}" alt="{{ character_name }}">
</div>
<div class="col-lg-10 col-sm-2">
<div class="alert alert-danger" role="alert">{% translate "Character not registered!" %}</div>
{% translate "This character is not associated with an auth account." %} <a href=" {% url 'authentication:add_character' %}">{% translate "Add it here" %}</a> {% translate "before attempting to click fleet attendance links." %}
<div class="alert alert-danger" role="alert">
{% translate "Character not registered!" %}
</div>
{% translate "This character is not associated with an auth account." %}
<a href="{% url 'authentication:add_character' %}">{% translate "Add it here" %}</a>
{% translate "before attempting to click fleet attendance links." %}
</div>
</div>
</div>

View File

@@ -0,0 +1,53 @@
{% extends "allianceauth/base-bs5.html" %}
{% load django_bootstrap5 %}
{% load i18n %}
{% block page_title %}
{% translate "Create Fatlink" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "Fleet Activity Tracking" %}
{% endblock header_nav_brand %}
{% block content %}
<div>
{% translate "Create Fatlink" as page_header %}
{% include "framework/header/page-header.html" with title=page_header %}
<div>
{% if badrequest %}
<div class="alert alert-danger" role="alert">{% translate "Bad request!" %}</div>
{% endif %}
{% for message in errormessages %}
<div class="alert alert-danger" role="alert">{{ message }}</div>
{% endfor %}
<div class="card card-primary border-0">
<div class="card-header">
<div class="card-title mb-0">
{% translate "Fatlink details" %}
</div>
</div>
<div class="card-body">
<div class="row justify-content-center">
<div class="col-md-6">
<form role="form" action="" method="POST">
{% csrf_token %}
{% bootstrap_form form %}
<div class="form-group mt-3 clearfix">
{% translate "Create fatlink" as button_text %}
{% bootstrap_button button_class="btn btn-primary" content=button_text name="submit_fat" id="submit_fat" %}
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}

View File

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

View File

@@ -1,21 +1,35 @@
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}{% translate "Fatlink view" %}{% endblock page_title %}
{% block page_title %}
{% translate "Fatlink view" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "Fleet Activity Tracking" %}
{% endblock header_nav_brand %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "Edit fatlink" %} "{{ fatlink }}"
<div class="text-end">
<form>
<button type="submit" onclick="return confirm('Are you sure?')" class="btn btn-danger" name="deletefat" value="True">
{% translate "Delete fat" %}
</button>
</form>
</div>
<div>
<h1 class="page-header text-center mb-3">
{% translate "Edit fatlink" %} "{{ fatlink }}"
</h1>
<div class="panel panel-default">
<div class="panel-heading">{% translate "Registered characters" %}</div>
<div class="panel-body">
<div class="text-end mb-3">
<form>
<button type="submit" onclick="return confirm('{% translate "Are you sure?" %}')" class="btn btn-danger" name="deletefat" value="True">
{% translate "Delete fat" %}
</button>
</form>
</div>
<div class="card card-default">
<div class="card-header">
<div class="card-title mb-0">{% translate "Registered characters" %}</div>
</div>
<div class="card-body">
<table class="table table-responsive table-hover">
<tr>
<th class="text-center">{% translate "User" %}</th>
@@ -25,21 +39,23 @@
<th class="text-center">{% translate "Eve Time" %}</th>
<th></th>
</tr>
{% for fat in registered_fats %}
<tr>
<td class="text-center">{{ fat.user }}</td>
<td class="text-center">{{ fat.character.character_name }}</td>
{% if fat.station != "No Station" %}
<td class="text-center">{% blocktranslate %}Docked in {% endblocktranslate %}{{ fat.system }}</td>
{% else %}
<td class="text-center">{{ fat.system }}</td>
{% endif %}
<td class="text-center">
{% if fat.station != "No Station" %}
{% translate "Docked in" %}
{% endif %}
{{ fat.system }}
</td>
<td class="text-center">{{ fat.shiptype }}</td>
<td class="text-center">{{ fat.fatlink.fatdatetime }}</td>
<td class="text-center">
<form>
<button type="submit" class="btn btn-warning" name="removechar" value="{{ fat.character.character_id }}">
<span class="glyphicon glyphicon-remove"></span>
<i class="fa-solid fa-trash-can fa-fw"></i>
</button>
</form>
</td>

View File

@@ -1,71 +1,104 @@
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}{% translate "Personal fatlink statistics" %}{% endblock page_title %}
{% block page_title %}
{% translate "Personal fatlink statistics" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "Fleet Activity Tracking" %}
{% endblock header_nav_brand %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% blocktranslate %}Participation data statistics for {{ month }}, {{ year }}{% endblocktranslate %}
{% if char_id %}
<div class="text-end">
<a href="{% url 'fatlink:user_statistics_month' char_id previous_month|date:'Y' previous_month|date:'m' %}" class="btn btn-info">{% translate "Previous month" %}</a>
<a href="{% url 'fatlink:user_statistics_month' char_id next_month|date:'Y' next_month|date:'m' %}" class="btn btn-info">{% translate "Next month" %}</a>
</div>
{% endif %}
<div>
<h1 class="page-header text-center mb-3">
{% blocktranslate %}Participation data statistics for {{ month }}, {{ year }}{% endblocktranslate %}
</h1>
<h2>
{% blocktranslate count links=n_fats trimmed %}
{{ user }} has collected one link this month.
{% plural %}
{{ user }} has collected {{ links }} links this month.
{% endblocktranslate %}
</h2>
<table class="table table-responsive">
<tr>
<th class="col-md-2 text-center">{% translate "Ship" %}</th>
<th class="col-md-2 text-center">{% translate "Times used" %}</th>
</tr>
{% for ship, n_fats in shipStats %}
<tr>
<td class="text-center">{{ ship }}</td>
<td class="text-center">{{ n_fats }}</td>
</tr>
{% endfor %}
</table>
{% if created_fats %}
<h2>
{% blocktranslate count links=n_created_fats trimmed %}
{{ user }} has created one link this month.
{% plural %}
{{ user }} has created {{ links }} links this month.
{% endblocktranslate %}
</h2>
{% if created_fats %}
<table class="table">
<tr>
<th class="text-center">{% translate "Fleet" %}</th>
<th class="text-center">{% translate "Creator" %}</th>
<th class="text-center">{% translate "Eve Time" %}</th>
<th class="text-center">{% translate "Duration" %}</th>
<th class="text-center">{% translate "Edit" %}</th>
</tr>
{% for link in created_fats %}
<tr>
<td class="text-center"><a href="{% url 'fatlink:click' link.hash %}" class="badge bg-primary">{{ link.fleet }}</a></td>
<td class="text-center">{{ link.creator.username }}</td>
<td class="text-center">{{ link.fatdatetime }}</td>
<td class="text-center">{{ link.duration }}</td>
<td class="text-center">
<a href="{% url 'fatlink:modify' link.hash %}">
<button type="button" class="btn btn-info"><span
class="glyphicon glyphicon-edit"></span></button>
</a>
</td>
</tr>
{% endfor %}
{% if char_id %}
<div class="text-end mb-3">
<a href="{% url 'fatlink:user_statistics_month' char_id previous_month|date:'Y' previous_month|date:'m' %}" class="btn btn-info">
{% translate "Previous month" %}
</a>
<a href="{% url 'fatlink:user_statistics_month' char_id next_month|date:'Y' next_month|date:'m' %}" class="btn btn-info">
{% translate "Next month" %}
</a>
</div>
{% endif %}
<div class="card card-default mb-3">
<div class="card-header">
<div class="card-title mb-0">
{% blocktranslate count links=n_fats trimmed %}
{{ user }} has collected one link this month.
{% plural %}
{{ user }} has collected {{ links }} links this month.
{% endblocktranslate %}
</div>
</div>
<div class="card-body">
<table class="table table-responsive">
<tr>
<th class="col-md-2 text-center">{% translate "Ship" %}</th>
<th class="col-md-2 text-center">{% translate "Times used" %}</th>
</tr>
{% for ship, n_fats in shipStats %}
<tr>
<td class="text-center">{{ ship }}</td>
<td class="text-center">{{ n_fats }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
</div>
</div>
{% if created_fats %}
<div class="card card-default">
<div class="card-header">
<div class="card-title mb-0">
{% blocktranslate count links=n_created_fats trimmed %}
{{ user }} has created one link this month.
{% plural %}
{{ user }} has created {{ links }} links this month.
{% endblocktranslate %}
</div>
</div>
<div class="card-body">
<table class="table">
<tr>
<th class="text-center">{% translate "Fleet" %}</th>
<th class="text-center">{% translate "Creator" %}</th>
<th class="text-center">{% translate "Eve Time" %}</th>
<th class="text-center">{% translate "Duration" %}</th>
<th class="text-center">{% translate "Edit" %}</th>
</tr>
{% for link in created_fats %}
<tr>
<td class="text-center">
<a href="{% url 'fatlink:click' link.hash %}" class="badge bg-primary">
{{ link.fleet }}
</a>
</td>
<td class="text-center">{{ link.creator.username }}</td>
<td class="text-center">{{ link.fatdatetime }}</td>
<td class="text-center">{{ link.duration }}</td>
<td class="text-center">
<a href="{% url 'fatlink:modify' link.hash %}">
<button type="button" class="btn btn-info">
<i class="fa-solid fa-pen-to-square fa-fw"></i>
</button>
</a>
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endif %}
</div>
{% endblock content %}

View File

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

View File

@@ -1,50 +1,63 @@
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}
{% translate "Fatlink Corp Statistics" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "Fleet Activity Tracking" %}
{% endblock header_nav_brand %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">
<div>
<h1 class="page-header text-center mb-3">
{% blocktranslate %}Participation data statistics for {{ month }}, {{ year }}{% endblocktranslate %}
<div class="text-end">
<a href="{% url "fatlink:statistics_corp_month" corpid previous_month|date:"Y" previous_month|date:"m" %}" class="btn btn-info">{% translate "Previous month" %}</a>
{% if next_month %}
<a href="{% url "fatlink:statistics_corp_month" corpid next_month|date:"Y" next_month|date:"m" %}" class="btn btn-info">{% translate "Next month" %}</a>
{% endif %}
</div>
</h1>
{% if fatStats %}
<div class="table-responsive">
<table class="table table-striped">
<tr>
<th scope="col" class="col-md-1"></th>
<th scope="col" class="col-md-2 text-center">{% translate "Main Character" %}</th>
<th scope="col" class="col-md-2 text-center">{% translate "Characters" %}</th>
<th scope="col" class="col-md-2 text-center">{% translate "Fats" %}</th>
<th scope="col" class="col-md-2 text-center">
{% translate "Average fats" %}
<i class="fa-solid fa-question" rel="tooltip" title="Fats / Characters"></i>
</th>
</tr>
{% for memberStat in fatStats %}
<tr>
<td>
<img src="{{ memberStat.mainchar.portrait_url_32 }}" class="ra-avatar img-responsive" alt="{{ memberStat.mainchar.character_name }}">
</td>
<td class="text-center">{{ memberStat.mainchar.character_name }}</td>
<td class="text-center">{{ memberStat.n_chars }}</td>
<td class="text-center">{{ memberStat.n_fats }}</td>
<td class="text-center">{{ memberStat.avg_fat }}</td>
</tr>
{% endfor %}
</table>
<div class="text-end mb-3">
<a href="{% url "fatlink:statistics_corp_month" corpid previous_month|date:"Y" previous_month|date:"m" %}" class="btn btn-info">{% translate "Previous month" %}</a>
{% if next_month %}
<a href="{% url "fatlink:statistics_corp_month" corpid next_month|date:"Y" next_month|date:"m" %}" class="btn btn-info">{% translate "Next month" %}</a>
{% endif %}
</div>
{% if fatStats %}
<div class="table-responsive">
<table class="table table-striped">
<tr>
<th scope="col" class="col-md-1"></th>
<th scope="col" class="col-md-2 text-center">{% translate "Main Character" %}</th>
<th scope="col" class="col-md-2 text-center">{% translate "Characters" %}</th>
<th scope="col" class="col-md-2 text-center">{% translate "Fats" %}</th>
<th scope="col" class="col-md-2 text-center">
{% translate "Average fats" %}
<i class="fa-solid fa-question" rel="tooltip" title="Fats / Characters"></i>
</th>
</tr>
{% for memberStat in fatStats %}
<tr>
<td>
<img src="{{ memberStat.mainchar.portrait_url_32 }}" class="ra-avatar img-responsive" alt="{{ memberStat.mainchar.character_name }}">
</td>
<td class="text-center">{{ memberStat.mainchar.character_name }}</td>
<td class="text-center">{{ memberStat.n_chars }}</td>
<td class="text-center">{{ memberStat.n_fats }}</td>
<td class="text-center">{{ memberStat.avg_fat }}</td>
</tr>
{% endfor %}
</table>
</div>
{% endif %}
</div>
{% endblock content %}
{% block extra_script %}
$(document).ready(function () {
$("[rel=tooltip]").tooltip();
});
{% endblock extra_script %}
{% block extra_javascript %}
<script>
$(document).ready(() => {
$("[rel=tooltip]").tooltip();
});
</script>
{% endblock extra_javascript %}

View File

@@ -1,54 +1,67 @@
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}
{% translate "Fatlink Statistics" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "Fleet Activity Tracking" %}
{% endblock header_nav_brand %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">
<div>
<h1 class="page-header text-center mb-3">
{% blocktranslate %}Participation data statistics for {{ month }}, {{ year }}{% endblocktranslate %}
<div class="text-end">
<a href="{% url "fatlink:statistics_month" previous_month|date:"Y" previous_month|date:"m" %}" class="btn btn-info">{% translate "Previous month" %}</a>
{% if next_month %}
<a href="{% url 'fatlink:statistics_month' next_month|date:"Y" next_month|date:"m" %}" class="btn btn-info">{% translate "Next month" %}</a>
{% endif %}
</div>
</h1>
{% if fatStats %}
<div class="table-responsive">
<table class="table table-striped">
<tr>
<th scope="col" class="col-md-1"></th>
<th scope="col" class="col-md-2 text-center">{% translate "Ticker" %}</th>
<th scope="col" class="col-md-5 text-center">{% translate "Corp" %}</th>
<th scope="col" class="col-md-2 text-center">{% translate "Members" %}</th>
<th scope="col" class="col-md-2 text-center">{% translate "Fats" %}</th>
<th scope="col" class="col-md-2 text-center">
{% translate "Average fats" %}
<i class="fa-solid fa-question" rel="tooltip" title="Fats / Characters"></i>
</th>
</tr>
{% for corpStat in fatStats %}
<tr>
<td>
<img src="{{ corpStat.corp.logo_url_32 }}" class="ra-avatar img-responsive" alt="{{ corpStat.corp.corporation_name }}">
</td>
<td class="text-center">
<a href="{% url 'fatlink:statistics_corp' corpStat.corp.corporation_id %}">[{{ corpStat.corp.corporation_ticker }}]</a>
</td>
<td class="text-center">{{ corpStat.corp.corporation_name }}</td>
<td class="text-center">{{ corpStat.corp.member_count }}</td>
<td class="text-center">{{ corpStat.n_fats }}</td>
<td class="text-center">{{ corpStat.avg_fat }}</td>
</tr>
{% endfor %}
</table>
<div class="text-end mb-3">
<a href="{% url "fatlink:statistics_month" previous_month|date:"Y" previous_month|date:"m" %}" class="btn btn-info">{% translate "Previous month" %}</a>
{% if next_month %}
<a href="{% url 'fatlink:statistics_month' next_month|date:"Y" next_month|date:"m" %}" class="btn btn-info">{% translate "Next month" %}</a>
{% endif %}
</div>
{% if fatStats %}
<div class="table-responsive">
<table class="table table-striped">
<tr>
<th scope="col" class="col-md-1"></th>
<th scope="col" class="col-md-2 text-center">{% translate "Ticker" %}</th>
<th scope="col" class="col-md-5 text-center">{% translate "Corp" %}</th>
<th scope="col" class="col-md-2 text-center">{% translate "Members" %}</th>
<th scope="col" class="col-md-2 text-center">{% translate "Fats" %}</th>
<th scope="col" class="col-md-2 text-center">
{% translate "Average fats" %}
<i class="fa-solid fa-question" rel="tooltip" title="Fats / Characters"></i>
</th>
</tr>
{% for corpStat in fatStats %}
<tr>
<td>
<img src="{{ corpStat.corp.logo_url_32 }}" class="ra-avatar img-responsive" alt="{{ corpStat.corp.corporation_name }}">
</td>
<td class="text-center">
<a href="{% url 'fatlink:statistics_corp' corpStat.corp.corporation_id %}">[{{ corpStat.corp.corporation_ticker }}]</a>
</td>
<td class="text-center">{{ corpStat.corp.corporation_name }}</td>
<td class="text-center">{{ corpStat.corp.member_count }}</td>
<td class="text-center">{{ corpStat.n_fats }}</td>
<td class="text-center">{{ corpStat.avg_fat }}</td>
</tr>
{% endfor %}
</table>
</div>
{% endif %}
</div>
{% endblock content %}
{% block extra_script %}
$(document).ready(function () {
$("[rel=tooltip]").tooltip();
});
{% endblock extra_script %}
{% block extra_javascript %}
<script>
$(document).ready(() => {
$("[rel=tooltip]").tooltip();
});
</script>
{% endblock extra_javascript %}

View File

@@ -1,11 +1,20 @@
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}
{% translate "Fatlink view" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "Fleet Activity Tracking" %}
{% endblock header_nav_brand %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "Participation data" %}</h1>
<div>
{% translate "Participation data" as page_header %}
{% include "framework/header/page-header.html" with title=page_header %}
<div class="table-responsive">
<table class="table table-striped">
<tr>
@@ -15,11 +24,15 @@
</h4>
</th>
<th class="col-md-2 align-self-end">
<a href="{% url 'fatlink:personal_statistics' %}" class="btn btn-info"><i class="fa-solid fa-circle-info fa-fw"></i>{% translate "Personal statistics" %}</a>
<a href="{% url 'fatlink:personal_statistics' %}" class="btn btn-info">
<i class="fa-solid fa-circle-info fa-fw"></i>
{% translate "Personal statistics" %}
</a>
</th>
</tr>
</table>
</div>
{% if fats %}
<div class="table-responsive">
<table class="table table-striped">
@@ -30,6 +43,7 @@
<th scope="col" class="text-center">{% translate "Ship" %}</th>
<th scope="col" class="text-center">{% translate "Eve Time" %}</th>
</tr>
{% for fat in fats %}
<tr>
<td class="text-center">{{ fat.fatlink.fleet }}</td>
@@ -48,6 +62,7 @@
{% else %}
<div class="alert alert-warning text-center">{% translate "No fleet activity on record." %}</div>
{% endif %}
{% if perms.auth.fleetactivitytracking %}
<div class="table-responsive">
<table class="table table-striped">
@@ -66,6 +81,7 @@
</tr>
</table>
</div>
{% if fatlinks %}
<div class="table-responsive">
<table class="table table-striped">
@@ -77,6 +93,7 @@
<th scope="col" class="text-center">{% translate "Duration" %}</th>
<th scope="col" class="text-center">{% translate "Edit" %}</th>
</tr>
{% for link in fatlinks %}
<tr>
<td class="text-center">

View File

@@ -352,11 +352,11 @@ def create_fatlink_view(request):
for errorname, message in e.message_dict.items():
messages.append(message[0].decode())
context = {'form': form, 'errormessages': messages}
return render(request, 'fleetactivitytracking/fatlinkformatter.html', context=context)
return render(request, 'fleetactivitytracking/fatlinkcreate.html', context=context)
else:
form = FatlinkForm()
context = {'form': form, 'badrequest': True}
return render(request, 'fleetactivitytracking/fatlinkformatter.html', context=context)
return render(request, 'fleetactivitytracking/fatlinkcreate.html', context=context)
return redirect('fatlink:view')
else:
@@ -365,7 +365,7 @@ def create_fatlink_view(request):
context = {'form': form}
return render(request, 'fleetactivitytracking/fatlinkformatter.html', context=context)
return render(request, 'fleetactivitytracking/fatlinkcreate.html', context=context)
@login_required
@@ -377,12 +377,12 @@ def modify_fatlink_view(request, fat_hash=None):
if request.GET.get('removechar', None):
character_id = request.GET.get('removechar')
character = EveCharacter.objects.get(character_id=character_id)
logger.debug(f"Removing character {character.character_name} from fleetactivitytracking {fatlink}")
logger.debug(f"Removing character {character.character_name} from fleetactivitytracking {fatlink}")
Fat.objects.filter(fatlink=fatlink).filter(character=character).delete()
if request.GET.get('deletefat', None):
logger.debug("Removing fleetactivitytracking %s" % fatlink)
logger.debug("Removing fleetactivitytracking %s" % fatlink)
fatlink.delete()
return redirect('fatlink:view')

View File

@@ -0,0 +1,3 @@
"""
Alliance Auth Framework
"""

View File

@@ -0,0 +1,64 @@
"""
Alliance Auth User API
"""
from typing import Optional
from django.contrib.auth.models import User
from allianceauth.eveonline.models import EveCharacter
def get_sentinel_user() -> User:
"""
Get the sentinel user or create one
:return:
"""
return User.objects.get_or_create(username="deleted")[0]
def get_main_character_from_user(user: User) -> Optional[EveCharacter]:
"""
Get the main character from a user
:param user:
:type user:
:return:
:rtype:
"""
if user is None:
return None
try:
main_character = user.profile.main_character
except AttributeError:
return None
return main_character
def get_main_character_name_from_user(user: User) -> str:
"""
Get the main character name from a user
:param user:
:type user:
:return:
:rtype:
"""
if user is None:
sentinel_user = get_sentinel_user()
return sentinel_user.username
main_character = get_main_character_from_user(user=user)
try:
username = main_character.character_name
except AttributeError:
return str(user)
return username

View File

@@ -0,0 +1,14 @@
"""
Framework App Config
"""
from django.apps import AppConfig
class FrameworkConfig(AppConfig):
"""
Framework App Config
"""
name = "allianceauth.framework"
label = "framework"

View File

@@ -0,0 +1,13 @@
{#Usage:#}
{# {% include "framework/header/page-header.html" with title="Foobar" subtitle="Barfoo" %}#}
{% if title %}
<h1 class="page-header text-center mb-3">
{{ title }}
{% if subtitle %}
<br>
<small>{{ subtitle }}</small>
{% endif %}
</h1>
{% endif %}

View File

@@ -0,0 +1,3 @@
"""
Initializing our tests
"""

View File

@@ -0,0 +1,179 @@
"""
Test sentinel user
"""
import re
# Django
from django.contrib.auth.models import User
from django.test import TestCase
# Alliance Auth
from allianceauth.framework.api.user import (
get_sentinel_user,
get_main_character_from_user,
get_main_character_name_from_user
)
from allianceauth.tests.auth_utils import AuthUtils
class TestSentinelUser(TestCase):
"""
Tests for the sentinel user
"""
def test_should_create_user_when_it_does_not_exist(self) -> None:
"""
Test should create a sentinel user when it doesn't exist
:return:
:rtype:
"""
# when
user = get_sentinel_user()
# then
self.assertEqual(first=user.username, second="deleted")
def test_should_return_user_when_it_does(self) -> None:
"""
Test should return sentinel user when it exists
:return:
:rtype:
"""
# given
User.objects.create_user(username="deleted")
# when
user = get_sentinel_user()
# then
self.assertEqual(first=user.username, second="deleted")
class TestGetMainForUser(TestCase):
"""
Tests for get_main_character_from_user
"""
@classmethod
def setUpClass(cls) -> None:
"""
Set up groups and users
"""
super().setUpClass()
cls.character_name = "William T. Riker"
cls.character_name_2 = "Christopher Pike"
cls.username = re.sub(pattern=r"[^\w\d@\.\+-]", repl="_", string=cls.character_name)
cls.username_2 = re.sub(
pattern=r"[^\w\d@\.\+-]", repl="_", string=cls.character_name_2
)
cls.user = AuthUtils.create_user(username=cls.username)
cls.user_without_main = AuthUtils.create_user(
username=cls.username_2, disconnect_signals=True
)
cls.character = AuthUtils.add_main_character_2(
user=cls.user, name=cls.character_name, character_id=1001
)
def test_get_main_character_from_user_should_return_character_name(self):
"""
Test should return the main character name for a regular user
:return:
:rtype:
"""
character = get_main_character_from_user(user=self.user)
self.assertEqual(first=character, second=self.character)
def test_get_main_character_from_user_should_return_none_for_no_main_character(self):
"""
Test should return None for User without a main character
:return:
:rtype:
"""
character = get_main_character_from_user(user=self.user_without_main)
self.assertIsNone(obj=character)
def test_get_main_character_from_user_should_none(self):
"""
Test should return None when user is None
:return:
:rtype:
"""
user = None
character = get_main_character_from_user(user=user)
self.assertIsNone(obj=character)
def test_get_main_character_name_from_user_should_return_character_name(self):
"""
Test should return the main character name for a regular user
:return:
:rtype:
"""
character_name = get_main_character_name_from_user(user=self.user)
self.assertEqual(first=character_name, second=self.character_name)
def test_get_main_character_name_from_user_should_return_user_name(self):
"""
Test should return just the username for a user without a main character
:return:
:rtype:
"""
character_name = get_main_character_name_from_user(user=self.user_without_main)
self.assertEqual(first=character_name, second=self.username_2)
def test_get_main_character_name_from_user_should_return_sentinel_user(self):
"""
Test should return "deleted" as username (Sentinel User)
:return:
:rtype:
"""
user = get_sentinel_user()
character_name = get_main_character_name_from_user(user=user)
self.assertEqual(first=character_name, second="deleted")
def test_get_main_character_name_from_user_should_return_sentinel_user_for_none(self):
"""
Test should return "deleted" (Sentinel User) if user is None
:return:
:rtype:
"""
user = None
character_name = get_main_character_name_from_user(user=user)
self.assertEqual(first=character_name, second="deleted")

View File

@@ -16,7 +16,7 @@ class GroupManagementMenuItem(MenuItemHook):
MenuItemHook.__init__(
self,
text=_("Group Management"),
classes="fas fa-users-cog fa-fw",
classes="fa-solid fa-users-gear",
url_name="groupmanagement:management",
order=50,
navactive=[
@@ -36,7 +36,7 @@ class GroupManagementMenuItem(MenuItemHook):
"""
<li class="d-flex m-2 p-2 pt-0 pb-0 mt-0 mb-0">
<i class="fas fa-users fa-fw align-self-center me-2"></i>
<i class="fa-solid fa-users fa-fw align-self-center me-2"></i>
<a class="nav-link flex-fill align-self-center {% navactive request 'groupmanagement:groups' %}" href="{% url 'groupmanagement:groups' %}">
{% translate "Groups" %}
</a>
@@ -49,7 +49,7 @@ class GroupsMenuItem(MenuItemHook):
MenuItemHook.__init__(
self,
text=_("Groups"),
classes="fas fa-user fa-fw",
classes="fa-solid fa-user",
url_name="groupmanagement:groups",
order=25,
navactive=[

View File

@@ -1,6 +1,10 @@
import functools
from django import forms
from django.contrib.auth.models import Group
from django.contrib.admin.widgets import FilteredSelectMultiple
from django.contrib.auth.models import Group, User
from django.core.exceptions import ValidationError
from django.db.models.functions import Lower
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
@@ -8,6 +12,39 @@ from .models import ReservedGroupName
class GroupAdminForm(forms.ModelForm):
users = forms.ModelMultipleChoiceField(
queryset=User.objects.order_by(Lower('username')),
required=False,
widget=FilteredSelectMultiple(verbose_name=_("Users"), is_stacked=False),
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance and self.instance.pk:
self.fields["users"].initial = self.instance.user_set.all()
def save(self, commit=True):
group: Group = super().save(commit=False)
if commit:
group.save()
users = self.cleaned_data["users"]
if group.pk:
self._save_m2m_and_users(group, users)
else:
self.save_m2m = functools.partial(
self._save_m2m_and_users, group=group, users=users
)
return group
def _save_m2m_and_users(self, group, users):
"""Save m2m relations incl. users."""
group.user_set.set(users)
self._save_m2m()
def clean_name(self):
my_name = self.cleaned_data['name']
if ReservedGroupName.objects.filter(name__iexact=my_name).exists():

View File

@@ -74,11 +74,11 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='AuthGroup',
fields=[
('group', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='auth.Group')),
('group', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='auth.Group')),
('internal', models.BooleanField(default=True, help_text='Internal group, users cannot see, join or request to join this group.<br>Used for groups such as Members, Corp_*, Alliance_* etc.<br><b>Overrides Hidden and Open options when selected.</b>')),
('hidden', models.BooleanField(default=True, help_text='Group is hidden from users but can still join with the correct link.')),
('open', models.BooleanField(default=False, help_text='Group is open and users will be automatically added upon request. <br>If the group is not open users will need their request manually approved.')),
('description', models.CharField(max_length=512, blank=True, help_text='Description of the group shown to users.', )),
('description', models.CharField(max_length=512, blank=True, help_text='Description of the group shown to users.', )),
('group_leaders', models.ManyToManyField(related_name='leads_groups', to=settings.AUTH_USER_MODEL, blank=True, help_text='Group leaders can process group requests for this group specifically. Use the auth.group_management permission to allow a user to manage all groups.',)),
],

View File

@@ -1,8 +1,7 @@
from typing import Set
from django.conf import settings
from django.contrib.auth.models import Group
from django.contrib.auth.models import User
from django.contrib.auth.models import Group, User
from django.db import models
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
@@ -14,7 +13,7 @@ from allianceauth.notifications import notify
class GroupRequest(models.Model):
"""Request from a user for joining or leaving a group."""
leave_request = models.BooleanField(default=0)
leave_request = models.BooleanField(default=False)
user = models.ForeignKey(User, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
@@ -49,7 +48,7 @@ class RequestLog(models.Model):
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)
action = models.BooleanField(default=False)
request_actor = models.ForeignKey(User, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True)

View File

@@ -1,15 +1,21 @@
{% extends "allianceauth/base-bs5.html" %}
{% load static %}
{% load i18n %}
{% load navactive %}
{% block page_title %}{{ group }} {% translate "Audit Log" %}{% endblock page_title %}
{% block header_nav_brand %}{% translate "Audit Log" %} - {{ group.name }}{% endblock header_nav_brand %}
{% block page_title %}
{{ group }} {% translate "Audit Log" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "Audit Log" %} - {{ group.name }}
{% endblock header_nav_brand %}
{% block header_nav_collapse_left %}
<li class="nav-item ">
<a class="nav-link {% navactive request 'groupmanagement:management' %}" href="{% url 'groupmanagement:management' %}">{% translate "Back" %}</a>
</li>
<li class="nav-item">
<a class="nav-link {% navactive request 'groupmanagement:management' %}" href="{% url 'groupmanagement:management' %}">{% translate "Back" %}</a>
</li>
{% endblock %}
{% block content %}
@@ -65,61 +71,61 @@
{% block extra_javascript %}
{% include 'bundles/datatables-js-bs5.html' %}
{% include 'bundles/moment-js.html' with locale=True %}
{% include 'bundles/filterdropdown-js.html' %}
{# {% include 'bundles/filterdropdown-js.html' %}#}
<script>
$.fn.dataTable.moment = (format, locale) => {
const types = $.fn.dataTable.ext.type;
// Add type detection
types.detect.unshift((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' ] = (d) => {
return moment(d, format, locale, true).unix();
};
};
$(document).ready(() => {
$.fn.dataTable.moment('YYYY-MMM-D, HH:mm');
$('#log-entries').DataTable({
order: [[0, 'desc'], [1, 'asc']],
filterDropDown:
{
columns: [
{
idx: 1
},
{
idx: 2
},
{
idx: 3
},
{
idx: 4
},
{
idx: 5
},
{
idx: 6
}
],
bootstrap: true
},
"stateSave": true,
"stateDuration": 0
});
});
</script>
{% endblock %}
{% block extra_css %}
{% include 'bundles/datatables-css-bs5.html' %}
{% endblock %}
{% block extra_script %}
$.fn.dataTable.moment = function(format, locale) {
let 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']],
filterDropDown:
{
columns: [
{
idx: 1
},
{
idx: 2
},
{
idx: 3
},
{
idx: 4
},
{
idx: 5
},
{
idx: 6
}
],
bootstrap: true
},
"stateSave": true,
"stateDuration": 0
});
});
{% endblock %}

View File

@@ -1,22 +1,28 @@
{% extends "allianceauth/base-bs5.html" %}
{% load static %}
{% load i18n %}
{% load evelinks %}
{% load navactive %}
{% block page_title %}{% translate "Group Members" %}{% endblock page_title %}
{% block header_nav_brand %}{% translate "Group Members" %} - {{ group.name }}{% endblock header_nav_brand %}
{% block page_title %}
{% translate "Group Members" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "Group Members" %} - {{ group.name }}
{% endblock header_nav_brand %}
{% block header_nav_collapse_left %}
<li class="nav-item ">
<a class="nav-link {% navactive request 'groupmanagement:management' %}" href="{% url 'groupmanagement:management' %}">{% translate "Back" %}</a>
</li>
<li class="nav-item">
<a class="nav-link {% navactive request 'groupmanagement:management' %}" href="{% url 'groupmanagement:management' %}">{% translate "Back" %}</a>
</li>
{% endblock %}
{% block content %}
{% if group.user_set %}
<div class="table-responsive">
<table class="table table-aa" id="tab_group_members">
<table class="table" id="tab_group_members">
<thead>
<tr>
<th>{% translate "Character" %}</th>
@@ -30,6 +36,7 @@
<tr>
<td>
<img src="{{ member.main_char|character_portrait_url:32 }}" class="rounded-circle" style="margin-right: 1rem;" alt="{{ member.main_char.character_name }}">
{% if member.main_char %}
<a href="{{ member.main_char|evewho_character_url }}" target="_blank">
{{ member.main_char.character_name }}
@@ -39,7 +46,7 @@
{% endif %}
{% if member.is_leader %}
<i class="fa-solid fa-star"> title="{% translate "Group leader" %}" style="margin-left: 1rem;"></i>&nbsp;
<sup><i class="fa-solid fa-star" title="{% translate "Group leader" %}"></i></sup>
{% endif %}
</td>
@@ -53,6 +60,7 @@
{% translate "(unknown)" %}
{% endif %}
</td>
<td class="text-end">
<a href="{% url 'groupmanagement:membership_remove' group.id member.user.id %}" class="btn btn-danger" title="{% translate "Remove from group" %}">
<i class="fa-solid fa-xmark"></i>
@@ -77,24 +85,24 @@
{% block extra_javascript %}
{% include 'bundles/datatables-js-bs5.html' %}
<script>
$(document).ready(() => {
$('#tab_group_members').DataTable({
order: [[0, "asc"]],
columnDefs: [
{
"sortable": false,
"targets": [2]
},
],
"stateSave": true,
"stateDuration": 0
});
});
</script>
{% endblock %}
{% block extra_css %}
{% include 'bundles/datatables-css-bs5.html' %}
{% endblock %}
{% block extra_script %}
$(document).ready(function(){
$('#tab_group_members').DataTable({
order: [[0, "asc"]],
columnDefs: [
{
"sortable": false,
"targets": [2]
},
],
"stateSave": true,
"stateDuration": 0
});
});
{% endblock %}

View File

@@ -9,7 +9,7 @@
{% block extra_css %}{% endblock extra_css %}
{% block header_nav_collapse_left %}
<li class="nav-item ">
<li class="nav-item">
<a class="nav-link {% navactive request 'groupmanagement:management' %}" href="{% url 'groupmanagement:management' %}">{% translate "Join/Leave Requests" %}</a>
</li>
{% endblock header_nav_collapse_left %}
@@ -17,7 +17,7 @@
{% block content %}
{% if groups %}
<div class="table-responsive">
<table class="table table-aa">
<table class="table">
<thead>
<tr>
<th>{% translate "Name" %}</th>
@@ -54,15 +54,15 @@
<td class="text-end">
<a href="{% url 'groupmanagement:membership' group.id %}" class="btn btn-primary" title="{% translate "View Members" %}">
<i class="far fa-eye"></i>
<i class="fa-regular fa-eye"></i>
</a>
<a href="{% url "groupmanagement:audit_log" group.id %}" class="btn btn-info" title="{% translate "Audit Members" %}">
<i class="far fa-list-alt"></i>
<i class="fa-regular fa-rectangle-list"></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="{% translate "Copy Direct Join Link" %}">
<i class="far fa-clipboard"></i>
<i class="fa-regular fa-clipboard"></i>
</a>
</td>
</tr>

View File

@@ -1,21 +1,28 @@
{% extends "allianceauth/base-bs5.html" %}
{% load static %}
{% load i18n %}
{% block page_title %}{% translate "Available Groups" %}{% endblock page_title %}
{% block header_nav_brand %}{% translate "Available Groups" %}{% endblock header_nav_brand %}
{% block page_title %}
{% translate "Available Groups" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "Available Groups" %}
{% endblock header_nav_brand %}
{% if manager_perms %}
{% block header_nav_collapse_left %}
<li class="nav-item">
<a class="nav-link" href="{% url 'groupmanagement:management' %}">{% translate "Group Management" %}
{% if req_count %}
<span class="badge bg-secondary">{{ req_count }}</span>
{% endif %}
</a>
</li>
{% endblock %}
{% block header_nav_collapse_left %}
<li class="nav-item">
<a class="nav-link" href="{% url 'groupmanagement:management' %}">{% translate "Group Management" %}
{% if req_count %}
<span class="badge bg-secondary">{{ req_count }}</span>
{% endif %}
</a>
</li>
{% endblock %}
{% endif %}
{% block content %}
{% if groups %}
<table class="table" id="groupsTable" >
@@ -78,16 +85,17 @@
</div>
{% endif %}
{% endblock content %}
{% block extra_javascript %}
{% include 'bundles/datatables-js-bs5.html' %}
<script>
$(document).ready(() => {
$('#groupsTable').DataTable();
});
</script>
{% endblock %}
{% block extra_css %}
{% include 'bundles/datatables-css-bs5.html' %}
{% endblock %}
{% block extra_script %}
$(document).ready(function () {
$('#groupsTable').DataTable();
});
{% endblock extra_script %}

View File

@@ -1,107 +1,55 @@
{% extends "allianceauth/base-bs5.html" %}
{% load static %}
{% load i18n %}
{% load evelinks %}
{% load navactive %}
{% block page_title %}{% translate "Groups Management" %}{% endblock page_title %}
{% block header_nav_brand %}{% translate "Groups Management" %}{% endblock header_nav_brand %}
{% block page_title %}
{% translate "Groups Management" %}
{% endblock page_title %}
{% block extra_css %}
{% endblock extra_css %}
{% block header_nav_brand %}
{% translate "Groups Management" %}
{% endblock header_nav_brand %}
{% block header_nav_collapse_left %}
<li class="active">
<a class="nav-link active" id="add-tab" data-bs-toggle="tab" data-bs-target="#add" type="button" role="tab" aria-controls="addd" aria-selected="true">
{% translate "Join Requests" %}
<li class="active">
<a class="nav-link active" id="add-tab" data-bs-toggle="tab" data-bs-target="#add" type="button" role="tab" aria-controls="add" aria-selected="true">
{% translate "Join Requests" %}
{% if acceptrequests %}
<span class="badge bg-secondary">{{ acceptrequests|length }}</span>
{% endif %}
</a>
</li>
{% if not auto_leave %}
<li>
<a class="nav-link" id="leave-tab" data-bs-toggle="tab" data-bs-target="#leave" type="button" role="tab" aria-controls="leave" aria-selected="false">
{% translate "Leave Requests" %}
{% if leaverequests %}
<span class="badge bg-secondary">{{ leaverequests|length }}</span>
{% if acceptrequests %}
<span class="badge bg-secondary">{{ acceptrequests|length }}</span>
{% endif %}
</a>
</li>
{% endif %}
<li class="nav-item ">
<a class="nav-link {% navactive request 'groupmanagement:membership groupmanagement:audit_log' %}" href="{% url 'groupmanagement:membership' %}">{% translate "Group Membership" %}</a>
</li>
{% endblock %}
{% if not show_leave_tab %}
<li>
<a class="nav-link" id="leave-tab" data-bs-toggle="tab" data-bs-target="#leave" type="button" role="tab" aria-controls="leave" aria-selected="false">
{% translate "Leave Requests" %}
{% if leaverequests %}
<span class="badge bg-secondary">{{ leaverequests|length }}</span>
{% endif %}
</a>
</li>
{% endif %}
<li class="nav-item ">
<a class="nav-link {% navactive request 'groupmanagement:membership groupmanagement:audit_log' %}" href="{% url 'groupmanagement:membership' %}">
{% translate "Group Membership" %}
</a>
</li>
{% endblock header_nav_collapse_left %}
{% block content %}
<div class="tab-content">
<div id="add" class="tab-pane active">
{% if acceptrequests %}
<div class="table-responsive">
<table class="table table-aa">
<thead>
<tr>
<th>{% translate "Character" %}</th>
<th>{% translate "Organization" %}</th>
<th>{% translate "Group" %}</th>
<th></th>
</tr>
</thead>
<tbody class="align-middle">
{% for acceptrequest in acceptrequests %}
<tr>
<td>
<img src="{{ acceptrequest.main_char|character_portrait_url:32 }}" class="rounded-circle" style="margin-right: 1rem;" alt="{{ acceptrequest.main_char.character_name }}">
{% 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 %}
{% translate "(unknown)" %}
{% endif %}
</td>
<td>{{ acceptrequest.group.name }}</td>
<td class="text-end">
<a href="{% url 'groupmanagement:accept_request' acceptrequest.id %}" class="btn btn-success">
{% translate "Accept" %}
</a>
<a href="{% url 'groupmanagement:reject_request' acceptrequest.id %}" class="btn btn-danger">
{% translate "Reject" %}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="alert alert-warning text-center">{% translate "No group add requests." %}</div>
{% endif %}
</div>
{% if not auto_leave %}
<div id="leave" class="tab-pane">
{% if leaverequests %}
<div class="tab-content">
<div id="add" class="tab-pane active">
{% if acceptrequests %}
<div class="table-responsive">
<table class="table table-aa">
<table class="table">
<thead>
<tr>
<th>{% translate "Character" %}</th>
@@ -112,36 +60,37 @@
</thead>
<tbody class="align-middle">
{% for leaverequest in leaverequests %}
{% for acceptrequest in acceptrequests %}
<tr>
<td>
<img src="{{ leaverequest.main_char|character_portrait_url:32 }}" class="rounded-circle" style="margin-right: 1rem;" alt="{{ leaverequest.main_char.character_name }}">
{% if leaverequest.main_char %}
<a href="{{ leaverequest.main_char|evewho_character_url }}" target="_blank">
{{ leaverequest.main_char.character_name }}
<img src="{{ acceptrequest.main_char|character_portrait_url:32 }}" class="rounded-circle" style="margin-right: 1rem;" alt="{{ acceptrequest.main_char.character_name }}">
{% if acceptrequest.main_char %}
<a href="{{ acceptrequest.main_char|evewho_character_url }}" target="_blank">
{{ acceptrequest.main_char.character_name }}
</a>
{% else %}
{{ leaverequest.user.username }}
{{ acceptrequest.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:"" }}
{% 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 %}
{% translate "(unknown)" %}
{% endif %}
</td>
<td>{{ leaverequest.group.name }}</td>
<td class="text-end">
<a href="{% url 'groupmanagement:leave_accept_request' leaverequest.id %}" class="btn btn-success">
{% translate "Accept" %}
</a>
<a href="{% url 'groupmanagement:leave_reject_request' leaverequest.id %}" class="btn btn-danger">
{% translate "Reject" %}
<td>{{ acceptrequest.group.name }}</td>
<td class="text-end">
<a href="{% url 'groupmanagement:accept_request' acceptrequest.id %}" class="btn btn-success">
{% translate "Accept" %}
</a>
</td>
</tr>
@@ -150,9 +99,73 @@
</table>
</div>
{% else %}
<div class="alert alert-warning text-center">{% translate "No group leave requests." %}</div>
<div class="aa-callout aa-callout-warning text-center">
{% translate "No group add requests." %}
</div>
{% endif %}
</div>
{% endif %}
</div>
{% if not show_leave_tab %}
<div id="leave" class="tab-pane">
{% if leaverequests %}
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>{% translate "Character" %}</th>
<th>{% translate "Organization" %}</th>
<th>{% translate "Group" %}</th>
<th></th>
</tr>
</thead>
<tbody class="align-middle">
{% for leaverequest in leaverequests %}
<tr>
<td>
<img src="{{ leaverequest.main_char|character_portrait_url:32 }}" class="rounded-circle" style="margin-right: 1rem;" alt="{{ leaverequest.main_char.character_name }}">
{% 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 %}
{% translate "(unknown)" %}
{% endif %}
</td>
<td>{{ leaverequest.group.name }}</td>
<td class="text-end">
<a href="{% url 'groupmanagement:leave_accept_request' leaverequest.id %}" class="btn btn-success">
{% translate "Accept" %}
</a>
<a href="{% url 'groupmanagement:leave_reject_request' leaverequest.id %}" class="btn btn-danger">
{% translate "Reject" %}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="aa-callout aa-callout-warning text-center">{% translate "No group leave requests." %}</div>
{% endif %}
</div>
{% endif %}
</div>
{% endblock content %}

View File

@@ -6,22 +6,22 @@ from django.conf import settings
from django.contrib import admin
from django.contrib.admin.sites import AdminSite
from django.contrib.auth.models import User
from django.test import TestCase, RequestFactory, Client, override_settings
from django.test import Client, RequestFactory, TestCase, override_settings
from allianceauth.authentication.models import CharacterOwnership, State
from allianceauth.eveonline.models import (
EveCharacter, EveCorporationInfo, EveAllianceInfo
EveAllianceInfo, EveCharacter, EveCorporationInfo,
)
from allianceauth.tests.auth_utils import AuthUtils
from . import get_admin_change_view_url
from ..admin import HasLeaderFilter, GroupAdmin, Group
from ..admin import Group, GroupAdmin, HasLeaderFilter
from ..models import ReservedGroupName
from . import get_admin_change_view_url
if 'allianceauth.eveonline.autogroups' in settings.INSTALLED_APPS:
_has_auto_groups = True
from allianceauth.eveonline.autogroups.models import AutogroupsConfig
from ..admin import IsAutoGroupFilter
else:
_has_auto_groups = False
@@ -621,21 +621,16 @@ class TestGroupAdmin2(TestCase):
response = self.client.post(
f"/admin/groupmanagement/group/{group.pk}/change/",
data={
"name": f"{group.name}",
"authgroup-TOTAL_FORMS": "1",
"authgroup-INITIAL_FORMS": "1",
"authgroup-MIN_NUM_FORMS": "0",
"authgroup-MAX_NUM_FORMS": "1",
"authgroup-0-description": "",
"authgroup-0-states": f"{member_state.pk}",
"name": group.name,
"users": [user_member.pk, user_guest.pk],
"authgroup-TOTAL_FORMS": 1,
"authgroup-INITIAL_FORMS": 1,
"authgroup-MIN_NUM_FORMS": 0,
"authgroup-MAX_NUM_FORMS": 1,
"authgroup-0-states": member_state.pk,
"authgroup-0-internal": "on",
"authgroup-0-hidden": "on",
"authgroup-0-group": f"{group.pk}",
"authgroup-__prefix__-description": "",
"authgroup-__prefix__-internal": "on",
"authgroup-__prefix__-hidden": "on",
"authgroup-__prefix__-group": f"{group.pk}",
"_save": "Save"
"authgroup-0-group": group.pk,
}
)
# then
@@ -644,6 +639,85 @@ class TestGroupAdmin2(TestCase):
self.assertIn(group, user_member.groups.all())
self.assertNotIn(group, user_guest.groups.all())
def test_should_add_user_to_existing_group(self):
# given
user_bruce = AuthUtils.create_user("Bruce Wayne")
user_lex = AuthUtils.create_user("Lex Luthor")
group = Group.objects.create(name="dummy")
user_bruce.groups.add(group)
self.client.force_login(self.superuser)
# when
response = self.client.post(
f"/admin/groupmanagement/group/{group.pk}/change/",
data={
"name": group.name,
"users": [user_bruce.pk, user_lex.pk],
"authgroup-TOTAL_FORMS": 1,
"authgroup-INITIAL_FORMS": 1,
"authgroup-MIN_NUM_FORMS": 0,
"authgroup-MAX_NUM_FORMS": 1,
"authgroup-0-internal": "on",
"authgroup-0-hidden": "on",
"authgroup-0-group": group.pk,
}
)
# then
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, "/admin/groupmanagement/group/")
self.assertIn(group, user_bruce.groups.all())
self.assertIn(group, user_lex.groups.all())
def test_should_remove_user_from_existing_group(self):
# given
user_bruce = AuthUtils.create_user("Bruce Wayne")
user_lex = AuthUtils.create_user("Lex Luthor")
group = Group.objects.create(name="dummy")
user_bruce.groups.add(group)
user_lex.groups.add(group)
self.client.force_login(self.superuser)
# when
response = self.client.post(
f"/admin/groupmanagement/group/{group.pk}/change/",
data={
"name": group.name,
"users": user_bruce.pk,
"authgroup-TOTAL_FORMS": 1,
"authgroup-INITIAL_FORMS": 1,
"authgroup-MIN_NUM_FORMS": 0,
"authgroup-MAX_NUM_FORMS": 1,
"authgroup-0-internal": "on",
"authgroup-0-hidden": "on",
"authgroup-0-group": group.pk,
}
)
# then
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, "/admin/groupmanagement/group/")
self.assertIn(group, user_bruce.groups.all())
self.assertNotIn(group, user_lex.groups.all())
def test_should_include_user_when_creating_group(self):
# given
user_bruce = AuthUtils.create_user("Bruce Wayne")
self.client.force_login(self.superuser)
# when
response = self.client.post(
"/admin/groupmanagement/group/add/",
data={
"name": "new group",
"users": user_bruce.pk,
"authgroup-TOTAL_FORMS": 1,
"authgroup-INITIAL_FORMS": 0,
"authgroup-MIN_NUM_FORMS": 0,
"authgroup-MAX_NUM_FORMS": 1,
}
)
# then
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, "/admin/groupmanagement/group/")
group = Group.objects.get(name="new group")
self.assertIn(group, user_bruce.groups.all())
class TestReservedGroupNameAdmin(TestCase):
@classmethod

View File

@@ -1,6 +1,7 @@
from django.test import RequestFactory, TestCase, override_settings
from django.urls import reverse
from allianceauth.groupmanagement.models import Group, GroupRequest
from allianceauth.tests.auth_utils import AuthUtils
from .. import views
@@ -16,6 +17,7 @@ class TestViews(TestCase):
self.factory = RequestFactory()
self.user = AuthUtils.create_user('Peter Parker')
self.user_with_manage_permission = AuthUtils.create_user('Bruce Wayne')
self.group = Group.objects.create(name="Example group")
# set permissions
AuthUtils.add_permission_to_user_by_name(
@@ -83,3 +85,19 @@ class TestViews(TestCase):
self.assertEqual(response.status_code, 200)
self.assertNotIn('id="leave-tab" data-bs-toggle="tab" data-bs-target="#leave"', content)
self.assertNotIn('<div id="leave" class="tab-pane">', content)
@override_settings(GROUPMANAGEMENT_AUTO_LEAVE=True)
def test_should_not_hide_leave_requests_tab_when_there_are_open_requests(self):
# given
request = self.factory.get(reverse('groupmanagement:management'))
request.user = self.user_with_manage_permission
GroupRequest.objects.create(user=self.user, group=self.group, leave_request=True)
# when
response = views.group_management(request)
# then
content = response_content_to_str(response)
self.assertEqual(response.status_code, 200)
self.assertIn('<a class="nav-link" id="leave-tab" data-bs-toggle="tab" data-bs-target="#leave"', content)
self.assertIn('<div id="leave" class="tab-pane">', content)

View File

@@ -2,13 +2,12 @@ import logging
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test
from django.contrib.auth.decorators import login_required, user_passes_test
from django.contrib.auth.models import Group
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.db.models import Count
from django.http import Http404
from django.shortcuts import render, redirect, get_object_or_404
from django.shortcuts import get_object_or_404, redirect, render
from django.utils.translation import gettext_lazy as _
from allianceauth.notifications import notify
@@ -16,7 +15,6 @@ from allianceauth.notifications import notify
from .managers import GroupManager
from .models import GroupRequest, RequestLog
logger = logging.getLogger(__name__)
@@ -45,10 +43,15 @@ def group_management(request):
logger.debug("Providing user {} with {} acceptrequests and {} leaverequests.".format(
request.user, len(acceptrequests), len(leaverequests)))
show_leave_tab = (
getattr(settings, 'GROUPMANAGEMENT_AUTO_LEAVE', False)
and not GroupRequest.objects.filter(leave_request=True).exists()
)
render_items = {
'acceptrequests': acceptrequests,
'leaverequests': leaverequests,
'auto_leave': getattr(settings, 'GROUPMANAGEMENT_AUTO_LEAVE', False),
'show_leave_tab': show_leave_tab,
}
return render(request, 'groupmanagement/index.html', context=render_items)

View File

@@ -13,7 +13,7 @@ class ChoiceInline(admin.TabularInline):
@admin.register(ApplicationQuestion)
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['title', 'help_text', 'multi_select']}),
(None, {'fields': ['title', 'help_text', 'multi_select']}),
]
inlines = [ChoiceInline]

View File

@@ -13,7 +13,7 @@ class ApplicationsMenu(MenuItemHook):
MenuItemHook.__init__(
self,
_('Applications'),
'far fa-file fa-fw',
'fa-regular fa-file',
'hrapplications:index',
navactive=['hrapplications:'])

View File

@@ -1,22 +1,37 @@
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}{% translate "Choose a Corp" %}{% endblock page_title %}
{% block page_title %}
{% translate "Choose a Corp" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "HR Application Management" %}
{% endblock header_nav_brand %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "Choose a Corp" %}</h1>
<div>
{% translate "Choose a Corp" as page_header %}
{% include "framework/header/page-header.html" with title=page_header %}
{% if choices %}
<div class="panel panel-primary">
<div class="panel-heading">{% translate "Available Corps" %}</div>
<table class="table table-responsive">
{% for choice in choices %}
<tr>
<td class="text-center">
<a href="{% url 'hrapplications:create_view' choice.0 %}" class="btn btn-primary" title="Apply">{{ choice.1 }}</a>
</td>
</tr>
{% endfor %}
</table>
<div class="card card-primary">
<div class="card-header">
<div class="card-title mb-0">{% translate "Available Corps" %}</div>
</div>
<div class="card-body">
<table class="table table-responsive">
{% for choice in choices %}
<tr>
<td class="text-center">
<a href="{% url 'hrapplications:create_view' choice.0 %}" class="btn btn-primary" title="Apply">{{ choice.1 }}</a>
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% else %}
<div class="alert alert-danger">{% translate "No corps are accepting applications at this time." %}</div>

View File

@@ -1,35 +1,66 @@
{% extends "allianceauth/base-bs5.html" %}
{% load django_bootstrap5 %}
{% load i18n %}
{% block page_title %}{% translate "Apply To" %} {{ corp.corporation_name }}{% endblock page_title %}
{% block page_title %}
{% translate "Apply To" %} {{ corp.corporation_name }}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "HR Application Management" %}
{% endblock header_nav_brand %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "Apply To" %} {{ corp.corporation_name }}</h1>
<div class="container-fluid">
<div class="col-md-4 col-md-offset-4">
<div class="row">
<form class="form-signin">
{% csrf_token %}
{% for question in questions %}
<div class="form-group">
<label class="control-label" for="id_{{ question.pk }}">{{ question.title }}</label>
<div class=" ">
{% if question.help_text %}
<div class="text-center">{{ question.help_text }}</div>
{% endif %}
{% for choice in question.choices.all %}
<input type={% if question.multi_select == False %}"radio"{% else %}"checkbox"{% endif %} name="{{ question.pk }}" id="id_{{ question.pk }}_choice_{{ forloop.counter }}" value="{{ choice.choice_text }}">
<label for="id_{{ question.pk }}_choice_{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% empty %}
<textarea class="form-control" cols="30" id="id_{{ question.pk }}" name="{{ question.pk }}" rows="4"></textarea>
<div>
<h1 class="page-header text-center mb-3">
{% translate "Apply To" %} {{ corp.corporation_name }}
</h1>
<div class="card">
<div class="card-header">
<div class="card-title mb-0">
{% translate "Application form" %}
</div>
</div>
<div class="card-body">
<div class="row justify-content-center">
<div class="col-md-8">
<form method="post">
{% csrf_token %}
{% for question in questions %}
<div class="card mb-3 form-group border-0">
<div class="card-header">
<div class="card-title mb-0">{{ question.title }}</div>
</div>
<div class="card-body">
{% if question.help_text %}
<p class="text-muted">
{{ question.help_text }}
</p>
{% endif %}
{% for choice in question.choices.all %}
<input type="{% if question.multi_select == False %}radio{% else %}checkbox{% endif %}" name="{{ question.pk }}" id="id_{{ question.pk }}_choice_{{ forloop.counter }}" value="{{ choice.choice_text }}">
<label for="id_{{ question.pk }}_choice_{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% empty %}
<textarea class="form-control" cols="30" id="id_{{ question.pk }}" name="{{ question.pk }}" rows="10"></textarea>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
<div class="form-group clearfix">
{% translate "Submit" as button_text %}
{% bootstrap_button button_class="btn btn-primary" content=button_text name="submitApplicationForm" id="submitApplicationForm" %}
</div>
</form>
</div>
{% endfor %}
<button class="btn btn-lg btn-primary btn-block" type="submit" formmethod="post">{% translate "Submit" %}</button>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -1,193 +1,215 @@
{% extends "allianceauth/base.html" %}
{% load bootstrap %}
{% extends "allianceauth/base-bs5.html" %}
{% load django_bootstrap5 %}
{% load i18n %}
{% block page_title %}{% translate "HR Application Management" %}{% endblock page_title %}
{% block extra_css %}{% endblock extra_css %}
{% block page_title %}
{% translate "HR Application Management" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "HR Application Management" %}
{% endblock header_nav_brand %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "Personal Applications" %}
<div class="text-end">
{% if create %}
<a href="{% url 'hrapplications:create_view' %}">
<button type="button" class="btn btn-success">{% translate "Create Application" %}</button>
</a>
{% else %}
<button type="button" class="btn btn-success" disabled>{% translate "Create Application" %}</button>
{% endif %}
</div>
</h1>
{% if personal_apps %}
<div class="panel panel-default">
<table class="table table-condensed">
<tr>
<th class="text-center">{% translate "Username" %}</th>
<th class="text-center">{% translate "Corporation" %}
<th class="text-center">{% translate "Status" %}</th>
<th class="text-center">{% translate "Actions" %}</th>
</tr>
{% for personal_app in personal_apps %}
<tr>
<td class="text-center">{{ personal_app.user.username }}</td>
<td class="text-center">{{ personal_app.form.corp.corporation_name }}</td>
<td class="text-center">
{% if personal_app.approved == None %}
<div class="badge bg-warning">{% translate "Pending" %}</div>
{% elif personal_app.approved == True %}
<div class="badge bg-success">{% translate "Approved" %}</div>
{% else %}
<div class="badge bg-danger">{% translate "Rejected" %}</div>
{% endif %}
</td>
<td class="text-center">
<a href="{% url 'hrapplications:personal_view' personal_app.id %}" class="btn btn-primary">
<span class="glyphicon glyphicon-eye-open"></span>
</a>
<div>
{% translate "Personal Applications" as page_header %}
{% include "framework/header/page-header.html" with title=page_header %}
{% if personal_app.approved == None %}
<a href="{% url 'hrapplications:personal_removal' personal_app.id %}" class="btn btn-danger">
<span class="glyphicon glyphicon-remove"></span>
</a>
{% endif %}
</td>
<div class="text-end mb-3">
{% if create %}
<a href="{% url 'hrapplications:create_view' %}">
<button type="button" class="btn btn-success">{% translate "Create Application" %}</button>
</a>
{% else %}
<button type="button" class="btn btn-success" disabled>{% translate "Create Application" %}</button>
{% endif %}
</div>
{% if personal_apps %}
<div class="card card-default mb-3">
<div class="card-body">
<table class="table table-condensed">
<tr>
<th class="text-center">{% translate "Username" %}</th>
<th class="text-center">{% translate "Corporation" %}
<th class="text-center">{% translate "Status" %}</th>
<th class="text-center">{% translate "Actions" %}</th>
</tr>
{% endfor %}
</table>
{% for personal_app in personal_apps %}
<tr>
<td class="text-center">{{ personal_app.user.username }}</td>
<td class="text-center">{{ personal_app.form.corp.corporation_name }}</td>
<td class="text-center">
{% if personal_app.approved == None %}
<div class="badge bg-warning">{% translate "Pending" %}</div>
{% elif personal_app.approved == True %}
<div class="badge bg-success">{% translate "Approved" %}</div>
{% else %}
<div class="badge bg-danger">{% translate "Rejected" %}</div>
{% endif %}
</td>
<td class="text-center">
<a href="{% url 'hrapplications:personal_view' personal_app.id %}" class="btn btn-primary">
<i class="fa-solid fa-eye"></i>
</a>
{% if personal_app.approved == None %}
<a href="{% url 'hrapplications:personal_removal' personal_app.id %}" class="btn btn-danger">
<i class="fa-solid fa-trash-can"></i>
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endif %}
{% if perms.auth.human_resources %}
<h1 class="page-header text-center">{% translate "Application Management" %}
<div class="text-end">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#myModal">
{% translate "Search Applications" %}
</button>
</div>
</h1>
<ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" href="#pending">{% translate "Pending" %}</a></li>
<li><a data-toggle="tab" href="#reviewed">{% translate "Reviewed" %}</a></li>
</ul>
<div class="tab-content">
<div id="pending" class="tab-pane fade in active panel panel-default">
<div class="panel-body">
{% if applications %}
<table class="table">
<tr>
<th class="text-center">{% translate "Date" %}</th>
<th class="text-center">{% translate "Username" %}</th>
<th class="text-center">{% translate "Main Character" %}</th>
<th class="text-center">{% translate "Corporation" %}</th>
<th class="text-center">{% translate "Status" %}</th>
<th class="text-center">{% translate "Actions" %}</th>
</tr>
{% for app in applications %}
{% translate "Application Management" as page_header %}
{% include "framework/header/page-header.html" with title=page_header %}
<div class="text-end mb-3">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#modal-hr-search">
{% translate "Search Applications" %}
</button>
</div>
<div class="card card-default">
<div class="card-body clearfix">
<ul class="nav nav-tabs" id="application-list" role="tablist">
<li class="nav-item" role="presentation">
<a
class="nav-link active"
id="pending"
data-bs-toggle="tab"
href="#tab-pending"
role="tab"
aria-controls="tab-pending"
aria-selected="true"
>
{% translate "Pending" %}
</a>
</li>
<li class="nav-item" role="presentation">
<a
class="nav-link"
id="reviewed"
data-bs-toggle="tab"
href="#tab-reviewed"
role="tab"
aria-controls="tab-reviewed"
aria-selected="false"
>
{% translate "Reviewed" %}
</a>
</li>
</ul>
<div class="tab-content" id="application-list-content">
<div id="tab-pending" class="tab-pane fade show active" role="tabpanel" aria-labelledby="tab-pending">
{% if applications %}
<table class="table">
<tr>
<td class="text-center">{{ app.created }}</td>
<td class="text-center">{{ app.user.username }}</td>
<td class="text-center">{{ app.main_character }}</td>
<td class="text-center">{{ app.form.corp.corporation_name }}</td>
<td class="text-center">
{% if app.approved == None %}
{% if app.reviewer_str %}
<div class="badge bg-info">{% translate "Reviewer:" %} {{ app.reviewer_str }}</div>
{% else %}
<div class="badge bg-warning">{% translate "Pending" %}</div>
{% endif %}
{% elif app.approved == True %}
<div class="badge bg-success">{% translate "Approved" %}</div>
{% else %}
<div class="badge bg-danger">{% translate "Rejected" %}</div>
{% endif %}
</td>
<td class="text-center">
<a href="{% url 'hrapplications:view' app.id %}" class="btn btn-primary">
<span class="glyphicon glyphicon-eye-open"></span>
</a>
</td>
<th class="text-center">{% translate "Date" %}</th>
<th class="text-center">{% translate "Username" %}</th>
<th class="text-center">{% translate "Main Character" %}</th>
<th class="text-center">{% translate "Corporation" %}</th>
<th class="text-center">{% translate "Status" %}</th>
<th class="text-center">{% translate "Actions" %}</th>
</tr>
{% endfor %}
</table>
{% else %}
<div class="alert alert-warning text-center">{% translate "No pending applications." %}</div>
{% endif %}
</div>
</div>
<div id="reviewed" class="tab-pane fade panel panel-default">
<div class="panel-body">
{% if finished_applications %}
<table class="table">
<tr>
<th class="text-center">{% translate "Date" %}</th>
<th class="text-center">{% translate "Username" %}</th>
<th class="text-center">{% translate "Main Character" %}</th>
<th class="text-center">{% translate "Corporation" %}</th>
<th class="text-center">{% translate "Status" %}</th>
<th class="text-center">{% translate "Actions" %}</th>
</tr>
{% for app in finished_applications %}
<tr>
<td class="text-center">{{ app.created }}</td>
<td class="text-center">{{ app.user.username }}</td>
<td class="text-center">{{ app.main_character }}</td>
<td class="text-center">{{ app.form.corp.corporation_name }}</td>
<td class="text-center">
{% if app.approved == None %}
{% if app.reviewer_str %}
<div class="badge bg-info">{% translate "Reviewer:" %} {{ app.reviewer_str }}</div>
{% for app in applications %}
<tr>
<td class="text-center">{{ app.created }}</td>
<td class="text-center">{{ app.user.username }}</td>
<td class="text-center">{{ app.main_character }}</td>
<td class="text-center">{{ app.form.corp.corporation_name }}</td>
<td class="text-center">
{% if app.approved == None %}
{% if app.reviewer_str %}
<div class="badge bg-info">{% translate "Reviewer:" %} {{ app.reviewer_str }}</div>
{% else %}
<div class="badge bg-warning">{% translate "Pending" %}</div>
{% endif %}
{% elif app.approved == True %}
<div class="badge bg-success">{% translate "Approved" %}</div>
{% else %}
<div class="badge bg-warning">{% translate "Pending" %}</div>
<div class="badge bg-danger">{% translate "Rejected" %}</div>
{% endif %}
{% elif app.approved == True %}
<div class="badge bg-success">{% translate "Approved" %}</div>
{% else %}
<div class="badge bg-danger">{% translate "Rejected" %}</div>
{% endif %}
</td>
<td class="text-center">
<a href="{% url 'hrapplications:view' app.id %}" class="btn btn-primary">
<span class="glyphicon glyphicon-eye-open"></span>
</a>
{% if perms.hrapplications.delete_application %}
<a href="{% url 'hrapplications:remove' app.id %}" class="btn btn-danger">
<span class="glyphicon glyphicon-remove"></span>
</td>
<td class="text-center">
<a href="{% url 'hrapplications:view' app.id %}" class="btn btn-primary">
<i class="fa-solid fa-eye"></i>
</a>
{% endif %}
</td>
</td>
</tr>
{% endfor %}
</table>
{% else %}
<div class="alert alert-warning text-center">{% translate "No pending applications." %}</div>
{% endif %}
</div>
<div id="tab-reviewed" class="tab-pane fade" role="tabpanel" aria-labelledby="tab-reviewed">
{% if finished_applications %}
<table class="table">
<tr>
<th class="text-center">{% translate "Date" %}</th>
<th class="text-center">{% translate "Username" %}</th>
<th class="text-center">{% translate "Main Character" %}</th>
<th class="text-center">{% translate "Corporation" %}</th>
<th class="text-center">{% translate "Status" %}</th>
<th class="text-center">{% translate "Actions" %}</th>
</tr>
{% endfor %}
</table>
{% else %}
<div class="alert alert-warning text-center">{% translate "No reviewed applications." %}</div>
{% endif %}
{% for app in finished_applications %}
<tr>
<td class="text-center">{{ app.created }}</td>
<td class="text-center">{{ app.user.username }}</td>
<td class="text-center">{{ app.main_character }}</td>
<td class="text-center">{{ app.form.corp.corporation_name }}</td>
<td class="text-center">
{% if app.approved == None %}
{% if app.reviewer_str %}
<div class="badge bg-info">{% translate "Reviewer:" %} {{ app.reviewer_str }}</div>
{% else %}
<div class="badge bg-warning">{% translate "Pending" %}</div>
{% endif %}
{% elif app.approved == True %}
<div class="badge bg-success">{% translate "Approved" %}</div>
{% else %}
<div class="badge bg-danger">{% translate "Rejected" %}</div>
{% endif %}
</td>
<td class="text-center">
<a href="{% url 'hrapplications:view' app.id %}" class="btn btn-primary">
<i class="fa-solid fa-eye"></i>
</a>
{% if perms.hrapplications.delete_application %}
<a href="{% url 'hrapplications:remove' app.id %}" class="btn btn-danger">
<i class="fa-solid fa-trash-can"></i>
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
{% else %}
<div class="alert alert-warning text-center">{% translate "No reviewed applications." %}</div>
{% endif %}
</div>
</div>
</div>
</div>
{% endif %}
</div>
{% if perms.auth.human_resources %}
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">{% translate "Close" %}</span></button>
<h4 class="modal-title" id="myModalLabel">{% translate "Application Search" %}</h4>
</div>
<div class="modal-body">
<form class="form-signin" role="form" action="{% url 'hrapplications:search' %}" method="POST">
{% csrf_token %}
{{ search_form|bootstrap }}
<br>
<button class="btn btn-lg btn-primary btn-block" type="submit">{% translate "Search" %}</button>
</form>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
{% endif %}
{% include "hrapplications/partials/modals/search.html" %}
{% endblock content %}

View File

@@ -0,0 +1,32 @@
{% load django_bootstrap5 %}
{% load i18n %}
{% if perms.auth.human_resources %}
<!-- Modal -->
<div class="modal fade" id="modal-hr-search" tabindex="-1" aria-labelledby="modalHrSearch" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<div class="modal-title fs-5" id="modalHrSearchLabel">
{% translate "Application Search" %}
</div>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{% translate 'Close' %}"></button>
</div>
<div class="modal-body">
<form class="form-signin" role="form" action="{% url 'hrapplications:search' %}" method="POST">
{% csrf_token %}
{% bootstrap_form search_form %}
<div class="form-group mt-3 clearfix">
{% translate "Search" as button_text %}
{% bootstrap_button button_class="btn btn-primary" content=button_text name="search" id="search" %}
</div>
</form>
</div>
</div>
</div>
</div>
{% endif %}

View File

@@ -1,49 +1,58 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load bootstrap %}
{% load i18n %}
{% block page_title %}{% translate "HR Application Management" %}{% endblock page_title %}
{% block extra_css %}{% endblock extra_css %}
{% block page_title %}
{% translate "HR Application Management" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "HR Application Management" %}
{% endblock header_nav_brand %}
{% block content %}
<div class="col-lg-12">
<div>
{% if perms.auth.human_resources %}
<h1 class="page-header text-center">{% translate "Application Search Results" %}
<div class="text-end">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#myModal">
{% translate "Search Applications" %}
</button>
</div>
</h1>
<div class="container-fluid">
<table class="table table-bordered">
{% translate "Application Search Results" as page_header %}
{% include "framework/header/page-header.html" with title=page_header %}
<div class="text-end mb-3">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#modal-hr-search">
{% translate "Search Applications" %}
</button>
</div>
<div>
<table class="table">
<tr>
<th class="text-center">{% translate "Application ID" %}</th>
<th class="text-center">{% translate "Username" %}</th>
<th class="text-center">{% translate "Main Character" %}</th>
<th class="text-center">{% translate "Corporation" %}</th>
<th>{% translate "Application ID" %}</th>
<th>{% translate "Username" %}</th>
<th>{% translate "Main Character" %}</th>
<th>{% translate "Corporation" %}</th>
<th class="text-center">{% translate "Status" %}</th>
<th class="text-center">{% translate "Actions" %}</th>
<th class="text-end">{% translate "Actions" %}</th>
</tr>
{% for app in applications %}
<tr>
<td class="text-center">{{ app.id }}</td>
<td class="text-center">{{ app.user }}</td>
<td class="text-center">{{ app.main_character }}</td>
<td class="text-center">{{ app.form.corp }}</td>
<td>{{ app.id }}</td>
<td>{{ app.user }}</td>
<td >{{ app.main_character }}</td>
<td>{{ app.form.corp }}</td>
<td class="text-center">
{% if app.approved == None %}
<div class="badge bg-warning">{% translate "Pending" %}</div>
{% elif app.approved == True %}
{% elif app.approved == True %}
<div class="badge bg-success">{% translate "Approved" %}</div>
{% else %}
<div class="badge bg-danger">{% translate "Rejected" %}</div>
{% endif %}
</td>
<td class="text-center">
<td class="text-end">
<a href="{% url 'hrapplications:view' app.id %}" class="btn btn-primary">
<span class="glyphicon glyphicon-eye-open"></span>
<i class="fa-solid fa-eye"></i>
</a>
</td>
</tr>
@@ -53,27 +62,5 @@
{% endif %}
</div>
{% if perms.auth.human_resources %}
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">{% translate "Close" %}</span></button>
<h4 class="modal-title" id="myModalLabel">{% translate "Application Search" %}</h4>
</div>
<div class="modal-body">
<form class="form-signin" role="form" action="{% url 'hrapplications:search' %}" method="POST">
{% csrf_token %}
{{ search_form|bootstrap }}
<br>
<button class="btn btn-lg btn-primary btn-block" type="submit">{% translate "Search" %}</button>
</form>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
{% endif %}
{% include "hrapplications/partials/modals/search.html" %}
{% endblock content %}

View File

@@ -1,149 +1,179 @@
{% extends "allianceauth/base.html" %}
{% load bootstrap %}
{% extends "allianceauth/base-bs5.html" %}
{% load django_bootstrap5 %}
{% load i18n %}
{% block page_title %}{% translate "View Application" %}{% endblock page_title %}
{% block extra_css %}{% endblock extra_css %}
{% block page_title %}
{% translate "View Application" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "HR Application Management" %}
{% endblock header_nav_brand %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "View Application" %}</h1>
<div class="container-fluid">
<div class="col-md-6 col-md-offset-3">
<div class="row">
{% if app.approved %}
<div class="alert alert-success text-center">{% translate "Approved" %}</div>
{% elif app.approved == False %}
<div class="alert alert-danger text-center">{% translate "Denied" %}</div>
{% else %}
<div class="alert alert-warning text-center">{% translate "Pending" %}</div>
{% endif %}
{% if app.reviewer_str %}
<div class="alert alert-info text-center">{% translate "Reviewer:" %} {{ app.reviewer_str }}</div>
{% endif %}
</div>
<div class="row">
<div class="panel panel-info">
<div class="panel-heading">{% translate "Applicant" %}</div>
<table class="table">
<tr>
<th class="text-center">{% translate "User" %}</th>
<th class="text-center">{% translate "Main Character" %}</th>
</tr>
<tr>
<td class="text-center">{{ app.user }}</td>
<td class="text-center">{{ app.main_character }}</td>
</tr>
</table>
</div>
<div class="panel panel-info">
<div class="panel-heading">{% translate "Characters" %}</div>
<table class="table">
<tr>
<th class="text-center"></th>
<th class="text-center">{% translate "Name" %}</th>
<th class="text-center">{% translate "Corp" %}</th>
<th class="text-center">{% translate "Alliance" %}</th>
</tr>
{% for char in app.characters %}
<tr>
<td class="text-center">
<img class="ra-avatar img-responsive img-circle" src="{{ char.portrait_url_32 }}" alt="{{ char.character_name }}">
</td>
<td class="text-center">{{ char.character_name }}</td>
<td class="text-center">{{ char.corporation_name }}</td>
<td class="text-center">{{ char.alliance_name }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
<div class="row">
{% for response in responses %}
<div class="panel panel-default">
<div class="panel-heading">{{ response.question.title }}</div>
<div class="alert">{{ response.answer|linebreaksbr }}</div>
</div>
{% endfor %}
</div>
{% if buttons %}
{% if perms.auth.human_resources %}
<div class="row">
<div class="panel panel-primary">
<div class="panel-heading">{% translate "Actions" %}</div>
<div class="panel-body text-center">
{% if app.approved == None %}
{% if app.reviewer == user %}
{% if perms.hrapplications.approve_application %}
<a href="{% url 'hrapplications:approve' app.id %}" class="btn btn-success">{% translate "Approve" %}</a>
{% endif %}
{% if perms.hrapplications.reject_application %}
<a href="{% url 'hrapplications:reject' app.id %}" class="btn btn-danger">{% translate "Reject" %}</a>
{% endif %}
{% if perms.hrapplications.delete_application %}
<a href="{% url 'hrapplications:remove' app.id %}" class="btn btn-danger">{% translate "Delete" %}</a>
{% endif %}
{% elif not app.reviewer %}
<a href="{% url 'hrapplications:mark_in_progress' app.id %}" class="btn btn-warning">{% translate "Mark in Progress" %}</a>
{% endif %}
{% endif %}
{% if perms.hrapplications.add_applicationcomment %}
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal">{% translate "Comment" %}</button>
{% endif %}
</div>
</div>
</div>
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingThree">
<h4 class="panel-title">
<a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
{% translate 'Comments' %} ({{ comments.count }})
</a>
</h4>
</div>
<div id="collapseThree" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingThree">
<div class="panel-body">
{% for comment in comments %}
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="">
<div class="panel-title">
<div class="pull-right">{{ comment.created }}</div>
<div class="pull-left">{% if comment.user.profile.main_character %}{{ comment.user.profile.main_character }}{% else %}{{ comment.user }}{% endif %}</div>
<div class="clearfix"></div>
</div>
</div>
<div class="panel-body">{{ comment.text|linebreaks }}</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
{% endif %}
{% endif %}
<div>
{% translate "View Application" as page_header %}
{% include "framework/header/page-header.html" with title=page_header %}
<div>
{% if app.approved %}
<div class="alert alert-success text-center">{% translate "Approved" %}</div>
{% elif app.approved == False %}
<div class="alert alert-danger text-center">{% translate "Denied" %}</div>
{% else %}
<div class="alert alert-warning text-center">{% translate "Pending" %}</div>
{% endif %}
{% if app.reviewer_str %}
<div class="alert alert-info text-center">{% translate "Reviewer:" %} {{ app.reviewer_str }}</div>
{% endif %}
</div>
<div class="card mb-3">
<div class="card-header bg-info">
<div class="card-title mb-0">{% translate "Applicant" %}</div>
</div>
<div class="card-body">
<table class="table">
<tr>
<th class="text-center">{% translate "User" %}</th>
<th class="text-center">{% translate "Main Character" %}</th>
</tr>
<tr>
<td class="text-center">{{ app.user }}</td>
<td class="text-center">{{ app.main_character }}</td>
</tr>
</table>
</div>
</div>
<div class="card mb-3">
<div class="card-header bg-info">
<div class="card-title mb-0">{% translate "Characters" %}</div>
</div>
<div class="card-body">
<table class="table">
<tr>
<th></th>
<th>{% translate "Name" %}</th>
<th>{% translate "Corporation" %}</th>
<th>{% translate "Alliance" %}</th>
</tr>
{% for char in app.characters %}
<tr>
<td>
<img class="ra-avatar img-responsive rounded-circle" src="{{ char.portrait_url_32 }}" alt="{{ char.character_name }}">
</td>
<td>{{ char.character_name }}</td>
<td>{{ char.corporation_name }}</td>
<td>{{ char.alliance_name }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% for response in responses %}
<div class="card mb-3">
<div class="card-header">
<div class="card-title mb-0">{{ response.question.title }}</div>
</div>
<div class="card-body">{{ response.answer|linebreaksbr }}</div>
</div>
{% endfor %}
{% if buttons %}
{% if perms.auth.human_resources %}
<div class="card mb-3">
<div class="card-header">
<div class="card-title mb-0">{% translate "Actions" %}</div>
</div>
<div class="card-body text-center">
{% if app.approved == None %}
{% if app.reviewer == user %}
{% if perms.hrapplications.approve_application %}
<a href="{% url 'hrapplications:approve' app.id %}" class="btn btn-success">{% translate "Approve" %}</a>
{% endif %}
{% if perms.hrapplications.reject_application %}
<a href="{% url 'hrapplications:reject' app.id %}" class="btn btn-warning">{% translate "Reject" %}</a>
{% endif %}
{% if perms.hrapplications.delete_application %}
<a href="{% url 'hrapplications:remove' app.id %}" class="btn btn-danger">{% translate "Delete" %}</a>
{% endif %}
{% elif not app.reviewer %}
<a href="{% url 'hrapplications:mark_in_progress' app.id %}" class="btn btn-warning">{% translate "Mark in Progress" %}</a>
{% endif %}
{% endif %}
{% if perms.hrapplications.add_applicationcomment %}
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modal-hr-comment">{% translate "Comment" %}</button>
{% endif %}
</div>
</div>
<div class="card-group" id="accordion" role="tablist" aria-multiselectable="true">
<div class="card card-default">
<div class="card-header">
<div class="card-title mb-0">
{% translate 'Comments' %} ({{ comments.count }})
</div>
</div>
<div class="card-body">
{% if comments %}
{% for comment in comments %}
<div class="card card-default">
<div class="card-header" role="tab" id="">
<div class="card-title mb-0 clearfix">
<div class="float-md-end">{{ comment.created }}</div>
<div class="float-md-start">{% if comment.user.profile.main_character %}{{ comment.user.profile.main_character }}{% else %}{{ comment.user }}{% endif %}</div>
</div>
</div>
<div class="card-body">{{ comment.text|linebreaks }}</div>
</div>
{% endfor %}
{% else %}
<div class="alert alert-info">
{% translate "No comments" %}
</div>
{% endif %}
</div>
</div>
</div>
{% endif %}
{% endif %}
</div>
{% if perms.hrapplications.add_applicationcomment %}
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal fade" id="modal-hr-comment" tabindex="-1" aria-labelledby="modalHrComment" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span aria-hidden="true">&times;</span><span class="sr-only">{% translate "Close" %}</span>
</button>
<h4 class="modal-title" id="myModalLabel">{% translate "Add Comment" %}</h4>
<div class="modal-title fs-5" id="modalHrCommentLabel">
{% translate "Add Comment" %}
</div>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{% translate 'Close' %}"></button>
</div>
<div class="modal-body">
<form class="form-signin" role="form" action="" method="POST">
{% csrf_token %}
{{ comment_form|bootstrap }}
<br>
<button class="btn btn-lg btn-primary btn-block" type="submit">{% translate "Add Comment" %}</button>
{% bootstrap_form comment_form %}
<div class="form-group mt-3 clearfix">
{% translate "Add comment" as button_text %}
{% bootstrap_button button_class="btn btn-primary" content=button_text name="addComment" id="addComment" %}
</div>
</form>
</div>
<div class="modal-footer"></div>
</div>
</div>
</div>

View File

@@ -4,9 +4,9 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# Erik Kalkoken <erik.kalkoken@gmail.com>, 2020
# Joel Falknau <ozirascal@gmail.com>, 2021
# Peter Pfeufer, 2022
# Erik Kalkoken <erik.kalkoken@gmail.com>, 2023
# Joel Falknau <ozirascal@gmail.com>, 2023
# Peter Pfeufer, 2023
#
#, fuzzy
msgid ""
@@ -14,8 +14,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-10-09 18:20+1000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
"Last-Translator: Peter Pfeufer, 2022\n"
"PO-Revision-Date: 2023-10-08 09:23+0000\n"
"Last-Translator: Peter Pfeufer, 2023\n"
"Language-Team: German (https://app.transifex.com/alliance-auth/teams/107430/de/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -34,7 +34,8 @@ msgstr "Google Analytics V4"
#: allianceauth/authentication/decorators.py:37
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."
"Zur Ausführung dieser Aktion ist ein Hauptcharakter erforderlich. Füge unten"
" einen hinzu."
#: allianceauth/authentication/forms.py:12
msgid "Email"
@@ -131,7 +132,7 @@ msgstr "Hauptcharakter ändern"
#: allianceauth/authentication/templates/authentication/dashboard.html:125
msgid "Group Memberships"
msgstr "Gruppen"
msgstr "Gruppenmitgliedschaften"
#: allianceauth/authentication/templates/authentication/dashboard.html:145
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:21
@@ -206,7 +207,7 @@ msgstr ""
#: allianceauth/authentication/views.py:83
#, python-format
msgid "Changed main character to %(char)s"
msgstr "Haupcharakter geändert zu %(char)s"
msgstr "Haupcharakter zu %(char)s geändert"
#: allianceauth/authentication/views.py:92
#, python-format
@@ -233,13 +234,12 @@ msgid ""
"Sent confirmation email. Please follow the link to confirm your email "
"address."
msgstr ""
"Bestätigungsmail gesendet. Bitte folge dem Link in der E-Mail zur "
"Bestätigung."
"Bestätigungs-E-Mail gesendet. Bitte folge dem Link, um Deine E-Mail-Adresse "
"zu bestätigen."
#: allianceauth/authentication/views.py:257
msgid "Confirmed your email address. Please login to continue."
msgstr ""
"Deine E-Mail Adresse wurde bestätigt. Bitte log Dich ein um fortzufahren."
msgstr "Deine E-Mail Adresse wurde bestätigt. Bitte einloggen zum Fortfahren."
#: allianceauth/authentication/views.py:262
msgid "Registration of new accounts is not allowed at this time."
@@ -274,7 +274,7 @@ msgstr "Hauptcharaktere"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:22
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:14
msgid "Members"
msgstr "Mitgliederzahl"
msgstr "Mitglieder"
#: allianceauth/corputils/templates/corputils/corpstats.html:35
msgid "Unregistered"
@@ -282,7 +282,7 @@ msgstr "Nicht registriert"
#: allianceauth/corputils/templates/corputils/corpstats.html:38
msgid "Last update:"
msgstr "Letzes Update:"
msgstr "Letzte Aktualisierung:"
#: allianceauth/corputils/templates/corputils/corpstats.html:74
#: allianceauth/corputils/templates/corputils/corpstats.html:112
@@ -382,11 +382,11 @@ msgstr "Charakter nicht registriert!"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/characternotexisting.html:19
msgid "This character is not associated with an auth account."
msgstr "Dieser Charakter ist mit keinen Auth Konto verbunden."
msgstr "Dieser Charakter ist keinem Auth Konto zugeordnet."
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/characternotexisting.html:19
msgid "Add it here"
msgstr "Füge es hier hinzu"
msgstr "Füge ihn hier hinzu"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/characternotexisting.html:19
msgid "before attempting to click fleet attendance links."
@@ -394,7 +394,7 @@ msgstr "bevor Du versuchst auf FAT-Links zu klicken."
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkformatter.html:5
msgid "Create Fatlink"
msgstr "Erstelle FAT-Link"
msgstr "FAT-Link erstellen"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkformatter.html:9
#: allianceauth/optimer/templates/optimer/add.html:13
@@ -409,20 +409,20 @@ msgstr "Fehlerhafte Anfrage!"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkformatter.html:24
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:63
msgid "Create fatlink"
msgstr "Erstelle FAT-Link"
msgstr "FAT-Link erstellen"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:3
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:4
msgid "Fatlink view"
msgstr "FAT-Link sehen"
msgstr "FAT-Link ansehen"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:7
msgid "Edit fatlink"
msgstr "Editiere FAT-Link"
msgstr "FAT-Link bearbeiten"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:11
msgid "Delete fat"
msgstr "Lösche FAT"
msgstr "FAT löschen"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:17
msgid "Registered characters"
@@ -497,7 +497,7 @@ msgstr[1] "%(user)s hat diesen Monat %(links)s FAT-Links eingesammelt."
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkpersonalmonthlystatisticsview.html:26
msgid "Times used"
msgstr "male genutzt"
msgstr "Wie oft genutzt"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkpersonalmonthlystatisticsview.html:37
#, python-format
@@ -570,7 +570,7 @@ msgstr "FAT-Link Statistik"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:20
msgid "Ticker"
msgstr "Ticker: "
msgstr "Ticker"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:8
msgid "Participation data"
@@ -594,7 +594,7 @@ msgstr "Letzter FAT-Link"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:58
msgid "View statistics"
msgstr "Statistik"
msgstr "Statistiken ansehen"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:95
msgid "No created fatlinks on record."
@@ -713,8 +713,8 @@ msgid ""
"States listed here will have the ability to join this group provided they "
"have the proper permissions.<br>"
msgstr ""
"Hier gelistete Ränge können dieser Gruppe beitreten, vorausgesetzt sie haben"
" die entsprechenden Berechtigungen.<br>"
"Die hier aufgeführten Status können dieser Gruppe beitreten, sofern sie über"
" die entsprechenden Berechtigungen verfügen.<br>"
#: allianceauth/groupmanagement/models.py:171
msgid ""
@@ -814,7 +814,7 @@ msgstr "Gruppenmitglieder"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:113
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:21
msgid "Organization"
msgstr "Organization"
msgstr "Organisation"
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:49
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:75
@@ -933,18 +933,18 @@ msgstr "Gruppenverwaltung"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:24
msgid "Join Requests"
msgstr "Beitrittsgesuche"
msgstr "Beitrittsanfragen"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:35
msgid "Leave Requests"
msgstr "Austrittsgesuche"
msgstr "Austrittsanfragen"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:57
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:114
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:18
#: allianceauth/services/modules/openfire/forms.py:6
msgid "Group"
msgstr "Gruppen"
msgstr "Gruppe"
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:88
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:145
@@ -968,7 +968,7 @@ msgstr "Keine Gruppenaustrittsanfragen"
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:8
#: allianceauth/templates/allianceauth/top-menu.html:8
msgid "Toggle navigation"
msgstr "Toggle Navigation"
msgstr "Navigation umschalten"
#: allianceauth/groupmanagement/templates/groupmanagement/menu.html:19
msgid "Group Requests"
@@ -994,7 +994,7 @@ msgstr "Gruppe existiert nicht"
#: allianceauth/groupmanagement/views.py:195
#, python-format
msgid "Accepted application from %(mainchar)s to %(group)s."
msgstr "Beitrittsgesuch von %(mainchar)s zur Gruppe %(group)s zugestimmt."
msgstr "Beitrittsanfrage von %(mainchar)s zur Gruppe %(group)s akzeptiert."
#: allianceauth/groupmanagement/views.py:201
#: allianceauth/groupmanagement/views.py:232
@@ -1003,18 +1003,18 @@ msgid ""
"An unhandled error occurred while processing the application from "
"%(mainchar)s to %(group)s."
msgstr ""
"Bei der Bearbeitung des Beitrittsgesuchs von %(mainchar)s zur Gruppe "
"Bei der Bearbeitung des Beitrittsanfrage von %(mainchar)s zur Gruppe "
"%(group)s ist ein unbehandelter Fehler aufgetreten."
#: allianceauth/groupmanagement/views.py:226
#, python-format
msgid "Rejected application from %(mainchar)s to %(group)s."
msgstr "Beitrittsgesuch von %(mainchar)s zur Gruppe %(group)s abgelehnt."
msgstr "Beitrittsanfrage von %(mainchar)s zur Gruppe %(group)s abgelehnt."
#: allianceauth/groupmanagement/views.py:261
#, python-format
msgid "Accepted application from %(mainchar)s to leave %(group)s."
msgstr "Austrittsgesuch von %(mainchar)s für Gruppe %(group)s akzeptiert."
msgstr "Austrittsanfrage von %(mainchar)s für Gruppe %(group)s akzeptiert."
#: allianceauth/groupmanagement/views.py:266
#: allianceauth/groupmanagement/views.py:298
@@ -1023,13 +1023,13 @@ msgid ""
"An unhandled error occurred while processing the application from "
"%(mainchar)s to leave %(group)s."
msgstr ""
"Bei der Bearbeitung des Austrittsgesuchs von %(mainchar)s für Gruppe "
"Bei der Bearbeitung des Austrittsanfrage von %(mainchar)s für Gruppe "
"%(group)s ist ein unbehandelter Fehler aufgetreten."
#: allianceauth/groupmanagement/views.py:292
#, python-format
msgid "Rejected application from %(mainchar)s to leave %(group)s."
msgstr "Austrittsgesuch von %(mainchar)s für Gruppe %(group)s abgelehnt."
msgstr "Austrittsanfrage von %(mainchar)s für Gruppe %(group)s abgelehnt."
#: allianceauth/groupmanagement/views.py:336
#: allianceauth/groupmanagement/views.py:346
@@ -1042,7 +1042,7 @@ msgstr "Du bist bereits Mitglied dieser Gruppe."
#: allianceauth/groupmanagement/views.py:358
msgid "You already have a pending application for that group."
msgstr "Du hast Dich bereits für diese Gruppe beworben."
msgstr "Du hast bereits für diese Gruppe angefragt."
#: allianceauth/groupmanagement/views.py:367
#, python-format
@@ -1059,12 +1059,12 @@ msgstr "Du bist kein Mitglied dieser Gruppe"
#: allianceauth/groupmanagement/views.py:393
msgid "You already have a pending leave request for that group."
msgstr "Du hast bereits ein ausstehendes Austrittsgesuch für diese Gruppe."
msgstr "Du hast bereits eine ausstehendes Austrittsanfrage für diese Gruppe."
#: allianceauth/groupmanagement/views.py:409
#, python-format
msgid "Applied to leave group %(group)s."
msgstr "Austrittsgesuch für Gruppe %(group)s gesendet."
msgstr "Austrittsanfrage für Gruppe %(group)s gesendet."
#: allianceauth/hrapplications/auth_hooks.py:14
msgid "Applications"
@@ -1086,11 +1086,11 @@ msgstr "Wähle eine Corporation"
#: allianceauth/hrapplications/templates/hrapplications/corpchoice.html:10
msgid "Available Corps"
msgstr "Zur Auswahl stehende Corporations"
msgstr "Verfügbare Corporationen"
#: allianceauth/hrapplications/templates/hrapplications/corpchoice.html:22
msgid "No corps are accepting applications at this time."
msgstr "Zur Zeit nimmt keine Corp Bewerbungen entgegen."
msgstr "Zur Zeit nimmt keine Corp Bewerbungen an."
#: allianceauth/hrapplications/templates/hrapplications/create.html:4
#: allianceauth/hrapplications/templates/hrapplications/create.html:7
@@ -1186,7 +1186,7 @@ msgstr "Keine angesehenen Bewerbungen"
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:62
#: allianceauth/hrapplications/templates/hrapplications/view.html:134
msgid "Close"
msgstr "Geschlossen"
msgstr "Schließen"
#: allianceauth/hrapplications/templates/hrapplications/management.html:177
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:63
@@ -1200,7 +1200,7 @@ msgstr "Suche"
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:11
msgid "Application Search Results"
msgstr "Bewerbungen Suchergebnisse"
msgstr "Ergebnisse der Bewerbungssuche"
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:22
msgid "Application ID"
@@ -1342,12 +1342,12 @@ msgstr "Operationsart"
#: allianceauth/optimer/form.py:17
#: allianceauth/srp/templates/srp/management.html:38
msgid "Fleet Commander"
msgstr "Flottenkommandeur"
msgstr "Flottenkommandant"
#: allianceauth/optimer/form.py:22 allianceauth/srp/form.py:14
#: allianceauth/srp/templates/srp/data.html:91
msgid "Additional Info"
msgstr "Zusätzliche Info"
msgstr "Zusätzliche Informationen"
#: allianceauth/optimer/form.py:23
msgid "(Optional) Describe the operation with a couple of short words."
@@ -1360,7 +1360,7 @@ msgstr "Operation erstellen"
#: allianceauth/optimer/templates/optimer/fleetoptable.html:12
msgid "Form Up System"
msgstr "Form Up System"
msgstr "Startsystem"
#: allianceauth/optimer/templates/optimer/fleetoptable.html:14
#: allianceauth/timerboard/templates/timerboard/view.html:36
@@ -1384,20 +1384,20 @@ msgstr "Flottenoperationen Zeiten"
#: allianceauth/optimer/templates/optimer/management.html:20
#: allianceauth/timerboard/templates/timerboard/view.html:22
msgid "Current Eve Time:"
msgstr "Momentane Eve Zeit"
msgstr "Aktuelle Eve Zeit"
#: allianceauth/optimer/templates/optimer/management.html:26
msgid "Next Fleet Operations"
msgstr "Anstehende Flottenoperationen"
msgstr "Anstehende Flotten"
#: allianceauth/optimer/templates/optimer/management.html:30
#: allianceauth/timerboard/templates/timerboard/view.html:362
msgid "No upcoming timers."
msgstr "Keine kommenden Timer."
msgstr "Keine bevorstehenden Timer."
#: allianceauth/optimer/templates/optimer/management.html:33
msgid "Past Fleet Operations"
msgstr "Vergangene Flottenoperationen"
msgstr "Vergangene Flotten"
#: allianceauth/optimer/templates/optimer/management.html:37
#: allianceauth/timerboard/templates/timerboard/view.html:535
@@ -1408,7 +1408,7 @@ msgstr "Keine vergangenen Timer."
#: allianceauth/optimer/templates/optimer/update.html:15
#: allianceauth/optimer/templates/optimer/update.html:27
msgid "Update Fleet Operation"
msgstr "Aktualisiere Flottenoperationen"
msgstr "Aktualisiere Flottenoperation"
#: allianceauth/optimer/templates/optimer/update.html:21
msgid "Fleet Operation Does Not Exist"
@@ -1432,7 +1432,7 @@ msgstr "Änderungen für Operation timer %(opname)s gespeichert."
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:4
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:8
msgid "Permissions Audit"
msgstr "Berechtigungsübersicht"
msgstr "Berechtigungsprüfung"
#: allianceauth/permissions_tool/templates/permissions_tool/audit.html:20
msgid "User / Character"
@@ -1494,11 +1494,11 @@ msgstr "Dienste"
#: allianceauth/services/forms.py:6
msgid "Name of Fleet:"
msgstr "SRP Flotte erstellen:"
msgstr "Name der Flotte:"
#: allianceauth/services/forms.py:7
msgid "Fleet Commander:"
msgstr "Flottenkommandeur:"
msgstr "Flottenkommandant:"
#: allianceauth/services/forms.py:8
msgid "Fleet Comms:"
@@ -1514,11 +1514,11 @@ msgstr "Schiffspriorität:"
#: allianceauth/services/forms.py:11
msgid "Formup Location:"
msgstr "Formup Location:"
msgstr "Startsystem:"
#: allianceauth/services/forms.py:12
msgid "Formup Time:"
msgstr "Formup Zeit:"
msgstr "Startzeit:"
#: allianceauth/services/forms.py:13
msgid "Expected Duration:"
@@ -1530,7 +1530,7 @@ msgstr "Grund:"
#: allianceauth/services/forms.py:15
msgid "Reimbursable?*"
msgstr "Erstattungsfähig?"
msgstr "Erstattungsfähig?*"
#: allianceauth/services/forms.py:15 allianceauth/services/forms.py:16
msgid "Yes"
@@ -1542,7 +1542,7 @@ msgstr "Nein"
#: allianceauth/services/forms.py:16
msgid "Important?*"
msgstr "Wichtig?"
msgstr "Wichtig?*"
#: allianceauth/services/forms.py:21 allianceauth/services/forms.py:31
msgid "Password"
@@ -1550,7 +1550,7 @@ msgstr "Passwort"
#: allianceauth/services/forms.py:26 allianceauth/services/forms.py:36
msgid "Password must be at least 8 characters long."
msgstr "Passwort muss mindestens 8 Zeichen lang sein"
msgstr "Das Passwort muss mindestens 8 Zeichen lang sein"
#: allianceauth/services/modules/discord/models.py:187
msgid "Discord Account Disabled"
@@ -1591,7 +1591,7 @@ msgstr "Discord Konto deaktiviert."
#: allianceauth/services/modules/discord/views.py:36
#: allianceauth/services/modules/discord/views.py:59
msgid "An error occurred while processing your Discord account."
msgstr "Es gab einen Fehler bei der Verarbeitung Deines Discord Kontos."
msgstr "Es gab einen Fehler während der Verarbeitung Deines Discord Kontos."
#: allianceauth/services/modules/discord/views.py:102
msgid "Your Discord account has been successfully activated."
@@ -1607,7 +1607,7 @@ msgstr ""
#: allianceauth/services/modules/discourse/views.py:29
msgid "You are not authorized to access Discourse."
msgstr "Du bist nicht autorisiert auf Discorse zuzugreifen."
msgstr "Du bist nicht autorisiert auf Discourse zuzugreifen."
#: allianceauth/services/modules/discourse/views.py:34
msgid "You must have a main character set to access Discourse."
@@ -1619,14 +1619,14 @@ msgid ""
"No SSO payload or signature. Please contact support if this problem "
"persists."
msgstr ""
"Keine SSO-Nutzdaten oder Signaturen. Bitte wenden Sie sich an den Support, "
"wenn das Problem weiterhin besteht."
"Keine SSO-Nutzdaten oder Signaturen. Bitte wende Dich an den Support, wenn "
"das Problem weiterhin besteht."
#: allianceauth/services/modules/discourse/views.py:54
#: allianceauth/services/modules/discourse/views.py:62
msgid "Invalid payload. Please contact support if this problem persists."
msgstr ""
"Ungültige Nutzdaten. Bitte wenden Sie sich an den Support, wenn das Problem "
"Ungültige Nutzdaten. Bitte wenden Dich an den Support, wenn das Problem "
"weiterhin besteht."
#: allianceauth/services/modules/ips4/views.py:31
@@ -1638,7 +1638,7 @@ msgstr "IP4Suite Konto aktiviert."
#: allianceauth/services/modules/ips4/views.py:81
#: allianceauth/services/modules/ips4/views.py:101
msgid "An error occurred while processing your IPSuite4 account."
msgstr "Es gab einen Fehler bei der Verarbeitung Deines IPSuite4 Kontos."
msgstr "Es gab einen Fehler während der Verarbeitung Deines IPSuite4 Kontos."
#: allianceauth/services/modules/ips4/views.py:52
msgid "Reset IPSuite4 password."
@@ -1660,7 +1660,7 @@ msgstr "Jabber"
#: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:5
#: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:10
msgid "Jabber Broadcast"
msgstr "Jabber Übertragung"
msgstr "Jabber Ankündigung"
#: allianceauth/services/modules/openfire/auth_hooks.py:94
msgid "Fleet Broadcast Formatter"
@@ -1672,11 +1672,11 @@ msgstr "Nachricht"
#: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:16
msgid "Broadcast Sent!!"
msgstr "Übertragung gesendet!!"
msgstr "Ankündigung gesendet!!"
#: allianceauth/services/modules/openfire/templates/services/openfire/broadcast.html:22
msgid "Broadcast"
msgstr "Übertragungen"
msgstr "Ankündigung"
#: allianceauth/services/modules/openfire/views.py:35
msgid "Activated jabber account."
@@ -1687,7 +1687,7 @@ msgstr "Jabber Konto aktiviert."
#: allianceauth/services/modules/openfire/views.py:76
#: allianceauth/services/modules/openfire/views.py:147
msgid "An error occurred while processing your jabber account."
msgstr "Es gab einen Fehler bei der Verarbeitung Deines Jabber Kontos."
msgstr "Es gab einen Fehler während der Verarbeitung Deines Jabber Kontos."
#: allianceauth/services/modules/openfire/views.py:69
msgid "Reset jabber password."
@@ -1696,7 +1696,7 @@ msgstr "Jabber Passwort zurücksetzen."
#: allianceauth/services/modules/openfire/views.py:115
#, python-format
msgid "Sent jabber broadcast to %s"
msgstr "Sende Jabber Durchsage an %s"
msgstr "Sende Jabber Ankündigung an %s"
#: allianceauth/services/modules/openfire/views.py:144
msgid "Set jabber password."
@@ -1711,7 +1711,7 @@ msgstr "Forum Konto aktiviert."
#: allianceauth/services/modules/phpbb3/views.py:78
#: allianceauth/services/modules/phpbb3/views.py:101
msgid "An error occurred while processing your forum account."
msgstr "Es gab einen Fehler bei der Verarbeitung Deines Forum Kontos."
msgstr "Es gab einen Fehler während der Verarbeitung Deines Forum Kontos."
#: allianceauth/services/modules/phpbb3/views.py:53
msgid "Deactivated forum account."
@@ -1734,7 +1734,7 @@ msgstr "SMF Konto aktiviert."
#: allianceauth/services/modules/smf/views.py:102
#: allianceauth/services/modules/smf/views.py:124
msgid "An error occurred while processing your SMF account."
msgstr "Es gab einen Fehler bei der Verarbeitung Deines SMF Kontos."
msgstr "Es gab einen Fehler während der Verarbeitung Deines SMF Kontos."
#: allianceauth/services/modules/smf/views.py:78
msgid "Deactivated SMF account."
@@ -1751,7 +1751,7 @@ msgstr "Setze SMF Passwort."
#: allianceauth/services/modules/teamspeak3/forms.py:14
#, python-format
msgid "Unable to locate user %s on server"
msgstr "Kann den Benutzer %s auf dem Server nicht finden"
msgstr "Der Benutzer %s konnte auf dem Server nicht gefunden werden"
#: allianceauth/services/modules/teamspeak3/templates/admin/teamspeak3/authts/change_list.html:8
msgid "Update TS3 groups"
@@ -1783,7 +1783,8 @@ msgstr "TeamSpeak3 Konto aktiviert."
#: allianceauth/services/modules/teamspeak3/views.py:74
#: allianceauth/services/modules/teamspeak3/views.py:100
msgid "An error occurred while processing your TeamSpeak3 account."
msgstr "Es gab einen Fehler bei der Verarbeitung Deines TeamSpeak3 Kontos."
msgstr ""
"Es gab einen Fehler während der Verarbeitung Deines TeamSpeak3 Kontos."
#: allianceauth/services/modules/teamspeak3/views.py:71
msgid "Deactivated TeamSpeak3 account."
@@ -1802,7 +1803,7 @@ msgstr "XenForo Konto aktiviert."
#: allianceauth/services/modules/xenforo/views.py:73
#: allianceauth/services/modules/xenforo/views.py:94
msgid "An error occurred while processing your XenForo account."
msgstr "Es gab einen Fehler bei der Verarbeitung Deines XenForo Kontos."
msgstr "Es gab einen Fehler während der Verarbeitung Deines XenForo Kontos."
#: allianceauth/services/modules/xenforo/views.py:50
msgid "Deactivated XenForo account."
@@ -1832,7 +1833,7 @@ msgstr "Formatieren"
#: allianceauth/services/templates/services/service_confirm_delete.html:12
#, python-format
msgid "Delete %(service_name)s Account?"
msgstr "Konto %(service_name)s löschen?"
msgstr " %(service_name)s Konto löschen?"
#: allianceauth/services/templates/services/service_confirm_delete.html:20
#, python-format
@@ -1856,7 +1857,7 @@ msgstr "%(service_name)s Passwort ändern"
#: allianceauth/services/templates/services/service_password.html:9
#, python-format
msgid "Set %(service_name)s Password"
msgstr "%(service_name)s Passwort"
msgstr "%(service_name)s Passwort setzen"
#: allianceauth/services/templates/services/service_password.html:17
msgid "Set Password"
@@ -1927,7 +1928,7 @@ msgstr "SRP Flotten Daten"
#: allianceauth/srp/templates/srp/data.html:50
msgid "SRP Fleet Data"
msgstr "SRP-Flotte Daten"
msgstr "SRP Flotte Daten"
#: allianceauth/srp/templates/srp/data.html:55
msgid "Mark Incomplete"
@@ -2005,7 +2006,7 @@ msgstr "Füge SRP Flotte hinzu"
#: allianceauth/srp/templates/srp/management.html:39
msgid "Fleet AAR"
msgstr "Flotten AAR"
msgstr "Flottenbericht"
#: allianceauth/srp/templates/srp/management.html:40
msgid "Fleet SRP Code"
@@ -2033,7 +2034,7 @@ msgstr "Deaktiviert"
#: allianceauth/srp/templates/srp/management.html:83
msgid "Completed"
msgstr "Fertig"
msgstr "Abgeschlossen"
#: allianceauth/srp/templates/srp/management.html:101
msgid "Are you sure you want to delete this SRP code and its contents?"
@@ -2086,7 +2087,7 @@ msgstr "SRP Link für %(fleetname)s aktiviert."
#: allianceauth/srp/views.py:140
#, python-format
msgid "Marked SRP fleet %(fleetname)s as completed."
msgstr "SRP Flotte %(fleetname)s als vollständig markiert."
msgstr "SRP Flotte %(fleetname)s als abgeschlossen markiert."
#: allianceauth/srp/views.py:153
#, python-format
@@ -2204,7 +2205,7 @@ msgstr "Testversion verfügbar"
#: allianceauth/templates/allianceauth/admin-status/overview.html:78
msgid "Task Queue"
msgstr "Warteschlange"
msgstr "Task-Warteschlange"
#: allianceauth/templates/allianceauth/admin-status/overview.html:81
#, python-format
@@ -2249,7 +2250,7 @@ msgstr "Ausloggen"
#: allianceauth/timerboard/form.py:53
msgid "Other"
msgstr "anderes"
msgstr "Anderes"
#: allianceauth/timerboard/form.py:54
#: allianceauth/timerboard/templates/timerboard/view.html:62
@@ -2353,7 +2354,7 @@ msgstr "Timer löschen"
#: allianceauth/timerboard/templates/timerboard/timer_confirm_delete.html:19
#, python-format
msgid "Are you sure you want to delete timer \"%(object)s\"?"
msgstr "Bist Du sicher das Du Timer \"%(object)s\" löschen möchtest?"
msgstr "Bist Du sicher das Du Timer %(object)s löschen möchtest?"
#: allianceauth/timerboard/templates/timerboard/timer_create_form.html:5
#: allianceauth/timerboard/templates/timerboard/timer_create_form.html:13

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-10-09 18:20+1000\n"
"POT-Creation-Date: 2023-11-08 23:55+1000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -26,7 +26,7 @@ msgstr ""
msgid "Google Analytics V4"
msgstr ""
#: allianceauth/authentication/decorators.py:37
#: allianceauth/authentication/decorators.py:49
msgid "A main character is required to perform that action. Add one below."
msgstr ""
@@ -39,63 +39,68 @@ msgstr ""
msgid "You are not allowed to add or remove these restricted groups: %s"
msgstr ""
#: allianceauth/authentication/models.py:80
#: allianceauth/authentication/models.py:71
msgid "English"
msgstr ""
#: allianceauth/authentication/models.py:81
#: allianceauth/authentication/models.py:72
msgid "German"
msgstr ""
#: allianceauth/authentication/models.py:82
#: allianceauth/authentication/models.py:73
msgid "Spanish"
msgstr ""
#: allianceauth/authentication/models.py:83
#: allianceauth/authentication/models.py:74
msgid "Chinese Simplified"
msgstr ""
#: allianceauth/authentication/models.py:84
#: allianceauth/authentication/models.py:75
msgid "Russian"
msgstr ""
#: allianceauth/authentication/models.py:85
#: allianceauth/authentication/models.py:76
msgid "Korean"
msgstr ""
#: allianceauth/authentication/models.py:86
#: allianceauth/authentication/models.py:77
msgid "French"
msgstr ""
#: allianceauth/authentication/models.py:87
#: allianceauth/authentication/models.py:78
msgid "Japanese"
msgstr ""
#: allianceauth/authentication/models.py:88
#: allianceauth/authentication/models.py:79
msgid "Italian"
msgstr ""
#: allianceauth/authentication/models.py:91
msgid "Language"
#: allianceauth/authentication/models.py:80
msgid "Ukrainian"
msgstr ""
#: allianceauth/authentication/models.py:96
msgid "Language"
msgstr ""
#: allianceauth/authentication/models.py:101
#: allianceauth/templates/allianceauth/night-toggle.html:6
msgid "Night Mode"
msgstr ""
#: allianceauth/authentication/models.py:110
#: allianceauth/authentication/models.py:115
#, python-format
msgid "State changed to: %s"
msgstr ""
#: allianceauth/authentication/models.py:111
#: allianceauth/authentication/models.py:116
#, python-format
msgid "Your user's state is now: %(state)s"
msgstr ""
#: allianceauth/authentication/templates/authentication/dashboard.html:4
#: allianceauth/authentication/templates/authentication/dashboard.html:7
#: allianceauth/authentication/templates/authentication/tokens.html:4
#: allianceauth/templates/allianceauth/side-menu.html:10
msgid "Dashboard"
msgstr ""
@@ -151,8 +156,49 @@ msgstr ""
msgid "Alliance"
msgstr ""
#: allianceauth/authentication/templates/authentication/tokens.html:7
#: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:62
msgid "Token Management"
msgstr ""
#: allianceauth/authentication/templates/authentication/tokens.html:12
msgid "Scopes"
msgstr ""
#: allianceauth/authentication/templates/authentication/tokens.html:13
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
#: allianceauth/hrapplications/templates/hrapplications/management.html:83
#: allianceauth/hrapplications/templates/hrapplications/management.html:127
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:27
#: allianceauth/hrapplications/templates/hrapplications/view.html:73
#: allianceauth/srp/templates/srp/data.html:101
#: allianceauth/srp/templates/srp/management.html:44
msgid "Actions"
msgstr ""
#: allianceauth/authentication/templates/authentication/tokens.html:14
#: allianceauth/corputils/templates/corputils/corpstats.html:74
#: allianceauth/corputils/templates/corputils/corpstats.html:112
#: allianceauth/corputils/templates/corputils/corpstats.html:156
#: allianceauth/corputils/templates/corputils/search.html:13
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:22
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:26
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:55
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
msgid "Character"
msgstr ""
#: allianceauth/authentication/templates/authentication/tokens.html:28
msgid ""
"This page is a best attempt, but backups or database logs can still contain "
"your tokens. Always revoke tokens on https://community.eveonline.com/support/"
"third-party-applications/ where possible."
msgstr ""
#: allianceauth/authentication/templates/public/login.html:6
#: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:58
#: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:69
msgid "Login"
msgstr ""
@@ -184,47 +230,47 @@ msgstr ""
msgid "Invalid or expired activation link."
msgstr ""
#: allianceauth/authentication/views.py:77
#: allianceauth/authentication/views.py:118
#, python-format
msgid ""
"Cannot change main character to %(char)s: character owned by a different "
"account."
msgstr ""
#: allianceauth/authentication/views.py:83
#: allianceauth/authentication/views.py:124
#, python-format
msgid "Changed main character to %(char)s"
msgstr ""
#: allianceauth/authentication/views.py:92
#: allianceauth/authentication/views.py:133
#, python-format
msgid "Added %(name)s to your account."
msgstr ""
#: allianceauth/authentication/views.py:94
#: allianceauth/authentication/views.py:135
#, python-format
msgid "Failed to add %(name)s to your account: they already have an account."
msgstr ""
#: allianceauth/authentication/views.py:133
#: allianceauth/authentication/views.py:174
msgid "Unable to authenticate as the selected character."
msgstr ""
#: allianceauth/authentication/views.py:197
#: allianceauth/authentication/views.py:238
msgid "Registration token has expired."
msgstr ""
#: allianceauth/authentication/views.py:252
#: allianceauth/authentication/views.py:296
msgid ""
"Sent confirmation email. Please follow the link to confirm your email "
"address."
msgstr ""
#: allianceauth/authentication/views.py:257
#: allianceauth/authentication/views.py:301
msgid "Confirmed your email address. Please login to continue."
msgstr ""
#: allianceauth/authentication/views.py:262
#: allianceauth/authentication/views.py:306
msgid "Registration of new accounts is not allowed at this time."
msgstr ""
@@ -267,19 +313,6 @@ msgstr ""
msgid "Last update:"
msgstr ""
#: allianceauth/corputils/templates/corputils/corpstats.html:74
#: allianceauth/corputils/templates/corputils/corpstats.html:112
#: allianceauth/corputils/templates/corputils/corpstats.html:156
#: allianceauth/corputils/templates/corputils/search.html:13
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:22
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:26
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:30
#: allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html:29
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:55
#: allianceauth/groupmanagement/templates/groupmanagement/index.html:112
msgid "Character"
msgstr ""
#: allianceauth/corputils/templates/corputils/corpstats.html:75
#: allianceauth/corputils/templates/corputils/search.html:14
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:31
@@ -611,36 +644,41 @@ msgstr ""
msgid "Group Management"
msgstr ""
#: allianceauth/groupmanagement/forms.py:15
#: allianceauth/groupmanagement/forms.py:18
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:35
msgid "Users"
msgstr ""
#: allianceauth/groupmanagement/forms.py:52
msgid "This name has been reserved and can not be used for groups."
msgstr ""
#: allianceauth/groupmanagement/forms.py:25
#: allianceauth/groupmanagement/forms.py:62
msgid "(auto)"
msgstr ""
#: allianceauth/groupmanagement/forms.py:34
#: allianceauth/groupmanagement/forms.py:71
msgid "There already exists a group with that name."
msgstr ""
#: allianceauth/groupmanagement/models.py:105
#: allianceauth/groupmanagement/models.py:104
msgid ""
"Internal group, users cannot see, join or request to join this group."
"<br>Used for groups such as Members, Corp_*, Alliance_* etc.<br><b>Overrides "
"Hidden and Open options when selected.</b>"
msgstr ""
#: allianceauth/groupmanagement/models.py:113
#: allianceauth/groupmanagement/models.py:112
msgid "Group is hidden from users but can still join with the correct link."
msgstr ""
#: allianceauth/groupmanagement/models.py:119
#: allianceauth/groupmanagement/models.py:118
msgid ""
"Group is open and users will be automatically added upon request.<br>If the "
"group is not open users will need their request manually approved."
msgstr ""
#: allianceauth/groupmanagement/models.py:126
#: allianceauth/groupmanagement/models.py:125
msgid ""
"Group is public. Any registered user is able to join this group, with "
"visibility based on the other options set for this group.<br>Auth will not "
@@ -648,65 +686,65 @@ msgid ""
"authenticated."
msgstr ""
#: allianceauth/groupmanagement/models.py:135
#: allianceauth/groupmanagement/models.py:134
msgid ""
"Group is restricted. This means that adding or removing users for this group "
"requires a superuser admin."
msgstr ""
#: allianceauth/groupmanagement/models.py:144
#: allianceauth/groupmanagement/models.py:143
msgid ""
"Group leaders can process requests for this group. Use the <code>auth."
"group_management</code> permission to allow a user to manage all groups.<br>"
msgstr ""
#: allianceauth/groupmanagement/models.py:154
#: allianceauth/groupmanagement/models.py:153
msgid ""
"Members of leader groups can process requests for this group. Use the "
"<code>auth.group_management</code> permission to allow a user to manage all "
"groups.<br>"
msgstr ""
#: allianceauth/groupmanagement/models.py:163
#: allianceauth/groupmanagement/models.py:162
msgid ""
"States listed here will have the ability to join this group provided they "
"have the proper permissions.<br>"
msgstr ""
#: allianceauth/groupmanagement/models.py:171
#: allianceauth/groupmanagement/models.py:170
msgid ""
"Short description <i>(max. 512 characters)</i> of the group shown to users."
msgstr ""
#: allianceauth/groupmanagement/models.py:178
#: allianceauth/groupmanagement/models.py:177
msgid "Can request non-public groups"
msgstr ""
#: allianceauth/groupmanagement/models.py:209
#: allianceauth/groupmanagement/models.py:208
msgid "name"
msgstr ""
#: allianceauth/groupmanagement/models.py:212
#: allianceauth/groupmanagement/models.py:211
msgid "Name that can not be used for groups."
msgstr ""
#: allianceauth/groupmanagement/models.py:215
#: allianceauth/groupmanagement/models.py:214
msgid "reason"
msgstr ""
#: allianceauth/groupmanagement/models.py:215
#: allianceauth/groupmanagement/models.py:214
msgid "Reason why this name is reserved."
msgstr ""
#: allianceauth/groupmanagement/models.py:218
#: allianceauth/groupmanagement/models.py:217
msgid "created by"
msgstr ""
#: allianceauth/groupmanagement/models.py:223
#: allianceauth/groupmanagement/models.py:222
msgid "created at"
msgstr ""
#: allianceauth/groupmanagement/models.py:223
#: allianceauth/groupmanagement/models.py:222
msgid "Date when this entry was created"
msgstr ""
@@ -933,86 +971,86 @@ msgstr ""
msgid "Group Membership"
msgstr ""
#: allianceauth/groupmanagement/views.py:163
#: allianceauth/groupmanagement/views.py:166
#, python-format
msgid "Removed user %(user)s from group %(group)s."
msgstr ""
#: allianceauth/groupmanagement/views.py:165
#: allianceauth/groupmanagement/views.py:168
msgid "User does not exist in that group"
msgstr ""
#: allianceauth/groupmanagement/views.py:168
#: allianceauth/groupmanagement/views.py:171
msgid "Group does not exist"
msgstr ""
#: allianceauth/groupmanagement/views.py:195
#: allianceauth/groupmanagement/views.py:198
#, python-format
msgid "Accepted application from %(mainchar)s to %(group)s."
msgstr ""
#: allianceauth/groupmanagement/views.py:201
#: allianceauth/groupmanagement/views.py:232
#: allianceauth/groupmanagement/views.py:204
#: allianceauth/groupmanagement/views.py:235
#, python-format
msgid ""
"An unhandled error occurred while processing the application from "
"%(mainchar)s to %(group)s."
msgstr ""
#: allianceauth/groupmanagement/views.py:226
#: allianceauth/groupmanagement/views.py:229
#, python-format
msgid "Rejected application from %(mainchar)s to %(group)s."
msgstr ""
#: allianceauth/groupmanagement/views.py:261
#: allianceauth/groupmanagement/views.py:264
#, python-format
msgid "Accepted application from %(mainchar)s to leave %(group)s."
msgstr ""
#: allianceauth/groupmanagement/views.py:266
#: allianceauth/groupmanagement/views.py:298
#: allianceauth/groupmanagement/views.py:269
#: allianceauth/groupmanagement/views.py:301
#, python-format
msgid ""
"An unhandled error occurred while processing the application from "
"%(mainchar)s to leave %(group)s."
msgstr ""
#: allianceauth/groupmanagement/views.py:292
#: allianceauth/groupmanagement/views.py:295
#, python-format
msgid "Rejected application from %(mainchar)s to leave %(group)s."
msgstr ""
#: allianceauth/groupmanagement/views.py:336
#: allianceauth/groupmanagement/views.py:346
#: allianceauth/groupmanagement/views.py:339
#: allianceauth/groupmanagement/views.py:349
msgid "You cannot join that group"
msgstr ""
#: allianceauth/groupmanagement/views.py:341
#: allianceauth/groupmanagement/views.py:344
msgid "You are already a member of that group."
msgstr ""
#: allianceauth/groupmanagement/views.py:358
#: allianceauth/groupmanagement/views.py:361
msgid "You already have a pending application for that group."
msgstr ""
#: allianceauth/groupmanagement/views.py:367
#: allianceauth/groupmanagement/views.py:370
#, python-format
msgid "Applied to group %(group)s."
msgstr ""
#: allianceauth/groupmanagement/views.py:377
#: allianceauth/groupmanagement/views.py:380
msgid "You cannot leave that group"
msgstr ""
#: allianceauth/groupmanagement/views.py:381
#: allianceauth/groupmanagement/views.py:384
msgid "You are not a member of that group"
msgstr ""
#: allianceauth/groupmanagement/views.py:393
#: allianceauth/groupmanagement/views.py:396
msgid "You already have a pending leave request for that group."
msgstr ""
#: allianceauth/groupmanagement/views.py:409
#: allianceauth/groupmanagement/views.py:412
#, python-format
msgid "Applied to leave group %(group)s."
msgstr ""
@@ -1074,16 +1112,6 @@ msgstr ""
msgid "Username"
msgstr ""
#: allianceauth/hrapplications/templates/hrapplications/management.html:28
#: allianceauth/hrapplications/templates/hrapplications/management.html:83
#: allianceauth/hrapplications/templates/hrapplications/management.html:127
#: allianceauth/hrapplications/templates/hrapplications/searchview.html:27
#: allianceauth/hrapplications/templates/hrapplications/view.html:73
#: allianceauth/srp/templates/srp/data.html:101
#: allianceauth/srp/templates/srp/management.html:44
msgid "Actions"
msgstr ""
#: allianceauth/hrapplications/templates/hrapplications/management.html:38
#: allianceauth/hrapplications/templates/hrapplications/management.html:99
#: allianceauth/hrapplications/templates/hrapplications/management.html:143
@@ -1422,10 +1450,6 @@ msgstr ""
msgid "Code Name"
msgstr ""
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:35
msgid "Users"
msgstr ""
#: allianceauth/permissions_tool/templates/permissions_tool/overview.html:41
msgid "States"
msgstr ""
@@ -2146,11 +2170,11 @@ msgid ""
msgstr ""
#: allianceauth/templates/allianceauth/admin-status/overview.html:95
#, python-format
msgid ""
"\n"
" %(queue_length)s queued tasks\n"
" "
msgid "running"
msgstr ""
#: allianceauth/templates/allianceauth/admin-status/overview.html:96
msgid "queued"
msgstr ""
#: allianceauth/templates/allianceauth/top-menu-admin.html:9
@@ -2166,11 +2190,11 @@ msgid "AA Support Discord"
msgstr ""
#: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:10
#: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:14
#: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:16
msgid "User Menu"
msgstr ""
#: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:56
#: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:67
msgid "Logout"
msgstr ""
@@ -2226,22 +2250,30 @@ msgid "Objective"
msgstr ""
#: allianceauth/timerboard/form.py:64
msgid "Days Remaining"
msgid "Absolute Timer"
msgstr ""
#: allianceauth/timerboard/form.py:65
msgid "Hours Remaining"
msgid "Date and Time"
msgstr ""
#: allianceauth/timerboard/form.py:66
msgid "Days Remaining"
msgstr ""
#: allianceauth/timerboard/form.py:67
msgid "Minutes Remaining"
msgid "Hours Remaining"
msgstr ""
#: allianceauth/timerboard/form.py:69
msgid "Minutes Remaining"
msgstr ""
#: allianceauth/timerboard/form.py:71
msgid "Important"
msgstr ""
#: allianceauth/timerboard/form.py:70
#: allianceauth/timerboard/form.py:72
msgid "Corp-Restricted"
msgstr ""

View File

@@ -4,11 +4,11 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# frank1210 <francolopez_16@hotmail.com>, 2021
# Joel Falknau <ozirascal@gmail.com>, 2021
# Young Anexo, 2023
# Fegpawn Kaundur, 2023
# frank1210 <francolopez_16@hotmail.com>, 2023
# trenus, 2023
# Joel Falknau <ozirascal@gmail.com>, 2023
# Young Anexo, 2023
#
#, fuzzy
msgid ""
@@ -16,8 +16,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-10-09 18:20+1000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
"Last-Translator: trenus, 2023\n"
"PO-Revision-Date: 2023-10-08 09:23+0000\n"
"Last-Translator: Young Anexo, 2023\n"
"Language-Team: Spanish (https://app.transifex.com/alliance-auth/teams/107430/es/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"

View File

@@ -4,14 +4,14 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# François LACROIX-DURANT <umbre@fallenstarscreations.com>, 2020
# Philippe Querin-Laporte <philippe.querin@hotmail.com>, 2020
# Keven D. <theenarki@gmail.com>, 2020
# Idea ., 2021
# Mickael PATTE, 2021
# Geoffrey Fabbro, 2021
# Keven D. <theenarki@gmail.com>, 2023
# rockclodbuster, 2023
# Geoffrey Fabbro, 2023
# Mohssine Daghghar, 2023
# Ludovick Fortin, 2023
# François LACROIX-DURANT <umbre@fallenstarscreations.com>, 2023
# Mickael PATTE, 2023
# Philippe Querin-Laporte <philippe.querin@hotmail.com>, 2023
# Idea ., 2023
#
#, fuzzy
msgid ""
@@ -19,8 +19,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-10-09 18:20+1000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
"Last-Translator: Ludovick Fortin, 2023\n"
"PO-Revision-Date: 2023-10-08 09:23+0000\n"
"Last-Translator: Idea ., 2023\n"
"Language-Team: French (France) (https://app.transifex.com/alliance-auth/teams/107430/fr_FR/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"

File diff suppressed because it is too large Load Diff

View File

@@ -4,8 +4,9 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# Foch Petain <brigadier.rockforward@gmail.com>, 2020
# Foch Petain <brigadier.rockforward@gmail.com>, 2023
# kotaneko, 2023
# Joel Falknau <ozirascal@gmail.com>, 2023
#
#, fuzzy
msgid ""
@@ -13,8 +14,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-10-09 18:20+1000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
"Last-Translator: kotaneko, 2023\n"
"PO-Revision-Date: 2023-10-08 09:23+0000\n"
"Last-Translator: Joel Falknau <ozirascal@gmail.com>, 2023\n"
"Language-Team: Japanese (https://app.transifex.com/alliance-auth/teams/107430/ja/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"

View File

@@ -4,13 +4,13 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# None None <khd1226543@gmail.com>, 2020
# Seowon Jung <seowon@hawaii.edu>, 2020
# Olgeda Choi <undead.choi@gmail.com>, 2020
# Lahty <js03js70@gmail.com>, 2020
# Joel Falknau <ozirascal@gmail.com>, 2020
# ThatRagingKid, 2022
# jackfrost, 2022
# None None <khd1226543@gmail.com>, 2023
# Joel Falknau <ozirascal@gmail.com>, 2023
# Seowon Jung <seowon@hawaii.edu>, 2023
# Olgeda Choi <undead.choi@gmail.com>, 2023
# ThatRagingKid, 2023
# Lahty <js03js70@gmail.com>, 2023
# jackfrost, 2023
#
#, fuzzy
msgid ""
@@ -18,8 +18,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-10-09 18:20+1000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
"Last-Translator: jackfrost, 2022\n"
"PO-Revision-Date: 2023-10-08 09:23+0000\n"
"Last-Translator: jackfrost, 2023\n"
"Language-Team: Korean (Korea) (https://app.transifex.com/alliance-auth/teams/107430/ko_KR/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"

View File

@@ -4,9 +4,9 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# Alexander Gess <de.alex.gess@gmail.com>, 2020
# Yuriy K <thedjcooltv@gmail.com>, 2020
# Андрей Зубков <and.vareba81@gmail.com>, 2020
# Yuriy K <thedjcooltv@gmail.com>, 2023
# Андрей Зубков <and.vareba81@gmail.com>, 2023
# Alexander Gess <de.alex.gess@gmail.com>, 2023
# Filipp Chertiev <f@fzfx.ru>, 2023
#
#, fuzzy
@@ -15,7 +15,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-10-09 18:20+1000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
"PO-Revision-Date: 2023-10-08 09:23+0000\n"
"Last-Translator: Filipp Chertiev <f@fzfx.ru>, 2023\n"
"Language-Team: Russian (https://app.transifex.com/alliance-auth/teams/107430/ru/)\n"
"MIME-Version: 1.0\n"

View File

@@ -4,6 +4,7 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# Denys Ivchenko, 2023
# Kristof Swensen, 2023
#
#, fuzzy
@@ -12,7 +13,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-10-09 18:20+1000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
"PO-Revision-Date: 2023-10-08 09:23+0000\n"
"Last-Translator: Kristof Swensen, 2023\n"
"Language-Team: Ukrainian (https://app.transifex.com/alliance-auth/teams/107430/uk/)\n"
"MIME-Version: 1.0\n"
@@ -32,7 +33,7 @@ msgstr "Google Analytics V4"
#: allianceauth/authentication/decorators.py:37
msgid "A main character is required to perform that action. Add one below."
msgstr ""
"Для виконання цієї дії потрібен головний персонаж. Додайте його нижче."
"Для виконання цієї дії потрібен основний персонаж. Додайте його нижче."
#: allianceauth/authentication/forms.py:12
msgid "Email"
@@ -124,7 +125,7 @@ msgstr "Додати персонажа"
#: allianceauth/authentication/templates/authentication/dashboard.html:115
msgid "Change Main"
msgstr "Змінити головного персонажа"
msgstr "Змінити основного персонажа"
#: allianceauth/authentication/templates/authentication/dashboard.html:125
msgid "Group Memberships"
@@ -352,7 +353,7 @@ msgstr "Не вдалося зібрати статистику корпорац
#: allianceauth/fleetactivitytracking/auth_hooks.py:9
msgid "Fleet Activity Tracking"
msgstr "Відстеження активності флоту"
msgstr "Відстеження активності флотів"
#: allianceauth/fleetactivitytracking/forms.py:6 allianceauth/srp/form.py:8
#: allianceauth/srp/templates/srp/management.html:35
@@ -456,7 +457,7 @@ msgstr "Корабель"
#: allianceauth/timerboard/templates/timerboard/view.html:202
#: allianceauth/timerboard/templates/timerboard/view.html:375
msgid "Eve Time"
msgstr "Час в грі"
msgstr "Ігровий час"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkmodify.html:33
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkview.html:36
@@ -560,16 +561,16 @@ msgstr "Fats"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:4
msgid "Fatlink Corp Statistics"
msgstr "Статистика корпорації Fatlink"
msgstr "Статистика фатів корпорації"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticscorpview.html:23
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:24
msgid "Average fats"
msgstr "Середній показник fats"
msgstr "Середній показник фатів"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:4
msgid "Fatlink statistics"
msgstr "Статистика Fatlink"
msgstr "Статистика фатів"
#: allianceauth/fleetactivitytracking/templates/fleetactivitytracking/fatlinkstatisticsview.html:20
msgid "Ticker"
@@ -625,7 +626,7 @@ msgid ""
"Cannot register the fleet participation for {character.character_name}. The "
"character needs to be online."
msgstr ""
"Не можна зареєструвати участь в флоті для {character.character_name}. "
"Не вдалося зареєструвати участь в флоті для {character.character_name}. "
"Персонаж повинен бути в мережі."
#: allianceauth/groupmanagement/auth_hooks.py:17
@@ -659,8 +660,7 @@ msgstr ""
#: allianceauth/groupmanagement/models.py:113
msgid "Group is hidden from users but can still join with the correct link."
msgstr ""
"Група прихована від користувачів, але можна приєднатися з правильним "
"посиланням."
"Група прихована від користувачів, але можна приєднатися за посиланням."
#: allianceauth/groupmanagement/models.py:119
msgid ""
@@ -1045,7 +1045,7 @@ msgstr "Ви вже є членом цієї групи."
#: allianceauth/groupmanagement/views.py:358
msgid "You already have a pending application for that group."
msgstr "У вас вже є очікуюча заявка на вступ до цієї групи."
msgstr "Ви вже подали заявку на вступ до цієї групи."
#: allianceauth/groupmanagement/views.py:367
#, python-format
@@ -1062,7 +1062,7 @@ msgstr "Ви не є учасником цієї групи"
#: allianceauth/groupmanagement/views.py:393
msgid "You already have a pending leave request for that group."
msgstr "Ви вже маєте очікувану запит на вихід з цієї групи."
msgstr "Ви вже подали запит на вихід з цієї групи."
#: allianceauth/groupmanagement/views.py:409
#, python-format
@@ -1321,7 +1321,7 @@ msgstr "Всі прочитані повідомлення видалено."
#: allianceauth/optimer/auth_hooks.py:10
msgid "Fleet Operations"
msgstr "Операції флоту"
msgstr "Флотові операції"
#: allianceauth/optimer/form.py:12
#: allianceauth/optimer/templates/optimer/fleetoptable.html:11
@@ -1345,7 +1345,7 @@ msgstr "Тип операції"
#: allianceauth/optimer/form.py:17
#: allianceauth/srp/templates/srp/management.html:38
msgid "Fleet Commander"
msgstr "Командувач флоту"
msgstr "Командир флоту"
#: allianceauth/optimer/form.py:22 allianceauth/srp/form.py:14
#: allianceauth/srp/templates/srp/data.html:91
@@ -1400,7 +1400,7 @@ msgstr "Немає наступних таймерів."
#: allianceauth/optimer/templates/optimer/management.html:33
msgid "Past Fleet Operations"
msgstr "Минулі флотові операції"
msgstr "Завершені флотові операції"
#: allianceauth/optimer/templates/optimer/management.html:37
#: allianceauth/timerboard/templates/timerboard/view.html:535
@@ -1484,7 +1484,7 @@ msgstr "Стани"
#: allianceauth/services/abstract.py:72
msgid "That service account already exists"
msgstr "Такий обліковий запис сервісу вже існує"
msgstr "Такий сервісний обліковий запис вже існує"
#: allianceauth/services/abstract.py:103
#, python-brace-format
@@ -1505,7 +1505,7 @@ msgstr "Командир флоту:"
#: allianceauth/services/forms.py:8
msgid "Fleet Comms:"
msgstr "Комунікації флоту:"
msgstr "Голосовий канал флоту:"
#: allianceauth/services/forms.py:9
msgid "Fleet Type:"
@@ -1545,7 +1545,7 @@ msgstr "Ні"
#: allianceauth/services/forms.py:16
msgid "Important?*"
msgstr "Важливо?*"
msgstr "Важливий?*"
#: allianceauth/services/forms.py:21 allianceauth/services/forms.py:31
msgid "Password"
@@ -1614,7 +1614,7 @@ msgstr "Ви не маєте прав на доступ до Discourse."
#: allianceauth/services/modules/discourse/views.py:34
msgid "You must have a main character set to access Discourse."
msgstr "Ви повинні мати головний персонаж, щоб отримати доступ до Discourse."
msgstr "Ви повинні мати основний персонаж, щоб отримати доступ до Discourse."
#: allianceauth/services/modules/discourse/views.py:44
msgid ""
@@ -1702,7 +1702,7 @@ msgstr "Відправлено трансляцію Jabber на %s"
#: allianceauth/services/modules/openfire/views.py:144
msgid "Set jabber password."
msgstr "Встановлення пароля Jabber."
msgstr "Встановити пароль Jabber."
#: allianceauth/services/modules/phpbb3/views.py:34
msgid "Activated forum account."
@@ -1713,7 +1713,7 @@ msgstr "Активований обліковий запис форуму."
#: allianceauth/services/modules/phpbb3/views.py:78
#: allianceauth/services/modules/phpbb3/views.py:101
msgid "An error occurred while processing your forum account."
msgstr "Виникла помилка під час обробки вашого облікового запису форуму."
msgstr "Виникла помилка під час обробки вашого облікового запису на форумі."
#: allianceauth/services/modules/phpbb3/views.py:53
msgid "Deactivated forum account."
@@ -1721,11 +1721,11 @@ msgstr "Деактивований обліковий запис форуму."
#: allianceauth/services/modules/phpbb3/views.py:70
msgid "Reset forum password."
msgstr "Скидання пароля форуму."
msgstr "Скинути пароль форуму."
#: allianceauth/services/modules/phpbb3/views.py:98
msgid "Set forum password."
msgstr "Встановлення пароля форуму."
msgstr "Встановити пароль форуму."
#: allianceauth/services/modules/smf/views.py:52
msgid "Activated SMF account."
@@ -1744,11 +1744,11 @@ msgstr "Деактивований обліковий запис SMF."
#: allianceauth/services/modules/smf/views.py:95
msgid "Reset SMF password."
msgstr "Скидання пароля SMF."
msgstr "Скинути пароль SMF."
#: allianceauth/services/modules/smf/views.py:121
msgid "Set SMF password."
msgstr "Встановлення пароля SMF."
msgstr "Встановити пароль SMF."
#: allianceauth/services/modules/teamspeak3/forms.py:14
#, python-format
@@ -1761,7 +1761,7 @@ msgstr "Оновити групи TS3"
#: allianceauth/services/modules/teamspeak3/templates/services/teamspeak3/teamspeakjoin.html:5
msgid "Verify Teamspeak"
msgstr "Перевірте Teamspeak"
msgstr "Перевірити Teamspeak"
#: allianceauth/services/modules/teamspeak3/templates/services/teamspeak3/teamspeakjoin.html:10
msgid "Verify Teamspeak Identity"
@@ -1869,11 +1869,11 @@ msgstr "Керування послугами"
#: allianceauth/services/templates/services/services.html:9
msgid "Available Services"
msgstr "Доступні послуги"
msgstr "Доступні сервіси"
#: allianceauth/services/templates/services/services.html:14
msgid "Service"
msgstr "Послуга"
msgstr "Сервіс"
#: allianceauth/services/templates/services/services.html:16
msgid "Domain"
@@ -1881,7 +1881,7 @@ msgstr "Домен"
#: allianceauth/srp/auth_hooks.py:13
msgid "Ship Replacement"
msgstr "Компенсація за корабель"
msgstr "Компенсації"
#: allianceauth/srp/form.py:9
#: allianceauth/srp/templates/srp/management.html:36

View File

@@ -4,9 +4,10 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# Joel Falknau <ozirascal@gmail.com>, 2020
# Jesse . <sgeine@hotmail.com>, 2020
# Aaron BuBu <351793078@qq.com>, 2020
# Jesse . <sgeine@hotmail.com>, 2023
# Aaron BuBu <351793078@qq.com>, 2023
# Joel Falknau <ozirascal@gmail.com>, 2023
# Shen Yang, 2023
#
#, fuzzy
msgid ""
@@ -14,8 +15,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-10-09 18:20+1000\n"
"PO-Revision-Date: 2020-02-18 03:14+0000\n"
"Last-Translator: Aaron BuBu <351793078@qq.com>, 2020\n"
"PO-Revision-Date: 2023-10-08 09:23+0000\n"
"Last-Translator: Shen Yang, 2023\n"
"Language-Team: Chinese Simplified (https://app.transifex.com/alliance-auth/teams/107430/zh-Hans/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -46,48 +47,48 @@ msgstr ""
#: allianceauth/authentication/models.py:80
msgid "English"
msgstr ""
msgstr "英语"
#: allianceauth/authentication/models.py:81
msgid "German"
msgstr ""
msgstr "德语"
#: allianceauth/authentication/models.py:82
msgid "Spanish"
msgstr ""
msgstr "西班牙语"
#: allianceauth/authentication/models.py:83
msgid "Chinese Simplified"
msgstr ""
msgstr "简体中文"
#: allianceauth/authentication/models.py:84
msgid "Russian"
msgstr ""
msgstr "俄语"
#: allianceauth/authentication/models.py:85
msgid "Korean"
msgstr ""
msgstr "韩语"
#: allianceauth/authentication/models.py:86
msgid "French"
msgstr ""
msgstr "法语"
#: allianceauth/authentication/models.py:87
msgid "Japanese"
msgstr ""
msgstr "日语"
#: allianceauth/authentication/models.py:88
msgid "Italian"
msgstr ""
msgstr "意大利语"
#: allianceauth/authentication/models.py:91
msgid "Language"
msgstr ""
msgstr "语言"
#: allianceauth/authentication/models.py:96
#: allianceauth/templates/allianceauth/night-toggle.html:6
msgid "Night Mode"
msgstr ""
msgstr "夜间模式"
#: allianceauth/authentication/models.py:110
#, python-format
@@ -696,7 +697,7 @@ msgstr ""
#: allianceauth/groupmanagement/models.py:215
msgid "reason"
msgstr ""
msgstr "原因"
#: allianceauth/groupmanagement/models.py:215
msgid "Reason why this name is reserved."
@@ -754,7 +755,7 @@ msgstr "操作者"
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:48
msgid "Removed"
msgstr ""
msgstr "已移除"
#: allianceauth/groupmanagement/templates/groupmanagement/audit.html:60
msgid "All times displayed are EVE/UTC."
@@ -1198,11 +1199,11 @@ msgstr "添加评论"
#: allianceauth/notifications/models.py:21
msgid "danger"
msgstr ""
msgstr "危险"
#: allianceauth/notifications/models.py:22
msgid "warning"
msgstr ""
msgstr "警告"
#: allianceauth/notifications/models.py:23
msgid "info"
@@ -1343,7 +1344,7 @@ msgstr "当前EVE游戏内时间"
#: allianceauth/optimer/templates/optimer/management.html:26
msgid "Next Fleet Operations"
msgstr ""
msgstr "下一个舰队任务"
#: allianceauth/optimer/templates/optimer/management.html:30
#: allianceauth/timerboard/templates/timerboard/view.html:362
@@ -1352,7 +1353,7 @@ msgstr "没有快到的时间节点,歇一会吧"
#: allianceauth/optimer/templates/optimer/management.html:33
msgid "Past Fleet Operations"
msgstr ""
msgstr "过去的舰队任务"
#: allianceauth/optimer/templates/optimer/management.html:37
#: allianceauth/timerboard/templates/timerboard/view.html:535
@@ -2257,15 +2258,15 @@ msgstr ""
#: allianceauth/timerboard/models.py:15
msgid "Shield"
msgstr ""
msgstr "护盾"
#: allianceauth/timerboard/models.py:16
msgid "Armor"
msgstr ""
msgstr "装甲"
#: allianceauth/timerboard/models.py:17
msgid "Hull"
msgstr ""
msgstr "结构"
#: allianceauth/timerboard/models.py:18
msgid "Final"
@@ -2273,11 +2274,11 @@ msgstr ""
#: allianceauth/timerboard/models.py:19
msgid "Anchoring"
msgstr ""
msgstr "铆钉"
#: allianceauth/timerboard/models.py:20
msgid "Unanchoring"
msgstr ""
msgstr "解锚"
#: allianceauth/timerboard/templates/timerboard/timer_confirm_delete.html:11
msgid "Delete Timer"

View File

@@ -3,6 +3,7 @@ import logging
from django.apps import AppConfig
from django.db.utils import ProgrammingError, OperationalError
logger = logging.getLogger(__name__)
@@ -12,8 +13,7 @@ class MenuConfig(AppConfig):
def ready(self):
try:
logger.debug("Syncing MenuItem Hooks")
from allianceauth.menu.providers import MenuItem
MenuItem.sync_hook_models()
from allianceauth.menu.providers import menu_provider
menu_provider.clear_synced_flag()
except (ProgrammingError, OperationalError):
logger.warning("Migrations not completed for MenuItems")

View File

@@ -0,0 +1,15 @@
from django.utils.deprecation import MiddlewareMixin
import logging
from allianceauth.menu.providers import menu_provider
logger = logging.getLogger(__name__)
class MenuSyncMiddleware(MiddlewareMixin):
def __call__(self, request):
"""Alliance Auth Menu Sync Middleware"""
menu_provider.check_and_sync_menu()
return super().__call__(request)

View File

@@ -144,7 +144,7 @@ class MenuItem(models.Model):
"render": _render,
"text": mi.text,
"rank": mi.rank,
"classes": (mi.icon_classes if mi.icon_classes != "" else "fas fa-folder"),
"classes": (mi.icon_classes if mi.icon_classes != "" else "fa-solid fa-folder"),
"hide": mi.hide
}

View File

@@ -1,10 +1,49 @@
from django.template.loader import render_to_string
import logging
from allianceauth.hooks import get_hooks
from django.core.cache import cache
from .models import MenuItem
from allianceauth.menu.models import MenuItem
from allianceauth.utils.django import StartupCommand
logger = logging.getLogger(__name__)
MENU_SYNC_CACHE_KEY = "ALLIANCEAUTH-MENU-SYNCED"
MENU_CACHE_KEY = "ALLIANCEAUTH-MENU-CACHE"
class MenuProvider():
def __init__(self) -> None:
def clear_synced_flag(self) -> bool:
return cache.delete(MENU_SYNC_CACHE_KEY)
def set_synced_flag(self) -> bool:
return cache.set(MENU_SYNC_CACHE_KEY, True)
def get_synced_flag(self) -> bool:
return cache.get(MENU_SYNC_CACHE_KEY, False)
def sync_menu_models(self):
MenuItem.sync_hook_models()
self.set_synced_flag()
def check_and_sync_menu(self) -> None:
if self.get_synced_flag():
# performance hit to each page view to ensure tests work.
# tests clear DB but not cache.
# TODO rethink all of this?
if MenuItem.objects.all().count() > 0:
logger.debug("Menu Hooks Synced")
else:
self.sync_menu_models()
else:
logger.debug("Syncing Menu Hooks")
self.sync_menu_models()
def get_and_cache_menu(self):
pass
def clear_menu_cache(self):
pass
menu_provider = MenuProvider()

View File

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

View File

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

View File

@@ -9,6 +9,7 @@
<div class="p-2 position-relative m-2">
<img class="rounded-circle" src="{{ main.character_id|character_portrait_url:64 }}" alt="{{ main.character_name }}">
<img class="rounded-circle position-absolute bottom-0 start-0" src="{{ main.corporation_logo_url_32 }}" alt="{{ main.corporation_name }}">
{% if main.alliance_id %}
<img class="rounded-circle position-absolute bottom-0 end-0" src="{{ main.alliance_logo_url_32 }}" alt="{{ main.alliance_name }}">
{% elif main.faction_id %}

View File

@@ -2,18 +2,19 @@
{% load navactive %}
{% load menu_menu_items %}
<div class="col-auto px-0 " >
<div class="collapse collapse-horizontal" tabindex="-1" id="sidebar" >
<div class="col-auto px-0">
<div class="collapse collapse-horizontal" tabindex="-1" id="sidebar">
<div style="width: 350px;">
<div class="nav-padding navbar-dark bg-dark text-light px-0 d-flex flex-column overflow-hidden vh-100 auth-logo" >
<div class="nav-padding navbar-dark bg-dark text-light px-0 d-flex flex-column overflow-hidden vh-100 auth-logo">
{% if user.is_authenticated %}
<ul style="z-index:5;" id="sidebar-menu" class="navbar-nav flex-column mb-auto overflow-auto pt-2">
<ul style="z-index:5;" id="sidebar-menu" class="navbar-nav flex-column mb-auto overflow-auto pt-2">
<li class="d-flex flex-wrap m-2 p-2 pt-0 pb-0 mt-0 mb-0 me-0 pe-0">
<i class="nav-link fas fa-tachometer-alt fa-fw align-self-center me-3 {% navactive request 'authentication:dashboard' %}"></i>
<a class="nav-link flex-fill align-self-center" href="{% url 'authentication:dashboard' %}">
{% translate "Dashboard" %}
</a>
</li>
{% sorted_menu_items %}
</ul>
{% endif %}

View File

@@ -3,7 +3,6 @@ from django import template
from allianceauth.hooks import get_hooks
from allianceauth.menu.models import MenuItem
from ..providers import MenuProvider
register = template.Library()

View File

@@ -1,4 +1,5 @@
{% extends "allianceauth/base-bs5.html" %}
{% load static %}
{% load i18n %}
@@ -17,6 +18,7 @@
<span class="badge bg-secondary">{{ unread|length }}</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" id="read-tab" data-bs-toggle="tab" data-bs-target="#read" type="button" role="tab" aria-controls="read" aria-selected="false">
{% translate "Read" %}
@@ -28,12 +30,13 @@
{% block header_nav_collapse_right %}
<li class="nav-item">
<a href="{% url 'notifications:mark_all_read' %}" class="nav-link" title="{% translate 'Mark all notifications as read' %}">
<i class="fas fa-check-double"></i>
<i class="fa-solid fa-check-double"></i>
</a>
</li>
<li class="nav-item">
<a href="{% url 'notifications:delete_all_read' %}" class="nav-link" title="{% translate 'Delete all read notifications' %}">
<i class="fas fa-trash"></i>
<i class="fa-solid fa-trash-can"></i>
</a>
</li>
{% endblock %}

View File

@@ -7,16 +7,18 @@
<th>{% translate "Title" %}</th>
<th class="text-end">{% translate "Action" %}</th>
</tr>
{% for notif in notifications %}
<tr class="table-{{ notif.level }}">
<td>{{ notif.timestamp }}</td>
<td>{{ notif.title }}</td>
<td class="text-end">
<a href="{% url 'notifications:view' notif.id %}" class="btn btn-primary btn-sm" title="View">
<span class="fas fa-eye"></span>
<span class="fa-solid fa-eye"></span>
</a>
<a href="{% url 'notifications:remove' notif.id %}" class="btn btn-danger btn-sm" title="Remove">
<span class="fas fa-trash"></span>
<span class="fa-solid fa-trash-can"></span>
</a>
</td>
</tr>

View File

@@ -10,7 +10,7 @@ class OpTimerboardMenu(MenuItemHook):
def __init__(self):
MenuItemHook.__init__(
self, _('Fleet Operations'),
'fas fa-exclamation fa-fw',
'fa-solid fa-exclamation',
'optimer:view',
navactive=['optimer:']
)
@@ -32,7 +32,7 @@ def register_url():
class NextOpsHook(hooks.DashboardItemHook):
def __init__(self): #TODO add the view permms so if they cant see it is not rendered
def __init__(self): #TODO add the view perms so if they cant see it is not rendered
hooks.DashboardItemHook.__init__(
self,
dashboard_ops,

View File

@@ -3,6 +3,7 @@ Form Widgets
"""
from django import forms
from django.utils.safestring import mark_safe
class DataListWidget(forms.TextInput):
@@ -42,4 +43,4 @@ class DataListWidget(forms.TextInput):
data_list += "</datalist>"
return text_html + data_list
return mark_safe(text_html + data_list)

View File

@@ -1,47 +1,64 @@
{% extends "allianceauth/base.html" %}
{% load bootstrap %}
{% extends "allianceauth/base-bs5.html" %}
{% load django_bootstrap5 %}
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
{% block page_title %}{% translate "Create Operation" %}{% endblock page_title %}
{% block page_title %}
{% translate "Create Operation" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "Fleet Operation Timers" %}
{% endblock header_nav_brand %}
{% block extra_css %}
{% include 'bundles/jquery-datetimepicker-css.html' %}
{% endblock extra_css %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "Create Fleet Operation" %}</h1>
<div>
{% translate "Create Fleet Operation" as page_header %}
{% include "framework/header/page-header.html" with title=page_header %}
<div class="container-fluid">
<div class="col-md-4 col-md-offset-4">
<div class="row">
<form class="form-signin" role="form" action="" method="POST">
<div class="card card-primary border-0">
<div class="card-header">
<div class="card-title mb-0">
{% translate "Fleet operation details" %}
</div>
</div>
<div class="card-body">
<div class="row justify-content-center">
<div class="col-md-6">
<form role="form" action="" method="POST">
{% csrf_token %}
{{ form|bootstrap }}
<br>
<button class="btn btn-lg btn-primary btn-block" type="submit">{% translate "Create Fleet Operation" %}</button>
{% bootstrap_form form %}
<div class="form-group mt-3 clearfix">
{% translate "Create fleet operation" as button_text %}
{% bootstrap_button button_class="btn btn-primary" content=button_text %}
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
{% block extra_javascript %}
{% include 'bundles/jquery-datetimepicker-js.html' %}
{% endblock %}
{% block extra_script %}
$('#id_start').datetimepicker({
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 %}
<script>
$(document).ready(() => {
$('#id_start').datetimepicker({
setlocale: '{{ LANGUAGE_CODE }}',
mask: true,
format: 'Y-m-d H:i',
minDate: 0
});
});
</script>
{% endblock %}

View File

@@ -1,10 +1,11 @@
{% load i18n %}
{% load evelinks %}
<div class="col-12 col-xl-6 align-self-stretch p-2">
<div class="col-12 align-self-stretch py-2">
<div class="card h-100">
<div class="card-body">
<h4 class="card-title text-center">{% translate "Upcoming Fleets" %}</h4>
<div class="card-body">
<div style="height: 300px; overflow-y:auto;">
<table class="table">
@@ -16,22 +17,23 @@
<th class="text-center">{% translate "Start Time" %}</th>
</tr>
</thead>
<tbody>
{% for ops in timers %}
<tr>
<td class="text-center">
{{ ops.operation_name }}
</td>
<td class="text-center">
({{ ops.type }})
</td>
<td class="text-center">
<a href="{{ ops.system|dotlan_solar_system_url }}">{{ ops.system }}</a>
</td>
<td class="text-center" nowrap>{{ ops.start | date:"Y-m-d H:i" }}</td>
</tr>
{% endfor %}
</tbody>
{% for ops in timers %}
<tr>
<td class="text-center">
{{ ops.operation_name }}
</td>
<td class="text-center">
{{ ops.type }}
</td>
<td class="text-center">
<a href="{{ ops.system|dotlan_solar_system_url }}">{{ ops.system }}</a>
</td>
<td class="text-center" nowrap>{{ ops.start | date:"Y-m-d H:i" }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>

View File

@@ -14,17 +14,20 @@
<th>{% translate "Local Time" %}</th>
<th>{% translate "Duration" %}</th>
<th>{% translate "FC" %}</th>
{% if perms.auth.optimer_management %}
{# <th>{% translate "Creator" %}</th>#}
<th class="text-end" style="width: 150px;">{% translate "Action" %}</th>
{% endif %}
</tr>
</thead>
{% for ops in timers %}
<tbody>
<tr>
<td>
{{ ops.operation_name }}
{% if ops.type %}
<br>({{ ops.type }})
{% endif %}
@@ -38,15 +41,16 @@
<td nowrap><div id="localtime{{ ops.id }}"></div><div id="countdown{{ ops.id }}"></div></td>
<td>{{ ops.duration }}</td>
<td>{{ ops.fc }}</td>
{% if perms.auth.optimer_management %}
{# <td>{{ ops.eve_character }}</td>#}
<td class="text-end">
<a href="{% url 'optimer:remove' ops.id %}" class="btn btn-danger">
<span class="glyphicon glyphicon-remove"></span>
<i class="fa-solid fa-trash-can"></i>
</a>
<a href="{% url 'optimer:edit' ops.id %}" class="btn btn-info">
<span class="glyphicon glyphicon-pencil"></span>
<i class="fa-solid fa-pen-to-square"></i>
</a>
</td>
{% endif %}

View File

@@ -1,41 +1,62 @@
{% extends "allianceauth/base.html" %}
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
{% block page_title %}{% translate "Fleet Operation Management" %}{% endblock page_title %}
{% block extra_css %}{% endblock extra_css %}
{% block page_title %}
{% translate "Fleet Operation Management" %}
{% endblock page_title %}
{% block header_nav_brand %}
{% translate "Fleet Operation Timers" %}
{% endblock header_nav_brand %}
{% block content %}
<div class="col-lg-12">
<h1 class="page-header text-center">{% translate "Fleet Operation Timers" %}
<div class="text-end">
{% if perms.auth.optimer_management %}
<a href="{% url 'optimer:add' %}" class="btn btn-success">{% translate "Create Operation" %}</a>
{% endif %}
</div>
</h1>
<div class="col-lg-12 text-center row">
<div class="badge bg-info text-start">
<b>{% translate "Current Eve Time:" %} </b>
</div>
<strong class="badge bg-info text-start" id="current-time"></strong>
<br>
<div>
<div class="text-end">
{% if perms.auth.optimer_management %}
<a href="{% url 'optimer:add' %}" class="btn btn-success">{% translate "Create Operation" %}</a>
{% endif %}
</div>
<h4><b>{% translate "Next Fleet Operations" %}</b></h4>
{% if future_timers %}
{% include "optimer/fleetoptable.html" with timers=future_timers %}
{% else %}
<div class="alert alert-warning text-center">{% translate "No upcoming timers." %}</div>
{% endif %}
<div class="text-center mb-3">
<div class="badge bg-info text-start">
<b>{% translate "Current Eve Time:" %}</b>
<span id="current-time"></span>
</div>
</div>
<h4><b>{% translate "Past Fleet Operations" %}</b></h4>
{% if past_timers %}
{% include "optimer/fleetoptable.html" with timers=past_timers %}
{% else %}
<div class="alert alert-warning text-center">{% translate "No past timers." %}</div>
{% endif %}
<div class="card mb-3">
<div class="card-header">
<div class="card-title mb-0">
{% translate "Next Fleet Operations" %}
</div>
</div>
<div class="card-body">
{% if future_timers %}
{% include "optimer/fleetoptable.html" with timers=future_timers %}
{% else %}
<div class="alert alert-warning text-center">{% translate "No upcoming timers." %}</div>
{% endif %}
</div>
</div>
<div class="card mb-3">
<div class="card-header">
<div class="card-title mb-0">
{% translate "Past Fleet Operations" %}
</div>
</div>
<div class="card-body">
{% if past_timers %}
{% include "optimer/fleetoptable.html" with timers=past_timers %}
{% else %}
<div class="alert alert-warning text-center">{% translate "No past timers." %}</div>
{% endif %}
</div>
</div>
</div>
{% include 'bundles/moment-js.html' with locale=True %}
@@ -43,23 +64,23 @@
<script>
// Data
let timers = [
{% for op in optimer %}
{
'id': {{ op.id }},
'start': moment("{{ op.start | date:"c" }}"),
'expired': false
},
{% endfor %}
const timers = [
{% for op in optimer %}
{
'id': {{ op.id }},
'start': moment("{{ op.start | date:"c" }}"),
'expired': false
},
{% endfor %}
];
/**
* Update a timer
* @param timer Timer information
*/
let updateTimer = function (timer) {
const updateTimer = (timer) => {
if (timer.start.isAfter(Date.now())) {
let duration = moment.duration(timer.start - moment(), 'milliseconds');
const duration = moment.duration(timer.start - moment(), 'milliseconds');
document.getElementById("countdown" + timer.id).innerHTML = getDurationString(duration);
} else {
@@ -69,10 +90,13 @@
}
};
let updateAllTimers = function () {
let l = timers.length;
/**
* Update all timers
*/
const updateAllTimers = () => {
const l = timers.length;
for (var i=0; i < l; ++i) {
for (let i=0; i < l; ++i) {
if (timers[i].expired) continue;
updateTimer(timers[i]);
@@ -83,26 +107,30 @@
* Set the local time info for the timer
* @param timer Timer information
*/
let setLocalTime = function (timer) {
const setLocalTime = (timer) => {
document.getElementById("localtime" + timer.id).innerHTML = timer.start.format("ddd @ LT");
};
/**
* Set all local time fields
*/
let setAllLocalTimes = function () {
let l = timers.length;
const setAllLocalTimes = () => {
const l = timers.length;
for (var i=0; i < l; ++i) {
for (let i=0; i < l; ++i) {
setLocalTime(timers[i]);
}
};
let updateClock = function () {
/**
* Get the current Eve time as a string
* @returns {string} Eve time string
*/
const updateClock = () => {
document.getElementById("current-time").innerHTML = getCurrentEveTimeString();
};
let timedUpdate = function () {
const timedUpdate = () => {
updateClock();
updateAllTimers();
};

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