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.
- {aa_fleetfinder-2.6.1.dist-info → aa_fleetfinder-2.7.1.dist-info}/METADATA +1 -1
- aa_fleetfinder-2.7.1.dist-info/RECORD +86 -0
- fleetfinder/__init__.py +1 -1
- fleetfinder/locale/cs_CZ/LC_MESSAGES/django.po +101 -27
- fleetfinder/locale/de/LC_MESSAGES/django.mo +0 -0
- fleetfinder/locale/de/LC_MESSAGES/django.po +106 -29
- fleetfinder/locale/django.pot +103 -28
- fleetfinder/locale/es/LC_MESSAGES/django.po +112 -27
- fleetfinder/locale/fr_FR/LC_MESSAGES/django.po +105 -27
- fleetfinder/locale/it_IT/LC_MESSAGES/django.po +98 -27
- fleetfinder/locale/ja/LC_MESSAGES/django.po +102 -27
- fleetfinder/locale/ko_KR/LC_MESSAGES/django.po +112 -27
- fleetfinder/locale/nl_NL/LC_MESSAGES/django.po +98 -27
- fleetfinder/locale/pl_PL/LC_MESSAGES/django.po +100 -27
- fleetfinder/locale/ru/LC_MESSAGES/django.mo +0 -0
- fleetfinder/locale/ru/LC_MESSAGES/django.po +116 -31
- fleetfinder/locale/sk/LC_MESSAGES/django.po +98 -27
- fleetfinder/locale/uk/LC_MESSAGES/django.mo +0 -0
- fleetfinder/locale/uk/LC_MESSAGES/django.po +116 -31
- fleetfinder/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
- fleetfinder/locale/zh_Hans/LC_MESSAGES/django.po +116 -31
- fleetfinder/static/fleetfinder/css/fleetfinder.css +21 -0
- fleetfinder/static/fleetfinder/css/fleetfinder.min.css +1 -1
- fleetfinder/static/fleetfinder/css/fleetfinder.min.css.map +1 -1
- fleetfinder/static/fleetfinder/js/fleetfinder-dashboard.js +86 -0
- fleetfinder/static/fleetfinder/js/fleetfinder-dashboard.min.js +2 -0
- fleetfinder/static/fleetfinder/js/fleetfinder-dashboard.min.js.map +1 -0
- fleetfinder/static/fleetfinder/js/fleetfinder-fleet-details.js +154 -0
- fleetfinder/static/fleetfinder/js/fleetfinder-fleet-details.min.js +2 -0
- fleetfinder/static/fleetfinder/js/fleetfinder-fleet-details.min.js.map +1 -0
- fleetfinder/static/fleetfinder/js/fleetfinder.js +23 -0
- fleetfinder/static/fleetfinder/js/fleetfinder.min.js +2 -0
- fleetfinder/static/fleetfinder/js/fleetfinder.min.js.map +1 -0
- fleetfinder/tasks.py +32 -8
- fleetfinder/templates/fleetfinder/base.html +11 -0
- fleetfinder/templates/fleetfinder/bundles/js/fleetfinder-js.html +9 -0
- fleetfinder/templates/fleetfinder/dashboard.html +9 -109
- fleetfinder/templates/fleetfinder/fleet-details.html +28 -65
- fleetfinder/templates/fleetfinder/join-fleet.html +11 -1
- fleetfinder/templates/fleetfinder/modals/kick-fleet-member.html +46 -0
- fleetfinder/tests/test_views.py +130 -10
- fleetfinder/urls.py +5 -0
- fleetfinder/views.py +173 -45
- aa_fleetfinder-2.6.1.dist-info/RECORD +0 -75
- {aa_fleetfinder-2.6.1.dist-info → aa_fleetfinder-2.7.1.dist-info}/WHEEL +0 -0
- {aa_fleetfinder-2.6.1.dist-info → aa_fleetfinder-2.7.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{% extends "allianceauth/base-bs5.html" %}
|
|
2
2
|
|
|
3
3
|
{% load i18n %}
|
|
4
|
+
{% load aa_i18n %}
|
|
4
5
|
|
|
5
6
|
{% block page_title %}
|
|
6
7
|
{% translate "Fleet Finder" %}
|
|
@@ -22,6 +23,16 @@
|
|
|
22
23
|
{% block content %}
|
|
23
24
|
<div class="aa-fleetfinder">
|
|
24
25
|
<div class="aa-fleetfinder-body">
|
|
26
|
+
{% get_datatables_language_static LANGUAGE_CODE as DT_LANG_PATH %}
|
|
27
|
+
|
|
28
|
+
<script>
|
|
29
|
+
const aaFleetFinderSettings = {
|
|
30
|
+
dataTables: {
|
|
31
|
+
languageUrl: "{{ DT_LANG_PATH }}",
|
|
32
|
+
datetimeFormat: 'YYYY-MM-DD, HH:mm',
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
</script>
|
|
25
36
|
{% block aa_fleetfinder_body %}{% endblock %}
|
|
26
37
|
</div>
|
|
27
38
|
|
|
@@ -19,12 +19,7 @@
|
|
|
19
19
|
<th>{% translate "Fleet commander" %}</th>
|
|
20
20
|
<th>{% translate "Fleet name" %}</th>
|
|
21
21
|
<th>{% translate "Created at" %}</th>
|
|
22
|
-
<th
|
|
23
|
-
|
|
24
|
-
{% if perms.fleetfinder.manage_fleets %}
|
|
25
|
-
<th>{% translate "Details" %}</th>
|
|
26
|
-
<th>{% translate "Edit" %}</th>
|
|
27
|
-
{% endif %}
|
|
22
|
+
<th class="text-end"><!-- {% translate "Join" %} --></th>
|
|
28
23
|
</tr>
|
|
29
24
|
</thead>
|
|
30
25
|
|
|
@@ -44,110 +39,15 @@
|
|
|
44
39
|
{% include "bundles/datatables-js-bs5.html" %}
|
|
45
40
|
{% include "bundles/moment-js.html" with locale=True %}
|
|
46
41
|
|
|
47
|
-
{% get_datatables_language_static LANGUAGE_CODE as DT_LANG_PATH %}
|
|
48
|
-
|
|
49
42
|
<script>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Initialize the datatable for fleet overview
|
|
56
|
-
*/
|
|
57
|
-
fetchGet({url: '{% url "fleetfinder:ajax_dashboard" %}'})
|
|
58
|
-
.then((data) => {
|
|
59
|
-
table_fleet_overview.DataTable({
|
|
60
|
-
language: {
|
|
61
|
-
url: '{{ DT_LANG_PATH }}'
|
|
62
|
-
},
|
|
63
|
-
data: data,
|
|
64
|
-
columns: [
|
|
65
|
-
{
|
|
66
|
-
data: 'fleet_commander',
|
|
67
|
-
render: {
|
|
68
|
-
_: 'html',
|
|
69
|
-
sort: 'sort'
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
{data: 'fleet_name'},
|
|
73
|
-
{
|
|
74
|
-
data: 'created_at',
|
|
75
|
-
},
|
|
76
|
-
{data: 'join'},
|
|
77
|
-
{% if perms.fleetfinder.manage_fleets %}
|
|
78
|
-
{data: 'details'},
|
|
79
|
-
{data: 'edit'},
|
|
80
|
-
{% endif %}
|
|
81
|
-
],
|
|
82
|
-
columnDefs: [
|
|
83
|
-
{
|
|
84
|
-
targets: 2,
|
|
85
|
-
render: DataTable.render.date(DATETIME_FORMAT)
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
orderable: false,
|
|
89
|
-
targets: [3]
|
|
90
|
-
},
|
|
91
|
-
{% if perms.fleetfinder.manage_fleets %}
|
|
92
|
-
{
|
|
93
|
-
orderable: false,
|
|
94
|
-
targets: [4, 5]
|
|
95
|
-
},
|
|
96
|
-
{% endif %}
|
|
97
|
-
],
|
|
98
|
-
order: [[0, 'asc']],
|
|
99
|
-
paging: false
|
|
100
|
-
});
|
|
101
|
-
})
|
|
102
|
-
.catch((error) => {
|
|
103
|
-
console.error('Error fetching fleet data:', error);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Refresh the datatable information every 30 seconds
|
|
108
|
-
*/
|
|
109
|
-
const intervalReloadDatatable = 30000; // ms
|
|
110
|
-
let expectedReloadDatatable = Date.now() + intervalReloadDatatable;
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* reload datatable "fleetfinderFleetsTable"
|
|
114
|
-
*/
|
|
115
|
-
const reloadDataTable = () => {
|
|
116
|
-
const dt = Date.now() - expectedReloadDatatable; // The drift (positive for overshooting)
|
|
117
|
-
|
|
118
|
-
if (dt > intervalReloadDatatable) {
|
|
119
|
-
// Something awful happened. Maybe the browser (tab) was inactive?
|
|
120
|
-
// Possibly special handling to avoid futile "catch up" run
|
|
121
|
-
console.log('Something went wrong, reloading page ...');
|
|
122
|
-
|
|
123
|
-
window.location.replace(
|
|
124
|
-
window.location.pathname + window.location.search + window.location.hash
|
|
125
|
-
);
|
|
43
|
+
const aaFleetFinderSettingsOverride = {
|
|
44
|
+
dataTables: {
|
|
45
|
+
url: {
|
|
46
|
+
dashboard: '{% url "fleetfinder:ajax_dashboard" %}'
|
|
126
47
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
.then((newData) => {
|
|
130
|
-
const dataTable = table_fleet_overview.DataTable();
|
|
131
|
-
|
|
132
|
-
dataTable.clear().rows.add(newData).draw();
|
|
133
|
-
})
|
|
134
|
-
.catch((error) => {
|
|
135
|
-
console.error('Error fetching updated data:', error);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
expectedReloadDatatable += intervalReloadDatatable;
|
|
139
|
-
|
|
140
|
-
// Take drift into account
|
|
141
|
-
setTimeout(
|
|
142
|
-
reloadDataTable,
|
|
143
|
-
Math.max(0, intervalReloadDatatable - dt)
|
|
144
|
-
);
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
setTimeout(
|
|
148
|
-
reloadDataTable,
|
|
149
|
-
intervalReloadDatatable
|
|
150
|
-
);
|
|
151
|
-
});
|
|
48
|
+
}
|
|
49
|
+
};
|
|
152
50
|
</script>
|
|
51
|
+
|
|
52
|
+
{% include "fleetfinder/bundles/js/fleetfinder-js.html" with view="dashboard" %}
|
|
153
53
|
{% endblock %}
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
{% endblock %}
|
|
9
9
|
|
|
10
10
|
{% block aa_fleetfinder_body %}
|
|
11
|
+
{% include "framework/header/page-header.html" with title=fleet.name subtitle=fleet.fleet_commander.character_name %}
|
|
12
|
+
|
|
13
|
+
<div class="alert alert-warning d-none" id="fleetfinder-fleet-details-warning"></div>
|
|
14
|
+
|
|
11
15
|
<div class="row">
|
|
12
16
|
<div class="col-lg-6 col-lg-push-6">
|
|
13
17
|
<div class="card card-primary">
|
|
@@ -19,7 +23,7 @@
|
|
|
19
23
|
|
|
20
24
|
<div class="card-body">
|
|
21
25
|
<div class="table-responsive">
|
|
22
|
-
<table class="table table-striped table-hover table-vertical-middle w-100" id="
|
|
26
|
+
<table class="table table-striped table-hover table-vertical-middle w-100" id="table-fleet-composition">
|
|
23
27
|
<thead>
|
|
24
28
|
<tr>
|
|
25
29
|
<th>{% translate "Ship class" %}</th>
|
|
@@ -44,12 +48,13 @@
|
|
|
44
48
|
|
|
45
49
|
<div class="card-body">
|
|
46
50
|
<div class="table-responsive">
|
|
47
|
-
<table class="table table-striped table-hover table-vertical-middle w-100" id="
|
|
51
|
+
<table class="table table-striped table-hover table-vertical-middle w-100" id="table-fleet-members">
|
|
48
52
|
<thead>
|
|
49
53
|
<tr>
|
|
50
54
|
<th>{% translate "Name" %}</th>
|
|
51
55
|
<th>{% translate "Ship class" %}</th>
|
|
52
56
|
<th>{% translate "System" %}</th>
|
|
57
|
+
<th><!-- {% translate "Action" %} --></th>
|
|
53
58
|
</tr>
|
|
54
59
|
</thead>
|
|
55
60
|
|
|
@@ -60,6 +65,8 @@
|
|
|
60
65
|
</div>
|
|
61
66
|
</div>
|
|
62
67
|
</div>
|
|
68
|
+
|
|
69
|
+
{% include "fleetfinder/modals/kick-fleet-member.html" %}
|
|
63
70
|
{% endblock %}
|
|
64
71
|
|
|
65
72
|
{% block extra_css %}
|
|
@@ -70,70 +77,26 @@
|
|
|
70
77
|
{% block extra_javascript %}
|
|
71
78
|
{% include "bundles/datatables-js-bs5.html" %}
|
|
72
79
|
|
|
73
|
-
{%
|
|
80
|
+
{% translate "Fleet boss" as l10nFleetBoss %}
|
|
81
|
+
{% translate "Kick member from fleet" as l10nKickMemberFromFleet %}
|
|
82
|
+
{% translate "An unknown error occurred." as l10nUnknownError %}
|
|
74
83
|
|
|
75
84
|
<script>
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
paging: false,
|
|
91
|
-
data: data.fleet_member,
|
|
92
|
-
columns: [
|
|
93
|
-
{data: 'character_name'},
|
|
94
|
-
{data: 'ship_type_name'},
|
|
95
|
-
{data: 'solar_system_name'}
|
|
96
|
-
]
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
tabe_fleet_composition.DataTable({
|
|
100
|
-
language: {
|
|
101
|
-
url: '{{ DT_LANG_PATH }}'
|
|
102
|
-
},
|
|
103
|
-
destroy: true,
|
|
104
|
-
paging: false,
|
|
105
|
-
data: data.fleet_composition,
|
|
106
|
-
columns: [
|
|
107
|
-
{data: 'ship_type_name'},
|
|
108
|
-
{data: 'number', className: 'text-right', width: '100px'}
|
|
109
|
-
],
|
|
110
|
-
order: [[1, 'desc']]
|
|
111
|
-
});
|
|
112
|
-
})
|
|
113
|
-
.catch((error) => {
|
|
114
|
-
console.error('Error fetching fleet details:', error);
|
|
115
|
-
});
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
table_fleet_members.DataTable({
|
|
119
|
-
language: {
|
|
120
|
-
url: '{{ DT_LANG_PATH }}'
|
|
121
|
-
},
|
|
122
|
-
paging: false,
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
tabe_fleet_composition.DataTable({
|
|
126
|
-
language: {
|
|
127
|
-
url: '{{ DT_LANG_PATH }}'
|
|
128
|
-
},
|
|
129
|
-
paging: false,
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
populateDatatables();
|
|
133
|
-
|
|
134
|
-
setInterval(function () {
|
|
135
|
-
populateDatatables();
|
|
136
|
-
}, 30000);
|
|
137
|
-
});
|
|
85
|
+
const aaFleetFinderSettingsOverride = {
|
|
86
|
+
dataTables: {
|
|
87
|
+
url: {
|
|
88
|
+
fleetDetails: '{% url "fleetfinder:ajax_fleet_details" fleet.fleet_id %}',
|
|
89
|
+
kickFleetMember: '{% url "fleetfinder:ajax_fleet_kick_member" fleet.fleet_id %}'
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
l10n: {
|
|
93
|
+
fleetBoss: '{{ l10nFleetBoss|escapejs }}',
|
|
94
|
+
kickMemberFromFleet: '{{ l10nKickMemberFromFleet|escapejs }}',
|
|
95
|
+
unknownError: '{{ l10nUnknownError|escapejs }}'
|
|
96
|
+
},
|
|
97
|
+
csrfToken: '{{ csrf_token }}'
|
|
98
|
+
};
|
|
138
99
|
</script>
|
|
100
|
+
|
|
101
|
+
{% include "fleetfinder/bundles/js/fleetfinder-js.html" with view="fleet-details" %}
|
|
139
102
|
{% endblock %}
|
|
@@ -18,11 +18,21 @@
|
|
|
18
18
|
<div class="card-body container">
|
|
19
19
|
<div class="row">
|
|
20
20
|
<div class="align-self-center">
|
|
21
|
+
<p>
|
|
22
|
+
{% translate "Please ensure you don't have any CSPA charges set on your characters, as this will prevent fleet invites from being sent." %}
|
|
23
|
+
<br>
|
|
24
|
+
{% translate "You can select multiple characters to invite them all at once." %}
|
|
25
|
+
</p>
|
|
26
|
+
|
|
27
|
+
<p>
|
|
28
|
+
{% translate "The selected characters will receive a fleet invite in-game, which they can accept to join the fleet." %}
|
|
29
|
+
</p>
|
|
30
|
+
|
|
21
31
|
<form class="form-signin" role="form" action="" method="POST">
|
|
22
32
|
{% csrf_token %}
|
|
23
33
|
|
|
24
34
|
<div class="mb-3">
|
|
25
|
-
<label for="character_ids">{% translate "
|
|
35
|
+
<label for="character_ids" class="mb-1">{% translate "Please select the characters you want to invite:" %}</label>
|
|
26
36
|
|
|
27
37
|
<select class="multiselect-ui" multiple="multiple" name="character_ids" id="character_ids">
|
|
28
38
|
{% for character in characters %}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{% load bootstrap %}
|
|
2
|
+
{% load i18n %}
|
|
3
|
+
|
|
4
|
+
<!-- kick fleet member modal -->
|
|
5
|
+
<div class="modal fade" id="kick-fleet-member" tabindex="-1" role="dialog" aria-hidden="true">
|
|
6
|
+
<div class="modal-dialog modal-dialog-centered" role="document">
|
|
7
|
+
<div class="modal-content">
|
|
8
|
+
<div class="modal-header">
|
|
9
|
+
<div class="modal-title fs-5">
|
|
10
|
+
{% translate "Kick member from fleet" %}
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{% translate 'Close' %}"></button>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<div class="modal-body">
|
|
17
|
+
<p>
|
|
18
|
+
{% translate "Are you sure you want to kick this member from the fleet?" %}
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
<p>
|
|
22
|
+
<strong id="kick-fleet-member-character-name"></strong>
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
<p class="aa-callout aa-callout-danger modal-kick-fleet-member-error d-none">
|
|
26
|
+
<i class="fa-solid fa-triangle-exclamation"></i>
|
|
27
|
+
{% translate "Error" %}
|
|
28
|
+
<br>
|
|
29
|
+
<span class="modal-kick-fleet-member-error-message"></span>
|
|
30
|
+
</p>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<div class="modal-footer">
|
|
34
|
+
<button id="modal-button-cancel-kick-fleet-member" type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">
|
|
35
|
+
<i class="fa-regular fa-hand"></i>
|
|
36
|
+
{% translate "Cancel" %}
|
|
37
|
+
</button>
|
|
38
|
+
|
|
39
|
+
<button id="modal-button-confirm-kick-fleet-member" type="button" class="btn btn-success btn-sm">
|
|
40
|
+
<i class="fa-solid fa-check"></i>
|
|
41
|
+
{% translate "Confirm" %}
|
|
42
|
+
</button>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
fleetfinder/tests/test_views.py
CHANGED
|
@@ -101,14 +101,14 @@ class TestAjaxDashboardView(FleetfinderTestViews):
|
|
|
101
101
|
It should also filter fleets based on the user's groups.
|
|
102
102
|
"""
|
|
103
103
|
|
|
104
|
-
# python
|
|
105
104
|
@patch("fleetfinder.views.get_all_characters_from_user")
|
|
106
|
-
def
|
|
105
|
+
def test_renders_dashboard_with_fleet_data_with_basic_access(
|
|
106
|
+
self, mock_get_characters
|
|
107
|
+
):
|
|
107
108
|
"""
|
|
108
|
-
Test that the ajax_dashboard view renders the dashboard with fleet data
|
|
109
|
+
Test that the ajax_dashboard view renders the dashboard with fleet data
|
|
110
|
+
when the user has basic access permissions.
|
|
109
111
|
|
|
110
|
-
:param mock_portrait_url:
|
|
111
|
-
:type mock_portrait_url:
|
|
112
112
|
:param mock_get_characters:
|
|
113
113
|
:type mock_get_characters:
|
|
114
114
|
:return:
|
|
@@ -124,9 +124,10 @@ class TestAjaxDashboardView(FleetfinderTestViews):
|
|
|
124
124
|
|
|
125
125
|
self.client.force_login(self.user_with_basic_acces_perms)
|
|
126
126
|
url = reverse("fleetfinder:ajax_dashboard")
|
|
127
|
+
join_url = reverse("fleetfinder:join_fleet", args=[self.fleet_id])
|
|
127
128
|
response = self.client.get(url)
|
|
128
129
|
|
|
129
|
-
|
|
130
|
+
expected_response = [
|
|
130
131
|
{
|
|
131
132
|
"fleet_commander": {
|
|
132
133
|
"html": '<img class="rounded eve-character-portrait" src="https://images.evetech.net/characters/1000/portrait?size=32" alt="Jean Luc Picard" loading="lazy">Jean Luc Picard',
|
|
@@ -134,16 +135,63 @@ class TestAjaxDashboardView(FleetfinderTestViews):
|
|
|
134
135
|
},
|
|
135
136
|
"fleet_name": "Starfleet",
|
|
136
137
|
"created_at": dt_to_iso(self.fleet_created_at),
|
|
137
|
-
"
|
|
138
|
-
"details": "",
|
|
139
|
-
"edit": "",
|
|
138
|
+
"actions": f'<a href="{join_url}" class="btn btn-sm btn-success ms-1" data-bs-tooltip="aa-fleetfinder" title="Join fleet"><i class="fa-solid fa-right-to-bracket"></i></a>',
|
|
140
139
|
}
|
|
141
140
|
]
|
|
142
141
|
|
|
143
142
|
self.assertEqual(response.status_code, HTTPStatus.OK)
|
|
144
143
|
self.assertIn("Starfleet", response.json()[0]["fleet_name"])
|
|
145
144
|
self.assertIn("Jean Luc Picard", response.json()[0]["fleet_commander"]["html"])
|
|
146
|
-
self.assertEqual(response.json(),
|
|
145
|
+
self.assertEqual(response.json(), expected_response)
|
|
146
|
+
|
|
147
|
+
@patch("fleetfinder.views.get_all_characters_from_user")
|
|
148
|
+
def test_renders_dashboard_with_fleet_data_with_manage_access(
|
|
149
|
+
self, mock_get_characters
|
|
150
|
+
):
|
|
151
|
+
"""
|
|
152
|
+
Test that the ajax_dashboard view renders the dashboard with fleet data
|
|
153
|
+
when the user has manage access permissions.
|
|
154
|
+
|
|
155
|
+
:param mock_get_characters:
|
|
156
|
+
:type mock_get_characters:
|
|
157
|
+
:return:
|
|
158
|
+
:rtype:
|
|
159
|
+
"""
|
|
160
|
+
|
|
161
|
+
mock_get_characters.return_value = [
|
|
162
|
+
self.user_with_manage_perms.profile.main_character
|
|
163
|
+
]
|
|
164
|
+
|
|
165
|
+
fleet = self.fleet
|
|
166
|
+
fleet.groups.set([])
|
|
167
|
+
|
|
168
|
+
self.client.force_login(self.user_with_manage_perms)
|
|
169
|
+
url = reverse("fleetfinder:ajax_dashboard")
|
|
170
|
+
join_url = reverse("fleetfinder:join_fleet", args=[self.fleet_id])
|
|
171
|
+
details_url = reverse("fleetfinder:fleet_details", args=[self.fleet_id])
|
|
172
|
+
edit_url = reverse("fleetfinder:edit_fleet", args=[self.fleet_id])
|
|
173
|
+
response = self.client.get(url)
|
|
174
|
+
|
|
175
|
+
expected_response = [
|
|
176
|
+
{
|
|
177
|
+
"fleet_commander": {
|
|
178
|
+
"html": '<img class="rounded eve-character-portrait" src="https://images.evetech.net/characters/1000/portrait?size=32" alt="Jean Luc Picard" loading="lazy">Jean Luc Picard',
|
|
179
|
+
"sort": "Jean Luc Picard",
|
|
180
|
+
},
|
|
181
|
+
"fleet_name": "Starfleet",
|
|
182
|
+
"created_at": dt_to_iso(self.fleet_created_at),
|
|
183
|
+
"actions": (
|
|
184
|
+
f'<a href="{join_url}" class="btn btn-sm btn-success ms-1" data-bs-tooltip="aa-fleetfinder" title="Join fleet"><i class="fa-solid fa-right-to-bracket"></i></a>'
|
|
185
|
+
f'<a href="{details_url}" class="btn btn-sm btn-info ms-1" data-bs-tooltip="aa-fleetfinder" title="View fleet details"><i class="fa-solid fa-eye"></i></a>'
|
|
186
|
+
f'<a href="{edit_url}" class="btn btn-sm btn-warning ms-1" data-bs-tooltip="aa-fleetfinder" title="Edit fleet advert"><i class="fa-solid fa-pen-to-square"></i></a>'
|
|
187
|
+
),
|
|
188
|
+
}
|
|
189
|
+
]
|
|
190
|
+
|
|
191
|
+
self.assertEqual(response.status_code, HTTPStatus.OK)
|
|
192
|
+
self.assertIn("Starfleet", response.json()[0]["fleet_name"])
|
|
193
|
+
self.assertIn("Jean Luc Picard", response.json()[0]["fleet_commander"]["html"])
|
|
194
|
+
self.assertEqual(response.json(), expected_response)
|
|
147
195
|
|
|
148
196
|
@patch("fleetfinder.views.get_all_characters_from_user")
|
|
149
197
|
def test_returns_empty_data_when_no_fleets_available(self, mock_get_characters):
|
|
@@ -171,6 +219,15 @@ class TestAjaxDashboardView(FleetfinderTestViews):
|
|
|
171
219
|
|
|
172
220
|
@patch("fleetfinder.views.get_all_characters_from_user")
|
|
173
221
|
def test_filters_fleets_by_user_groups(self, mock_get_characters):
|
|
222
|
+
"""
|
|
223
|
+
Test that the ajax_dashboard view filters fleets based on the user's groups.
|
|
224
|
+
|
|
225
|
+
:param mock_get_characters:
|
|
226
|
+
:type mock_get_characters:
|
|
227
|
+
:return:
|
|
228
|
+
:rtype:
|
|
229
|
+
"""
|
|
230
|
+
|
|
174
231
|
mock_get_characters.return_value = [
|
|
175
232
|
self.user_with_manage_perms.profile.main_character
|
|
176
233
|
]
|
|
@@ -345,6 +402,21 @@ class TestFleetDetailsView(FleetfinderTestViews):
|
|
|
345
402
|
|
|
346
403
|
self.assertEqual(response.status_code, HTTPStatus.FOUND)
|
|
347
404
|
|
|
405
|
+
def test_fleet_redirects_to_dashboard_if_not_found(self):
|
|
406
|
+
"""
|
|
407
|
+
Test that the fleet_details view redirects to the dashboard if the fleet does not exist.
|
|
408
|
+
|
|
409
|
+
:return:
|
|
410
|
+
:rtype:
|
|
411
|
+
"""
|
|
412
|
+
|
|
413
|
+
self.client.force_login(self.user_with_manage_perms)
|
|
414
|
+
|
|
415
|
+
response = self.client.get(reverse("fleetfinder:fleet_details", args=[123]))
|
|
416
|
+
|
|
417
|
+
self.assertEqual(response.status_code, HTTPStatus.FOUND)
|
|
418
|
+
self.assertEqual(response.url, reverse("fleetfinder:dashboard"))
|
|
419
|
+
|
|
348
420
|
|
|
349
421
|
class TestAjaxFleetDetailsView(FleetfinderTestViews):
|
|
350
422
|
"""
|
|
@@ -414,3 +486,51 @@ class TestAjaxFleetDetailsView(FleetfinderTestViews):
|
|
|
414
486
|
|
|
415
487
|
self.assertEqual(response.status_code, HTTPStatus.OK)
|
|
416
488
|
self.assertEqual(json.loads(response.content), expected_fleet_composition)
|
|
489
|
+
|
|
490
|
+
@patch("fleetfinder.views.get_fleet_composition")
|
|
491
|
+
def test_returns_error_when_fleet_does_not_exist(self, mock_get_fleet_composition):
|
|
492
|
+
"""
|
|
493
|
+
Test that the ajax_fleet_details view returns an error when the fleet does not exist.
|
|
494
|
+
|
|
495
|
+
:param mock_get_fleet_composition:
|
|
496
|
+
:type mock_get_fleet_composition:
|
|
497
|
+
:return:
|
|
498
|
+
:rtype:
|
|
499
|
+
"""
|
|
500
|
+
|
|
501
|
+
mock_get_fleet_composition.side_effect = Fleet.DoesNotExist
|
|
502
|
+
|
|
503
|
+
self.client.force_login(user=self.user_with_manage_perms)
|
|
504
|
+
|
|
505
|
+
url = reverse("fleetfinder:ajax_fleet_details", args=[123])
|
|
506
|
+
response = self.client.get(url)
|
|
507
|
+
|
|
508
|
+
self.assertEqual(response.status_code, HTTPStatus.OK)
|
|
509
|
+
self.assertJSONEqual(
|
|
510
|
+
response.content,
|
|
511
|
+
{"error": "Fleet with ID 123 does not exist."},
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
@patch("fleetfinder.views.get_fleet_composition")
|
|
515
|
+
def test_returns_error_when_runtime_error_occurs(self, mock_get_fleet_composition):
|
|
516
|
+
"""
|
|
517
|
+
Test that the ajax_fleet_details view returns an error when a runtime error occurs.
|
|
518
|
+
|
|
519
|
+
:param mock_get_fleet_composition:
|
|
520
|
+
:type mock_get_fleet_composition:
|
|
521
|
+
:return:
|
|
522
|
+
:rtype:
|
|
523
|
+
"""
|
|
524
|
+
|
|
525
|
+
mock_get_fleet_composition.side_effect = RuntimeError("Unexpected error")
|
|
526
|
+
|
|
527
|
+
self.client.force_login(user=self.user_with_manage_perms)
|
|
528
|
+
|
|
529
|
+
url = reverse("fleetfinder:ajax_fleet_details", args=[123])
|
|
530
|
+
response = self.client.get(url)
|
|
531
|
+
|
|
532
|
+
self.assertEqual(response.status_code, HTTPStatus.OK)
|
|
533
|
+
self.assertJSONEqual(
|
|
534
|
+
response.content,
|
|
535
|
+
{"error": "Error retrieving fleet composition: Unexpected error"},
|
|
536
|
+
)
|
fleetfinder/urls.py
CHANGED