aa-fleetfinder 2.6.1__py3-none-any.whl → 2.7.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of aa-fleetfinder might be problematic. Click here for more details.

Files changed (46) hide show
  1. {aa_fleetfinder-2.6.1.dist-info → aa_fleetfinder-2.7.1.dist-info}/METADATA +1 -1
  2. aa_fleetfinder-2.7.1.dist-info/RECORD +86 -0
  3. fleetfinder/__init__.py +1 -1
  4. fleetfinder/locale/cs_CZ/LC_MESSAGES/django.po +101 -27
  5. fleetfinder/locale/de/LC_MESSAGES/django.mo +0 -0
  6. fleetfinder/locale/de/LC_MESSAGES/django.po +106 -29
  7. fleetfinder/locale/django.pot +103 -28
  8. fleetfinder/locale/es/LC_MESSAGES/django.po +112 -27
  9. fleetfinder/locale/fr_FR/LC_MESSAGES/django.po +105 -27
  10. fleetfinder/locale/it_IT/LC_MESSAGES/django.po +98 -27
  11. fleetfinder/locale/ja/LC_MESSAGES/django.po +102 -27
  12. fleetfinder/locale/ko_KR/LC_MESSAGES/django.po +112 -27
  13. fleetfinder/locale/nl_NL/LC_MESSAGES/django.po +98 -27
  14. fleetfinder/locale/pl_PL/LC_MESSAGES/django.po +100 -27
  15. fleetfinder/locale/ru/LC_MESSAGES/django.mo +0 -0
  16. fleetfinder/locale/ru/LC_MESSAGES/django.po +116 -31
  17. fleetfinder/locale/sk/LC_MESSAGES/django.po +98 -27
  18. fleetfinder/locale/uk/LC_MESSAGES/django.mo +0 -0
  19. fleetfinder/locale/uk/LC_MESSAGES/django.po +116 -31
  20. fleetfinder/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  21. fleetfinder/locale/zh_Hans/LC_MESSAGES/django.po +116 -31
  22. fleetfinder/static/fleetfinder/css/fleetfinder.css +21 -0
  23. fleetfinder/static/fleetfinder/css/fleetfinder.min.css +1 -1
  24. fleetfinder/static/fleetfinder/css/fleetfinder.min.css.map +1 -1
  25. fleetfinder/static/fleetfinder/js/fleetfinder-dashboard.js +86 -0
  26. fleetfinder/static/fleetfinder/js/fleetfinder-dashboard.min.js +2 -0
  27. fleetfinder/static/fleetfinder/js/fleetfinder-dashboard.min.js.map +1 -0
  28. fleetfinder/static/fleetfinder/js/fleetfinder-fleet-details.js +154 -0
  29. fleetfinder/static/fleetfinder/js/fleetfinder-fleet-details.min.js +2 -0
  30. fleetfinder/static/fleetfinder/js/fleetfinder-fleet-details.min.js.map +1 -0
  31. fleetfinder/static/fleetfinder/js/fleetfinder.js +23 -0
  32. fleetfinder/static/fleetfinder/js/fleetfinder.min.js +2 -0
  33. fleetfinder/static/fleetfinder/js/fleetfinder.min.js.map +1 -0
  34. fleetfinder/tasks.py +32 -8
  35. fleetfinder/templates/fleetfinder/base.html +11 -0
  36. fleetfinder/templates/fleetfinder/bundles/js/fleetfinder-js.html +9 -0
  37. fleetfinder/templates/fleetfinder/dashboard.html +9 -109
  38. fleetfinder/templates/fleetfinder/fleet-details.html +28 -65
  39. fleetfinder/templates/fleetfinder/join-fleet.html +11 -1
  40. fleetfinder/templates/fleetfinder/modals/kick-fleet-member.html +46 -0
  41. fleetfinder/tests/test_views.py +130 -10
  42. fleetfinder/urls.py +5 -0
  43. fleetfinder/views.py +173 -45
  44. aa_fleetfinder-2.6.1.dist-info/RECORD +0 -75
  45. {aa_fleetfinder-2.6.1.dist-info → aa_fleetfinder-2.7.1.dist-info}/WHEEL +0 -0
  46. {aa_fleetfinder-2.6.1.dist-info → aa_fleetfinder-2.7.1.dist-info}/licenses/LICENSE +0 -0
@@ -4,25 +4,25 @@
4
4
  # Dehao Wu <wudehao2000@163.com>, 2024.
5
5
  # Faer Yili <yilifaer@gmail.com>, 2024.
6
6
  # SAM_FPS <sam_fps@163.com>, 2024.
7
- # Peter Pfeufer <info@ppfeufer.de>, 2024.
7
+ # Peter Pfeufer <info@ppfeufer.de>, 2024, 2025.
8
8
  msgid ""
9
9
  msgstr ""
10
10
  "Project-Id-Version: AA Fleet Finder 2.2.1\n"
11
11
  "Report-Msgid-Bugs-To: https://github.com/ppfeufer/aa-fleetfinder/issues\n"
12
- "POT-Creation-Date: 2025-08-19 17:07+0200\n"
13
- "PO-Revision-Date: 2024-06-06 14:27+0000\n"
12
+ "POT-Creation-Date: 2025-08-23 16:51+0200\n"
13
+ "PO-Revision-Date: 2025-08-21 13:16+0000\n"
14
14
  "Last-Translator: Peter Pfeufer <info@ppfeufer.de>\n"
15
- "Language-Team: Chinese (Simplified) <https://weblate.ppfeufer.de/projects/alliance-auth-apps/aa-fleetfinder/zh_Hans/>\n"
15
+ "Language-Team: Chinese (Simplified Han script) <https://weblate.ppfeufer.de/projects/alliance-auth-apps/aa-fleetfinder/zh_Hans/>\n"
16
16
  "Language: zh_Hans\n"
17
17
  "MIME-Version: 1.0\n"
18
18
  "Content-Type: text/plain; charset=UTF-8\n"
19
19
  "Content-Transfer-Encoding: 8bit\n"
20
20
  "Plural-Forms: nplurals=1; plural=0;\n"
21
- "X-Generator: Weblate 5.5.5\n"
21
+ "X-Generator: Weblate 5.13\n"
22
22
 
23
23
  #: fleetfinder/__init__.py:9 fleetfinder/models.py:24
24
- #: fleetfinder/templates/fleetfinder/base.html:6
25
- #: fleetfinder/templates/fleetfinder/base.html:10
24
+ #: fleetfinder/templates/fleetfinder/base.html:7
25
+ #: fleetfinder/templates/fleetfinder/base.html:11
26
26
  #: fleetfinder/templates/fleetfinder/create-fleet.html:7
27
27
  #: fleetfinder/templates/fleetfinder/edit-fleet.html:7
28
28
  #: fleetfinder/templates/fleetfinder/fleet-details.html:7
@@ -116,14 +116,6 @@ msgstr "创建于"
116
116
  msgid "Join"
117
117
  msgstr "加入"
118
118
 
119
- #: fleetfinder/templates/fleetfinder/dashboard.html:25
120
- msgid "Details"
121
- msgstr "细节"
122
-
123
- #: fleetfinder/templates/fleetfinder/dashboard.html:26
124
- msgid "Edit"
125
- msgstr "编辑"
126
-
127
119
  #: fleetfinder/templates/fleetfinder/edit-fleet.html:6
128
120
  #: fleetfinder/templates/fleetfinder/edit-fleet.html:14
129
121
  msgid "Edit fleet"
@@ -133,32 +125,51 @@ msgstr "编辑舰队"
133
125
  msgid "Fleet details"
134
126
  msgstr "舰队细节"
135
127
 
136
- #: fleetfinder/templates/fleetfinder/fleet-details.html:16
128
+ #: fleetfinder/templates/fleetfinder/fleet-details.html:20
137
129
  msgid "Fleet composition"
138
130
  msgstr "舰队组成"
139
131
 
140
- #: fleetfinder/templates/fleetfinder/fleet-details.html:25
141
- #: fleetfinder/templates/fleetfinder/fleet-details.html:51
132
+ #: fleetfinder/templates/fleetfinder/fleet-details.html:29
133
+ #: fleetfinder/templates/fleetfinder/fleet-details.html:55
142
134
  msgid "Ship class"
143
135
  msgstr "舰船等级"
144
136
 
145
- #: fleetfinder/templates/fleetfinder/fleet-details.html:26
137
+ #: fleetfinder/templates/fleetfinder/fleet-details.html:30
146
138
  msgid "Count"
147
139
  msgstr "计数"
148
140
 
149
- #: fleetfinder/templates/fleetfinder/fleet-details.html:41
141
+ #: fleetfinder/templates/fleetfinder/fleet-details.html:45
150
142
  msgid "Fleet members"
151
143
  msgstr "舰队成员"
152
144
 
153
- #: fleetfinder/templates/fleetfinder/fleet-details.html:50
145
+ #: fleetfinder/templates/fleetfinder/fleet-details.html:54
154
146
  msgid "Name"
155
147
  msgstr "名字"
156
148
 
157
- #: fleetfinder/templates/fleetfinder/fleet-details.html:52
149
+ #: fleetfinder/templates/fleetfinder/fleet-details.html:56
158
150
  msgid "System"
159
151
  msgstr "星系"
160
152
 
161
- #: fleetfinder/templates/fleetfinder/join-fleet.html:6 fleetfinder/views.py:132
153
+ #: fleetfinder/templates/fleetfinder/fleet-details.html:57
154
+ msgid "Action"
155
+ msgstr "行动"
156
+
157
+ #: fleetfinder/templates/fleetfinder/fleet-details.html:80
158
+ #, fuzzy
159
+ #| msgid "Fleet members"
160
+ msgid "Fleet boss"
161
+ msgstr "舰队成员"
162
+
163
+ #: fleetfinder/templates/fleetfinder/fleet-details.html:81
164
+ #: fleetfinder/templates/fleetfinder/modals/kick-fleet-member.html:10
165
+ msgid "Kick member from fleet"
166
+ msgstr ""
167
+
168
+ #: fleetfinder/templates/fleetfinder/fleet-details.html:82
169
+ msgid "An unknown error occurred."
170
+ msgstr ""
171
+
172
+ #: fleetfinder/templates/fleetfinder/join-fleet.html:6 fleetfinder/views.py:182
162
173
  msgid "Join fleet"
163
174
  msgstr "加入舰队"
164
175
 
@@ -166,14 +177,50 @@ msgstr "加入舰队"
166
177
  msgid "Fleet invitation"
167
178
  msgstr "舰队邀请"
168
179
 
169
- #: fleetfinder/templates/fleetfinder/join-fleet.html:25
170
- msgid "Select the characters to invite"
180
+ #: fleetfinder/templates/fleetfinder/join-fleet.html:22
181
+ msgid "Please ensure you don't have any CSPA charges set on your characters, as this will prevent fleet invites from being sent."
182
+ msgstr ""
183
+
184
+ #: fleetfinder/templates/fleetfinder/join-fleet.html:24
185
+ #, fuzzy
186
+ #| msgid "Select the characters to invite"
187
+ msgid "You can select multiple characters to invite them all at once."
171
188
  msgstr "选择要邀请的角色"
172
189
 
190
+ #: fleetfinder/templates/fleetfinder/join-fleet.html:28
191
+ msgid "The selected characters will receive a fleet invite in-game, which they can accept to join the fleet."
192
+ msgstr ""
193
+
173
194
  #: fleetfinder/templates/fleetfinder/join-fleet.html:35
195
+ #, fuzzy
196
+ #| msgid "Select the characters to invite"
197
+ msgid "Please select the characters you want to invite:"
198
+ msgstr "选择要邀请的角色"
199
+
200
+ #: fleetfinder/templates/fleetfinder/join-fleet.html:45
174
201
  msgid "Send fleet invites"
175
202
  msgstr "发送舰队邀请"
176
203
 
204
+ #: fleetfinder/templates/fleetfinder/modals/kick-fleet-member.html:13
205
+ msgid "Close"
206
+ msgstr ""
207
+
208
+ #: fleetfinder/templates/fleetfinder/modals/kick-fleet-member.html:18
209
+ msgid "Are you sure you want to kick this member from the fleet?"
210
+ msgstr ""
211
+
212
+ #: fleetfinder/templates/fleetfinder/modals/kick-fleet-member.html:27
213
+ msgid "Error"
214
+ msgstr ""
215
+
216
+ #: fleetfinder/templates/fleetfinder/modals/kick-fleet-member.html:36
217
+ msgid "Cancel"
218
+ msgstr "取消"
219
+
220
+ #: fleetfinder/templates/fleetfinder/modals/kick-fleet-member.html:41
221
+ msgid "Confirm"
222
+ msgstr "确认"
223
+
177
224
  #: fleetfinder/templates/fleetfinder/partials/body/form-fleet-details.html:15
178
225
  msgid "Select groups"
179
226
  msgstr "选择群组"
@@ -198,34 +245,72 @@ msgstr "加入我们的翻译团队吧!"
198
245
  msgid "Available fleets"
199
246
  msgstr "可用的舰队"
200
247
 
201
- #: fleetfinder/views.py:145
248
+ #: fleetfinder/views.py:193
202
249
  msgid "View fleet details"
203
250
  msgstr "查看船队详情"
204
251
 
205
- #: fleetfinder/views.py:154
252
+ #: fleetfinder/views.py:199
206
253
  msgid "Edit fleet advert"
207
254
  msgstr "编辑舰队宣传信息"
208
255
 
209
- #: fleetfinder/views.py:201
256
+ #: fleetfinder/views.py:244
210
257
  #, fuzzy, python-brace-format
211
258
  #| msgid "<h4>Error!</h4><p>ESI returned the following error: {esi_error_message}</p>"
212
259
  msgid "<h4>Error!</h4><p>There was an error creating the fleet: {error_detail}</p>"
213
260
  msgstr "<h4>错误!</h4><p>ESI返回如下错误:{esi_error_message}</p>"
214
261
 
215
- #: fleetfinder/views.py:241
262
+ #: fleetfinder/views.py:284 fleetfinder/views.py:474
216
263
  msgid "<h4>Error!</h4><p>Fleet does not exist or is no longer available.</p>"
217
264
  msgstr ""
218
265
 
219
- #: fleetfinder/views.py:395
266
+ #: fleetfinder/views.py:438
220
267
  #, fuzzy, python-brace-format
221
268
  #| msgid "<h4>Error!</h4><p>ESI returned the following error: {esi_error_message}</p>"
222
269
  msgid "<h4>Error!</h4><p>ESI returned the following error: {esi_error}</p>"
223
270
  msgstr "<h4>错误!</h4><p>ESI返回如下错误:{esi_error_message}</p>"
224
271
 
225
- #: fleetfinder/views.py:403
272
+ #: fleetfinder/views.py:446
226
273
  #, python-brace-format
227
274
  msgid "<h4>Error!</h4><p>There was an error creating the fleet: {ex}</p>"
228
275
  msgstr ""
229
276
 
277
+ #: fleetfinder/views.py:510
278
+ #, python-brace-format
279
+ msgid "Fleet with ID {fleet_id} does not exist."
280
+ msgstr ""
281
+
282
+ #: fleetfinder/views.py:516
283
+ #, python-brace-format
284
+ msgid "Error retrieving fleet composition: {ex}"
285
+ msgstr ""
286
+
287
+ #: fleetfinder/views.py:546
288
+ msgid "Method not allowed"
289
+ msgstr ""
290
+
291
+ #: fleetfinder/views.py:556
292
+ msgid "Member ID required"
293
+ msgstr ""
294
+
295
+ #: fleetfinder/views.py:575
296
+ #, fuzzy
297
+ #| msgid "Fleet invitation"
298
+ msgid "Fleet not found"
299
+ msgstr "舰队邀请"
300
+
301
+ #: fleetfinder/views.py:579
302
+ msgid "Invalid request data"
303
+ msgstr ""
304
+
305
+ #: fleetfinder/views.py:583
306
+ msgid "Member not found in fleet"
307
+ msgstr ""
308
+
309
+ #~ msgid "Details"
310
+ #~ msgstr "细节"
311
+
312
+ #~ msgid "Edit"
313
+ #~ msgstr "编辑"
314
+
230
315
  #~ msgid "Toggle navigation"
231
316
  #~ msgstr "切换导航"
@@ -7,4 +7,25 @@
7
7
  .aa-fleetfinder .table-vertical-middle td {
8
8
  vertical-align: middle;
9
9
  }
10
+
11
+ /* Slim Select
12
+ --------------------------------------------------------------------------------- */
13
+
14
+ .aa-fleetfinder .ss-main {
15
+ appearance: none;
16
+ background-clip: padding-box;
17
+ border: var(--bs-border-width) solid var(--bs-border-color);
18
+ border-radius: var(--bs-border-radius);
19
+ color: var(--bs-body-color);
20
+ font-size: 1rem;
21
+ font-weight: 400;
22
+ line-height: 1.5;
23
+ min-height: calc(1.5em + .75rem + 2px);
24
+ padding: .375rem .75rem;
25
+ transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
26
+ width: 100%;
27
+ }
28
+
29
+ /* END Slim Select
30
+ --------------------------------------------------------------------------------- */
10
31
  }
@@ -1,2 +1,2 @@
1
- @media all{.aa-fleetfinder .eve-character-portrait,.aa-fleetfinder .eve-type-icon{margin-right:.5rem}.aa-fleetfinder .table-vertical-middle td{vertical-align:middle}}
1
+ @media all{.aa-fleetfinder .eve-character-portrait,.aa-fleetfinder .eve-type-icon{margin-right:.5rem}.aa-fleetfinder .table-vertical-middle td{vertical-align:middle}.aa-fleetfinder .ss-main{appearance:none;background-clip:padding-box;border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);color:var(--bs-body-color);font-size:1rem;font-weight:400;line-height:1.5;min-height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;width:100%}}
2
2
  /*# sourceMappingURL=fleetfinder.min.css.map */
@@ -1 +1 @@
1
- {"version":3,"sources":["fleetfinder.css"],"names":[],"mappings":"AAAA,A,WACI,uC,CACA,8B,CACI,kB,CAGJ,yC,CACI,uB","file":"fleetfinder.css","sourcesContent":["@media all {\n .aa-fleetfinder .eve-character-portrait,\n .aa-fleetfinder .eve-type-icon {\n margin-right: 0.5rem;\n }\n\n .aa-fleetfinder .table-vertical-middle td {\n vertical-align: middle;\n }\n}\n"]}
1
+ {"version":3,"sources":["fleetfinder.css"],"names":[],"mappings":"AAAA,A,WACI,uC,CACA,8B,CACI,kB,CAGJ,yC,CACI,qB,CAMJ,wB,CACI,e,CACA,2B,CACA,0D,CACA,qC,CACA,0B,CACA,c,CACA,e,CACA,e,CACA,qC,CACA,sB,CACA,oE,CACA,Y","file":"fleetfinder.css","sourcesContent":["@media all {\n .aa-fleetfinder .eve-character-portrait,\n .aa-fleetfinder .eve-type-icon {\n margin-right: 0.5rem;\n }\n\n .aa-fleetfinder .table-vertical-middle td {\n vertical-align: middle;\n }\n\n /* Slim Select\n --------------------------------------------------------------------------------- */\n\n .aa-fleetfinder .ss-main {\n appearance: none;\n background-clip: padding-box;\n border: var(--bs-border-width) solid var(--bs-border-color);\n border-radius: var(--bs-border-radius);\n color: var(--bs-body-color);\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n min-height: calc(1.5em + .75rem + 2px);\n padding: .375rem .75rem;\n transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;\n width: 100%;\n }\n\n /* END Slim Select\n --------------------------------------------------------------------------------- */\n}\n"]}
@@ -0,0 +1,86 @@
1
+ /* global aaFleetFinderSettings, aaFleetFinderSettingsOverride, objectDeepMerge, fetchGet, fleetfinderBootstrapTooltip, DataTable */
2
+
3
+ $(document).ready(() => {
4
+ 'use strict';
5
+
6
+ const fleetFinderSettings = objectDeepMerge(aaFleetFinderSettings, aaFleetFinderSettingsOverride);
7
+
8
+ const table_fleet_overview = $('#table_available-fleets');
9
+ let dataTable = null;
10
+
11
+ /**
12
+ * Initialize or update the datatable.
13
+ * If the table already exists, it will be updated with new data.
14
+ * If it does not exist, a new DataTable will be created.
15
+ *
16
+ * @param {Object} data - The fleet data to populate the table.
17
+ */
18
+ const initializeOrUpdateTable = (data) => {
19
+ if (dataTable) {
20
+ // Update existing table
21
+ dataTable.clear().rows.add(data).draw();
22
+ } else {
23
+ // Initialize new table
24
+ dataTable = table_fleet_overview.DataTable({
25
+ language: {
26
+ url: fleetFinderSettings.dataTables.languageUrl
27
+ },
28
+ data: data,
29
+ columns: [
30
+ {
31
+ data: 'fleet_commander',
32
+ render: {
33
+ _: 'html',
34
+ sort: 'sort'
35
+ }
36
+ },
37
+ {
38
+ data: 'fleet_name'
39
+ },
40
+ {
41
+ data: 'created_at',
42
+ },
43
+ {
44
+ data: 'actions',
45
+ className: 'text-end',
46
+ },
47
+ ],
48
+ columnDefs: [
49
+ {
50
+ targets: 2,
51
+ render: DataTable.render.date(
52
+ fleetFinderSettings.dataTables.datetimeFormat
53
+ )
54
+ },
55
+ {
56
+ orderable: false,
57
+ targets: [3]
58
+ },
59
+ ],
60
+ order: [[0, 'asc']],
61
+ paging: false,
62
+ initComplete: () => {
63
+ // Initialize Bootstrap tooltips
64
+ fleetfinderBootstrapTooltip({selector: '#table_available-fleets'});
65
+ }
66
+ });
67
+ }
68
+ };
69
+
70
+ /**
71
+ * Fetch and update fleet data
72
+ */
73
+ const fetchFleetData = () => {
74
+ fetchGet({url: fleetFinderSettings.dataTables.url.dashboard})
75
+ .then(initializeOrUpdateTable)
76
+ .catch((error) => {
77
+ console.error('Error fetching fleet data:', error);
78
+ });
79
+ };
80
+
81
+ // Initial load
82
+ fetchFleetData();
83
+
84
+ // Refresh every 30 seconds
85
+ setInterval(fetchFleetData, 30000);
86
+ });
@@ -0,0 +1,2 @@
1
+ $(document).ready(()=>{'use strict';const e=objectDeepMerge(aaFleetFinderSettings,aaFleetFinderSettingsOverride),a=$('#table_available-fleets');let t=null;const r=r=>{t?t.clear().rows.add(r).draw():t=a.DataTable({language:{url:e.dataTables.languageUrl},data:r,columns:[{data:'fleet_commander',render:{_:'html',sort:'sort'}},{data:'fleet_name'},{data:'created_at'},{data:'actions',className:'text-end'}],columnDefs:[{targets:2,render:DataTable.render.date(e.dataTables.datetimeFormat)},{orderable:!1,targets:[3]}],order:[[0,'asc']],paging:!1,initComplete:()=>{fleetfinderBootstrapTooltip({selector:'#table_available-fleets'})}})},l=()=>{fetchGet({url:e.dataTables.url.dashboard}).then(r).catch(e=>{console.error('Error fetching fleet data:',e)})};l(),setInterval(l,3e4)});
2
+ //# sourceMappingURL=fleetfinder-dashboard.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["$","document","ready","fleetFinderSettings","objectDeepMerge","aaFleetFinderSettings","aaFleetFinderSettingsOverride","table_fleet_overview","dataTable","initializeOrUpdateTable","data","clear","rows","add","draw","DataTable","language","url","dataTables","languageUrl","columns","render","_","sort","className","columnDefs","targets","date","datetimeFormat","orderable","order","paging","initComplete","fleetfinderBootstrapTooltip","selector","fetchFleetData","fetchGet","dashboard","then","catch","error","console","setInterval"],"sources":["fleetfinder-dashboard.js"],"mappings":"AAEAA,EAAEC,UAAUC,MAAM,KACd,aAEA,MAAMC,EAAsBC,gBAAgBC,sBAAuBC,+BAE7DC,EAAuBP,EAAE,2BAC/B,IAAIQ,EAAY,KAShB,MAAMC,EAA2BC,IACzBF,EAEAA,EAAUG,QAAQC,KAAKC,IAAIH,GAAMI,OAGjCN,EAAYD,EAAqBQ,UAAU,CACvCC,SAAU,CACNC,IAAKd,EAAoBe,WAAWC,aAExCT,KAAMA,EACNU,QAAS,CACL,CACIV,KAAM,kBACNW,OAAQ,CACJC,EAAG,OACHC,KAAM,SAGd,CACIb,KAAM,cAEV,CACIA,KAAM,cAEV,CACIA,KAAM,UACNc,UAAW,aAGnBC,WAAY,CACR,CACIC,QAAS,EACTL,OAAQN,UAAUM,OAAOM,KACrBxB,EAAoBe,WAAWU,iBAGvC,CACIC,WAAW,EACXH,QAAS,CAAC,KAGlBI,MAAO,CAAC,CAAC,EAAG,QACZC,QAAQ,EACRC,aAAc,KAEVC,4BAA4B,CAACC,SAAU,gCASjDC,EAAiB,KACnBC,SAAS,CAACnB,IAAKd,EAAoBe,WAAWD,IAAIoB,YAC7CC,KAAK7B,GACL8B,MAAOC,IACJC,QAAQD,MAAM,6BAA8BA,MAKxDL,IAGAO,YAAYP,EAAgB","ignoreList":[]}
@@ -0,0 +1,154 @@
1
+ /* global objectDeepMerge, aaFleetFinderSettings, aaFleetFinderSettingsOverride, fetchGet, fetchPost, fleetfinderBootstrapTooltip */
2
+
3
+ $(document).ready(() => {
4
+ 'use strict';
5
+
6
+ const fleetFinderSettings = objectDeepMerge(aaFleetFinderSettings, aaFleetFinderSettingsOverride);
7
+
8
+ /* DataTables
9
+ ------------------------------------------------------------------------- */
10
+ const elements = {
11
+ tableFleetMembers: $('#table-fleet-members'),
12
+ tableFleetComposition: $('#table-fleet-composition'),
13
+ kickFleetMemberModal: $('#kick-fleet-member'),
14
+ kickFleetMemberCharacterName: $('#kick-fleet-member-character-name'),
15
+ modalButtonConfirmKickFleetMember: $('#modal-button-confirm-kick-fleet-member'),
16
+ warning: $('#fleetfinder-fleet-details-warning')
17
+ };
18
+ const dataTableConfig = {
19
+ language: {
20
+ url: fleetFinderSettings.dataTables.languageUrl
21
+ },
22
+ paging: false,
23
+ destroy: true
24
+ };
25
+
26
+ const populateDatatables = () => {
27
+ fetchGet({
28
+ url: fleetFinderSettings.dataTables.url.fleetDetails,
29
+ })
30
+ .then((data) => {
31
+ if (data.error) {
32
+ elements.warning.removeClass('d-none').text(data.error);
33
+
34
+ return;
35
+ }
36
+
37
+ elements.warning.addClass('d-none');
38
+
39
+ elements.tableFleetMembers.DataTable({
40
+ ...dataTableConfig,
41
+ data: data.fleet_member,
42
+ columns: [
43
+ {
44
+ render: (data, type, row) => {
45
+ const fwIcon = '<i class="fa-solid fa-star"></i>';
46
+
47
+ return row.is_fleet_boss ? `${row.character_name} <sup data-bs-tooltip="aa-fleetfinder" title="${fleetFinderSettings.l10n.fleetBoss}"><small>${fwIcon}</small></sup>` : row.character_name;
48
+ }
49
+ },
50
+ {data: 'ship_type_name'},
51
+ {data: 'solar_system_name'},
52
+ {
53
+ render: (data, type, row) => {
54
+ const fwIcon = '<i class="fa-solid fa-user-minus"></i>';
55
+ const dataAttributes = Object.entries({
56
+ 'data-character-id': row.character_id,
57
+ 'data-character-name': row.character_name,
58
+ 'data-bs-toggle': 'modal',
59
+ 'data-bs-target': '#kick-fleet-member',
60
+ 'data-bs-tooltip': 'aa-fleetfinder'
61
+ }).map(([key, value]) => {
62
+ return `${key}="${value}"`;
63
+ }).join(' ');
64
+
65
+ return row.is_fleet_boss ? '' : `<button type="button" class="btn btn-sm btn-danger" ${dataAttributes} title="${fleetFinderSettings.l10n.kickMemberFromFleet}">${fwIcon}</button>`;
66
+ },
67
+ orderable: false,
68
+ searchable: false,
69
+ width: '50px',
70
+ className: 'text-end'
71
+ }
72
+ ],
73
+ createdRow: (row, data, rowIndex) => {
74
+ $(row).attr('data-row-id', rowIndex);
75
+ $(row).attr('data-character-id', data.character_id);
76
+ },
77
+ initComplete: () => {
78
+ // Initialize Bootstrap tooltips
79
+ fleetfinderBootstrapTooltip({selector: '#table-fleet-members'});
80
+ }
81
+ });
82
+
83
+ elements.tableFleetComposition.DataTable({
84
+ ...dataTableConfig,
85
+ data: data.fleet_composition,
86
+ columns: [
87
+ {data: 'ship_type_name'},
88
+ {data: 'number', className: 'text-right', width: '100px'}
89
+ ],
90
+ order: [[1, 'desc']]
91
+ });
92
+ })
93
+ .catch((error) => {
94
+ console.error('Error fetching fleet details:', error);
95
+ });
96
+ };
97
+
98
+ populateDatatables();
99
+
100
+ setInterval(populateDatatables, 30000);
101
+
102
+ /* Modals
103
+ ------------------------------------------------------------------------- */
104
+ // Handle the kick fleet member modal
105
+ elements.kickFleetMemberModal
106
+ .on('show.bs.modal', (event) => {
107
+ const button = $(event.relatedTarget);
108
+ const characterId = button.data('character-id');
109
+ const characterName = button.data('character-name');
110
+ const link = fleetFinderSettings.dataTables.url.kickFleetMember;
111
+
112
+ // Populate the modal content
113
+ $('#kick-fleet-member-character-name').text(characterName);
114
+
115
+ $('#modal-button-confirm-kick-fleet-member')
116
+ // Remove any previous click handlers to avoid multiple bindings
117
+ .off('click.kickMember')
118
+ // Bind the click event for the confirmation button
119
+ .on('click.kickMember', () => {
120
+ fetchPost({
121
+ url: link,
122
+ csrfToken: fleetFinderSettings.csrfToken,
123
+ payload: {
124
+ memberId: characterId
125
+ },
126
+ responseIsJson: true
127
+ })
128
+ .then(() => {
129
+ populateDatatables();
130
+
131
+ $('#kick-fleet-member').modal('hide');
132
+ })
133
+ .catch((error) => {
134
+ console.error('Error kicking fleet member:', error);
135
+
136
+ $('#kick-fleet-member .modal-kick-fleet-member-error')
137
+ .removeClass('d-none')
138
+ .find('.modal-kick-fleet-member-error-message')
139
+ .text(error || fleetFinderSettings.l10n.unknownError);
140
+ });
141
+ });
142
+ })
143
+ .on('hide.bs.modal', () => {
144
+ // Reset modal content
145
+ $('#kick-fleet-member-character-name').empty();
146
+ $('#kick-fleet-member .modal-kick-fleet-member-error')
147
+ .addClass('d-none')
148
+ .find('.modal-kick-fleet-member-error-message')
149
+ .empty();
150
+
151
+ // Clean up event handler
152
+ $('#modal-button-confirm-kick-fleet-member').off('click.kickMember');
153
+ });
154
+ });
@@ -0,0 +1,2 @@
1
+ $(document).ready(()=>{'use strict';const e=objectDeepMerge(aaFleetFinderSettings,aaFleetFinderSettingsOverride),t={tableFleetMembers:$('#table-fleet-members'),tableFleetComposition:$('#table-fleet-composition'),kickFleetMemberModal:$('#kick-fleet-member'),kickFleetMemberCharacterName:$('#kick-fleet-member-character-name'),modalButtonConfirmKickFleetMember:$('#modal-button-confirm-kick-fleet-member'),warning:$('#fleetfinder-fleet-details-warning')},a={language:{url:e.dataTables.languageUrl},paging:!1,destroy:!0},r=()=>{fetchGet({url:e.dataTables.url.fleetDetails}).then(r=>{r.error?t.warning.removeClass('d-none').text(r.error):(t.warning.addClass('d-none'),t.tableFleetMembers.DataTable({...a,data:r.fleet_member,columns:[{render:(t,a,r)=>{const l='<i class="fa-solid fa-star"></i>';return r.is_fleet_boss?`${r.character_name} <sup data-bs-tooltip="aa-fleetfinder" title="${e.l10n.fleetBoss}"><small>${l}</small></sup>`:r.character_name}},{data:'ship_type_name'},{data:'solar_system_name'},{render:(t,a,r)=>{const l='<i class="fa-solid fa-user-minus"></i>',m=Object.entries({'data-character-id':r.character_id,'data-character-name':r.character_name,'data-bs-toggle':'modal','data-bs-target':'#kick-fleet-member','data-bs-tooltip':'aa-fleetfinder'}).map(([e,t])=>`${e}="${t}"`).join(' ');return r.is_fleet_boss?'':`<button type="button" class="btn btn-sm btn-danger" ${m} title="${e.l10n.kickMemberFromFleet}">${l}</button>`},orderable:!1,searchable:!1,width:'50px',className:'text-end'}],createdRow:(e,t,a)=>{$(e).attr('data-row-id',a),$(e).attr('data-character-id',t.character_id)},initComplete:()=>{fleetfinderBootstrapTooltip({selector:'#table-fleet-members'})}}),t.tableFleetComposition.DataTable({...a,data:r.fleet_composition,columns:[{data:'ship_type_name'},{data:'number',className:'text-right',width:'100px'}],order:[[1,'desc']]}))}).catch(e=>{console.error('Error fetching fleet details:',e)})};r(),setInterval(r,3e4),t.kickFleetMemberModal.on('show.bs.modal',t=>{const a=$(t.relatedTarget),l=a.data('character-id'),m=a.data('character-name'),o=e.dataTables.url.kickFleetMember;$('#kick-fleet-member-character-name').text(m),$('#modal-button-confirm-kick-fleet-member').off('click.kickMember').on('click.kickMember',()=>{fetchPost({url:o,csrfToken:e.csrfToken,payload:{memberId:l},responseIsJson:!0}).then(()=>{r(),$('#kick-fleet-member').modal('hide')}).catch(t=>{console.error('Error kicking fleet member:',t),$('#kick-fleet-member .modal-kick-fleet-member-error').removeClass('d-none').find('.modal-kick-fleet-member-error-message').text(t||e.l10n.unknownError)})})}).on('hide.bs.modal',()=>{$('#kick-fleet-member-character-name').empty(),$('#kick-fleet-member .modal-kick-fleet-member-error').addClass('d-none').find('.modal-kick-fleet-member-error-message').empty(),$('#modal-button-confirm-kick-fleet-member').off('click.kickMember')})});
2
+ //# sourceMappingURL=fleetfinder-fleet-details.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["$","document","ready","fleetFinderSettings","objectDeepMerge","aaFleetFinderSettings","aaFleetFinderSettingsOverride","elements","tableFleetMembers","tableFleetComposition","kickFleetMemberModal","kickFleetMemberCharacterName","modalButtonConfirmKickFleetMember","warning","dataTableConfig","language","url","dataTables","languageUrl","paging","destroy","populateDatatables","fetchGet","fleetDetails","then","data","error","removeClass","text","addClass","DataTable","fleet_member","columns","render","type","row","fwIcon","is_fleet_boss","character_name","l10n","fleetBoss","dataAttributes","Object","entries","character_id","map","key","value","join","kickMemberFromFleet","orderable","searchable","width","className","createdRow","rowIndex","attr","initComplete","fleetfinderBootstrapTooltip","selector","fleet_composition","order","catch","console","setInterval","on","event","button","relatedTarget","characterId","characterName","link","kickFleetMember","off","fetchPost","csrfToken","payload","memberId","responseIsJson","modal","find","unknownError","empty"],"sources":["fleetfinder-fleet-details.js"],"mappings":"AAEAA,EAAEC,UAAUC,MAAM,KACd,aAEA,MAAMC,EAAsBC,gBAAgBC,sBAAuBC,+BAI7DC,EAAW,CACbC,kBAAmBR,EAAE,wBACrBS,sBAAuBT,EAAE,4BACzBU,qBAAsBV,EAAE,sBACxBW,6BAA8BX,EAAE,qCAChCY,kCAAmCZ,EAAE,2CACrCa,QAASb,EAAE,uCAETc,EAAkB,CACpBC,SAAU,CACNC,IAAKb,EAAoBc,WAAWC,aAExCC,QAAQ,EACRC,SAAS,GAGPC,EAAqB,KACvBC,SAAS,CACLN,IAAKb,EAAoBc,WAAWD,IAAIO,eAEvCC,KAAMC,IACCA,EAAKC,MACLnB,EAASM,QAAQc,YAAY,UAAUC,KAAKH,EAAKC,QAKrDnB,EAASM,QAAQgB,SAAS,UAE1BtB,EAASC,kBAAkBsB,UAAU,IAC9BhB,EACHW,KAAMA,EAAKM,aACXC,QAAS,CACL,CACIC,OAAQ,CAACR,EAAMS,EAAMC,KACjB,MAAMC,EAAS,mCAEf,OAAOD,EAAIE,cAAgB,GAAGF,EAAIG,+DAA+DnC,EAAoBoC,KAAKC,qBAAqBJ,kBAAyBD,EAAIG,iBAGpL,CAACb,KAAM,kBACP,CAACA,KAAM,qBACP,CACIQ,OAAQ,CAACR,EAAMS,EAAMC,KACjB,MAAMC,EAAS,yCACTK,EAAiBC,OAAOC,QAAQ,CAClC,oBAAqBR,EAAIS,aACzB,sBAAuBT,EAAIG,eAC3B,iBAAkB,QAClB,iBAAkB,qBAClB,kBAAmB,mBACpBO,IAAI,EAAEC,EAAKC,KACH,GAAGD,MAAQC,MACnBC,KAAK,KAER,OAAOb,EAAIE,cAAgB,GAAK,uDAAuDI,YAAyBtC,EAAoBoC,KAAKU,wBAAwBb,cAErKc,WAAW,EACXC,YAAY,EACZC,MAAO,OACPC,UAAW,aAGnBC,WAAY,CAACnB,EAAKV,EAAM8B,KACpBvD,EAAEmC,GAAKqB,KAAK,cAAeD,GAC3BvD,EAAEmC,GAAKqB,KAAK,oBAAqB/B,EAAKmB,eAE1Ca,aAAc,KAEVC,4BAA4B,CAACC,SAAU,4BAI/CpD,EAASE,sBAAsBqB,UAAU,IAClChB,EACHW,KAAMA,EAAKmC,kBACX5B,QAAS,CACL,CAACP,KAAM,kBACP,CAACA,KAAM,SAAU4B,UAAW,aAAcD,MAAO,UAErDS,MAAO,CAAC,CAAC,EAAG,cAGnBC,MAAOpC,IACJqC,QAAQrC,MAAM,gCAAiCA,MAI3DL,IAEA2C,YAAY3C,EAAoB,KAKhCd,EAASG,qBACJuD,GAAG,gBAAkBC,IAClB,MAAMC,EAASnE,EAAEkE,EAAME,eACjBC,EAAcF,EAAO1C,KAAK,gBAC1B6C,EAAgBH,EAAO1C,KAAK,kBAC5B8C,EAAOpE,EAAoBc,WAAWD,IAAIwD,gBAGhDxE,EAAE,qCAAqC4B,KAAK0C,GAE5CtE,EAAE,2CAEGyE,IAAI,oBAEJR,GAAG,mBAAoB,KACpBS,UAAU,CACN1D,IAAKuD,EACLI,UAAWxE,EAAoBwE,UAC/BC,QAAS,CACLC,SAAUR,GAEdS,gBAAgB,IAEftD,KAAK,KACFH,IAEArB,EAAE,sBAAsB+E,MAAM,UAEjCjB,MAAOpC,IACJqC,QAAQrC,MAAM,8BAA+BA,GAE7C1B,EAAE,qDACG2B,YAAY,UACZqD,KAAK,0CACLpD,KAAKF,GAASvB,EAAoBoC,KAAK0C,oBAI/DhB,GAAG,gBAAiB,KAEjBjE,EAAE,qCAAqCkF,QACvClF,EAAE,qDACG6B,SAAS,UACTmD,KAAK,0CACLE,QAGLlF,EAAE,2CAA2CyE,IAAI","ignoreList":[]}
@@ -0,0 +1,23 @@
1
+ /* global bootstrap */
2
+
3
+ /* jshint -W097 */
4
+ 'use strict';
5
+
6
+ /**
7
+ * Bootstrap tooltip
8
+ *
9
+ * @param {string} [selector=body] Selector for the tooltip elements, defaults to 'body'
10
+ * to apply to all elements with the data-bs-tooltip attribute.
11
+ * Example: 'body', '.my-tooltip-class', '#my-tooltip-id'
12
+ * If you want to apply it to a specific element, use that element's selector.
13
+ * If you want to apply it to all elements with the data-bs-tooltip attribute,
14
+ * use 'body' or leave it empty.
15
+ * @param {string} [namespace=aa-fleetfinderl] Namespace for the tooltip
16
+ * @returns {void}
17
+ */
18
+ const fleetfinderBootstrapTooltip = ({selector = 'body', namespace = 'aa-fleetfinder'}) => { // eslint-disable-line no-unused-vars
19
+ document.querySelectorAll(`${selector} [data-bs-tooltip="${namespace}"]`)
20
+ .forEach((tooltipTriggerEl) => {
21
+ return new bootstrap.Tooltip(tooltipTriggerEl);
22
+ });
23
+ };
@@ -0,0 +1,2 @@
1
+ 'use strict';const fleetfinderBootstrapTooltip=({selector:t='body',namespace:e='aa-fleetfinder'})=>{document.querySelectorAll(`${t} [data-bs-tooltip="${e}"]`).forEach(t=>new bootstrap.Tooltip(t))};
2
+ //# sourceMappingURL=fleetfinder.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["fleetfinderBootstrapTooltip","selector","namespace","document","querySelectorAll","forEach","tooltipTriggerEl","bootstrap","Tooltip"],"sources":["fleetfinder.js"],"mappings":"AAGA,aAcA,MAAMA,4BAA8B,EAAEC,WAAW,OAAQC,YAAY,qBACjEC,SAASC,iBAAiB,GAAGH,uBAA8BC,OACtDG,QAASC,GACC,IAAIC,UAAUC,QAAQF","ignoreList":[]}
fleetfinder/tasks.py CHANGED
@@ -291,7 +291,9 @@ def check_fleet_adverts() -> None:
291
291
 
292
292
 
293
293
  @shared_task
294
- def get_fleet_composition(fleet_id: int) -> FleetViewAggregate | None:
294
+ def get_fleet_composition( # pylint: disable=too-many-locals
295
+ fleet_id: int,
296
+ ) -> FleetViewAggregate | None:
295
297
  """
296
298
  Get the composition of a fleet by its ID
297
299
  This task retrieves the composition of a fleet using its ESI ID.
@@ -304,10 +306,10 @@ def get_fleet_composition(fleet_id: int) -> FleetViewAggregate | None:
304
306
 
305
307
  try:
306
308
  fleet = Fleet.objects.get(fleet_id=fleet_id)
307
- except Fleet.DoesNotExist:
309
+ except Fleet.DoesNotExist as exc:
308
310
  logger.error(f"Fleet with ID {fleet_id} not found")
309
311
 
310
- return None
312
+ raise Fleet.DoesNotExist(f"Fleet with ID {fleet_id} not found.") from exc
311
313
 
312
314
  logger.info(
313
315
  f'Getting fleet composition for fleet "{fleet.name}" '
@@ -336,20 +338,40 @@ def get_fleet_composition(fleet_id: int) -> FleetViewAggregate | None:
336
338
  ]
337
339
  }
338
340
 
339
- ids_to_name = esi.client.Universe.post_universe_names(
340
- ids=list(all_ids)
341
- ).result()
341
+ logger.debug(
342
+ f"Found {len(all_ids)} unique IDs to fetch names for in fleet {fleet_id}"
343
+ )
344
+
345
+ # Process IDs in chunks of 1000 to avoid ESI limits.
346
+ # ESI has a limit of 1000 IDs per request, so we will chunk the requests,
347
+ # even though there is a theoretical limit of 768 unique IDs per fleet,
348
+ # so we never should hit the ESI limit.
349
+ # But to be on the safe side, we will chunk the requests in case CCP decides
350
+ # to change the fleet limit in the future, we will use a chunk size of 1000,
351
+ # which is the maximum allowed by ESI for the `post_universe_names` endpoint.
352
+ chunk_size = 1000
353
+ ids_to_name = []
354
+ all_ids_list = list(all_ids)
355
+
356
+ for i in range(0, len(all_ids_list), chunk_size):
357
+ chunk = all_ids_list[i : i + chunk_size]
358
+ chunk_result = esi.client.Universe.post_universe_names(ids=chunk).result()
359
+
360
+ ids_to_name.extend(chunk_result)
342
361
 
343
362
  # Create a lookup dictionary for names
344
363
  name_lookup = {item["id"]: item["name"] for item in ids_to_name}
345
364
 
346
- # Add names to fleet members
365
+ # Add additional information to each fleet member
347
366
  for member in fleet_infos:
367
+ is_fleet_boss = member["character_id"] == fleet.fleet_commander.character_id
368
+
348
369
  member.update(
349
370
  {
350
371
  "character_name": name_lookup[member["character_id"]],
351
372
  "solar_system_name": name_lookup[member["solar_system_id"]],
352
373
  "ship_type_name": name_lookup[member["ship_type_id"]],
374
+ "is_fleet_boss": is_fleet_boss,
353
375
  }
354
376
  )
355
377
 
@@ -360,4 +382,6 @@ def get_fleet_composition(fleet_id: int) -> FleetViewAggregate | None:
360
382
  except Exception as e: # pylint: disable=broad-exception-caught
361
383
  logger.error(f"Failed to get fleet composition for fleet {fleet_id}: {e}")
362
384
 
363
- return None
385
+ raise RuntimeError(
386
+ f"Failed to get fleet composition for fleet {fleet_id} : {str(e)}"
387
+ ) from e