aa-fatanalysis 0.1.0__tar.gz

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.
Files changed (25) hide show
  1. aa_fatanalysis-0.1.0/.gitignore +8 -0
  2. aa_fatanalysis-0.1.0/LICENSE +21 -0
  3. aa_fatanalysis-0.1.0/PKG-INFO +82 -0
  4. aa_fatanalysis-0.1.0/README.md +40 -0
  5. aa_fatanalysis-0.1.0/fatanalysis/__init__.py +1 -0
  6. aa_fatanalysis-0.1.0/fatanalysis/apps.py +6 -0
  7. aa_fatanalysis-0.1.0/fatanalysis/auth_hooks.py +30 -0
  8. aa_fatanalysis-0.1.0/fatanalysis/forms.py +15 -0
  9. aa_fatanalysis-0.1.0/fatanalysis/migrations/0001_initial.py +36 -0
  10. aa_fatanalysis-0.1.0/fatanalysis/migrations/0002_alter_uploadperiod_upload_date.py +19 -0
  11. aa_fatanalysis-0.1.0/fatanalysis/migrations/__init__.py +1 -0
  12. aa_fatanalysis-0.1.0/fatanalysis/models.py +27 -0
  13. aa_fatanalysis-0.1.0/fatanalysis/templates/fatanalysis/base.html +21 -0
  14. aa_fatanalysis-0.1.0/fatanalysis/templates/fatanalysis/import_csv.html +20 -0
  15. aa_fatanalysis-0.1.0/fatanalysis/templates/fatanalysis/index.html +94 -0
  16. aa_fatanalysis-0.1.0/fatanalysis/templates/fatanalysis/overview.html +141 -0
  17. aa_fatanalysis-0.1.0/fatanalysis/templates/fatanalysis/period_delete.html +24 -0
  18. aa_fatanalysis-0.1.0/fatanalysis/templates/fatanalysis/period_detail.html +90 -0
  19. aa_fatanalysis-0.1.0/fatanalysis/templates/fatanalysis/period_list.html +66 -0
  20. aa_fatanalysis-0.1.0/fatanalysis/templates/fatanalysis/player_detail.html +139 -0
  21. aa_fatanalysis-0.1.0/fatanalysis/tests/__init__.py +0 -0
  22. aa_fatanalysis-0.1.0/fatanalysis/tests/test_settings.py +26 -0
  23. aa_fatanalysis-0.1.0/fatanalysis/urls.py +15 -0
  24. aa_fatanalysis-0.1.0/fatanalysis/views.py +374 -0
  25. aa_fatanalysis-0.1.0/pyproject.toml +50 -0
@@ -0,0 +1,8 @@
1
+ *.pyc
2
+ __pycache__/
3
+ db.sqlite3
4
+ dist/
5
+ build/
6
+ *.egg-info/
7
+ .venv/
8
+ venv/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Maddog Broekman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,82 @@
1
+ Metadata-Version: 2.5
2
+ Name: aa-fatanalysis
3
+ Version: 0.1.0
4
+ Summary: FAT Analysis Plugin for Alliance Auth
5
+ Author-email: Maddog Broekman <maddogbroekman@gmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Maddog Broekman
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+ License-File: LICENSE
28
+ Keywords: allianceauth,fatanalysis
29
+ Classifier: Environment :: Web Environment
30
+ Classifier: Framework :: Django
31
+ Classifier: Framework :: Django :: 5.2
32
+ Classifier: Intended Audience :: Developers
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Operating System :: OS Independent
35
+ Classifier: Programming Language :: Python
36
+ Classifier: Programming Language :: Python :: 3 :: Only
37
+ Classifier: Topic :: Internet :: WWW/HTTP
38
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
39
+ Requires-Python: <3.14,>=3.10
40
+ Requires-Dist: allianceauth>=5
41
+ Description-Content-Type: text/markdown
42
+
43
+ # FAT Analysis
44
+
45
+ Alliance Auth plugin for analyzing FATs (Fleet Activity Tracking). This plugin allows for the upload of 30-day and 90-day FAT CSV files, parses them dynamically, and provides overviews and interactive charts on both a per-character and per-corporation basis.
46
+
47
+ ## Installation
48
+
49
+ 1. **Activate your Alliance Auth virtual environment**
50
+ ```bash
51
+ source /home/allianceserver/venv/auth/bin/activate
52
+ ```
53
+
54
+ 2. **Install the plugin**
55
+ Navigate to the directory containing this plugin and run:
56
+ ```bash
57
+ pip install -e .
58
+ ```
59
+ *(Or install via git / pip once published to a repository)*
60
+
61
+ 3. **Update your Alliance Auth settings**
62
+ Add `'fatanalysis'` to your `INSTALLED_APPS` in `myauth/myauth/settings/local.py`:
63
+ ```python
64
+ INSTALLED_APPS += [
65
+ 'fatanalysis',
66
+ ]
67
+ ```
68
+
69
+ 4. **Run migrations**
70
+ ```bash
71
+ python manage.py makemigrations
72
+ python manage.py migrate
73
+ ```
74
+
75
+ 5. **Restart Alliance Auth services**
76
+ ```bash
77
+ sudo systemctl restart supervisor
78
+ ```
79
+ *(Or restart gunicorn and celery according to your specific setup)*
80
+
81
+ ## Permissions
82
+ Assign the `fatanalysis.basic_access` permission in the admin panel to any user or group that should have access to view and upload FAT analysis data.
@@ -0,0 +1,40 @@
1
+ # FAT Analysis
2
+
3
+ Alliance Auth plugin for analyzing FATs (Fleet Activity Tracking). This plugin allows for the upload of 30-day and 90-day FAT CSV files, parses them dynamically, and provides overviews and interactive charts on both a per-character and per-corporation basis.
4
+
5
+ ## Installation
6
+
7
+ 1. **Activate your Alliance Auth virtual environment**
8
+ ```bash
9
+ source /home/allianceserver/venv/auth/bin/activate
10
+ ```
11
+
12
+ 2. **Install the plugin**
13
+ Navigate to the directory containing this plugin and run:
14
+ ```bash
15
+ pip install -e .
16
+ ```
17
+ *(Or install via git / pip once published to a repository)*
18
+
19
+ 3. **Update your Alliance Auth settings**
20
+ Add `'fatanalysis'` to your `INSTALLED_APPS` in `myauth/myauth/settings/local.py`:
21
+ ```python
22
+ INSTALLED_APPS += [
23
+ 'fatanalysis',
24
+ ]
25
+ ```
26
+
27
+ 4. **Run migrations**
28
+ ```bash
29
+ python manage.py makemigrations
30
+ python manage.py migrate
31
+ ```
32
+
33
+ 5. **Restart Alliance Auth services**
34
+ ```bash
35
+ sudo systemctl restart supervisor
36
+ ```
37
+ *(Or restart gunicorn and celery according to your specific setup)*
38
+
39
+ ## Permissions
40
+ Assign the `fatanalysis.basic_access` permission in the admin panel to any user or group that should have access to view and upload FAT analysis data.
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
@@ -0,0 +1,6 @@
1
+ from django.apps import AppConfig
2
+
3
+ class FatAnalysisConfig(AppConfig):
4
+ name = 'fatanalysis'
5
+ label = 'fatanalysis'
6
+ verbose_name = 'FAT Analysis'
@@ -0,0 +1,30 @@
1
+ from allianceauth import hooks
2
+ from allianceauth.services.hooks import MenuItemHook, UrlHook
3
+ from django.utils.translation import gettext_lazy as _
4
+
5
+ from . import urls
6
+
7
+ class FatAnalysisMenuItem(MenuItemHook):
8
+ """This class ensures only authorized users will see the menu entry"""
9
+ def __init__(self):
10
+ # Setup menu entry for sidebar
11
+ MenuItemHook.__init__(
12
+ self,
13
+ _('FAT Analysis'),
14
+ 'fas fa-chart-line fa-fw',
15
+ 'fatanalysis:index',
16
+ navactive=['fatanalysis:']
17
+ )
18
+
19
+ def render(self, request):
20
+ if request.user.has_perm('fatanalysis.basic_access'):
21
+ return MenuItemHook.render(self, request)
22
+ return ''
23
+
24
+ @hooks.register('menu_item_hook')
25
+ def register_menu():
26
+ return FatAnalysisMenuItem()
27
+
28
+ @hooks.register('url_hook')
29
+ def register_urls():
30
+ return UrlHook(urls, 'fatanalysis', r'^fatanalysis/')
@@ -0,0 +1,15 @@
1
+ from django import forms
2
+
3
+ class CsvImportForm(forms.Form):
4
+ PERIOD_CHOICES = (
5
+ (30, '30 Days'),
6
+ (90, '90 Days'),
7
+ )
8
+ csv_file = forms.FileField(label='FAT CSV File')
9
+ period_type = forms.ChoiceField(choices=PERIOD_CHOICES, label='Period Type')
10
+ custom_date = forms.DateTimeField(
11
+ required=False,
12
+ label='Custom Date (Optional)',
13
+ help_text='Leave empty to use current date and time. Use format YYYY-MM-DD HH:MM if your browser does not show a date picker.',
14
+ widget=forms.DateTimeInput(attrs={'type': 'datetime-local'})
15
+ )
@@ -0,0 +1,36 @@
1
+ # Generated by Django 5.2.16 on 2026-07-31 17:05
2
+
3
+ import django.db.models.deletion
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ initial = True
10
+
11
+ dependencies = [
12
+ ('eveonline', '0025_remove_evecharacter_last_updated_and_more'),
13
+ ]
14
+
15
+ operations = [
16
+ migrations.CreateModel(
17
+ name='UploadPeriod',
18
+ fields=[
19
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
+ ('upload_date', models.DateTimeField(auto_now_add=True)),
21
+ ('uploader', models.CharField(max_length=255)),
22
+ ('period_type', models.IntegerField(choices=[(30, '30 Days'), (90, '90 Days')])),
23
+ ],
24
+ ),
25
+ migrations.CreateModel(
26
+ name='FatEntry',
27
+ fields=[
28
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
29
+ ('character_name', models.CharField(max_length=255)),
30
+ ('total_fats', models.IntegerField(default=0)),
31
+ ('fat_details', models.JSONField(blank=True, default=dict)),
32
+ ('character', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='eveonline.evecharacter')),
33
+ ('period', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='fat_entries', to='fatanalysis.uploadperiod')),
34
+ ],
35
+ ),
36
+ ]
@@ -0,0 +1,19 @@
1
+ # Generated by Django 5.2.15 on 2026-07-31 17:31
2
+
3
+ import django.utils.timezone
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ('fatanalysis', '0001_initial'),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AlterField(
15
+ model_name='uploadperiod',
16
+ name='upload_date',
17
+ field=models.DateTimeField(default=django.utils.timezone.now),
18
+ ),
19
+ ]
@@ -0,0 +1 @@
1
+ # Migrations module
@@ -0,0 +1,27 @@
1
+ from django.db import models
2
+ from allianceauth.eveonline.models import EveCharacter
3
+ from django.utils import timezone
4
+
5
+ class UploadPeriod(models.Model):
6
+ PERIOD_CHOICES = (
7
+ (30, '30 Days'),
8
+ (90, '90 Days'),
9
+ )
10
+ upload_date = models.DateTimeField(default=timezone.now)
11
+ uploader = models.CharField(max_length=255)
12
+ period_type = models.IntegerField(choices=PERIOD_CHOICES)
13
+
14
+ def __str__(self):
15
+ return f"{self.get_period_type_display()} Upload ({self.upload_date.strftime('%Y-%m-%d %H:%M')})"
16
+
17
+ class FatEntry(models.Model):
18
+ period = models.ForeignKey(UploadPeriod, on_delete=models.CASCADE, related_name='fat_entries')
19
+ character = models.ForeignKey(EveCharacter, on_delete=models.SET_NULL, null=True, blank=True)
20
+ character_name = models.CharField(max_length=255)
21
+ total_fats = models.IntegerField(default=0)
22
+
23
+ # Stores dynamic fleet types (e.g. Strategic, QRF, Astartes) without hardcoding columns
24
+ fat_details = models.JSONField(default=dict, blank=True)
25
+
26
+ def __str__(self):
27
+ return f"{self.character_name} - {self.total_fats} FATs"
@@ -0,0 +1,21 @@
1
+ {% extends "allianceauth/base-bs5.html" %}
2
+ {% load i18n %}
3
+
4
+ {% block page_title %}{% trans "FAT Analysis" %}{% endblock page_title %}
5
+
6
+ {% block content %}
7
+ <div class="row">
8
+ <div class="col-md-12">
9
+ <h1 class="page-header text-center">{% trans "FAT Analysis Dashboard" %}</h1>
10
+ {% block fatanalysis_content %}{% endblock %}
11
+ </div>
12
+ </div>
13
+ {% endblock %}
14
+
15
+ {% block extra_css %}
16
+ {% include 'bundles/datatables-css-bs5.html' %}
17
+ {% endblock %}
18
+
19
+ {% block extra_javascript %}
20
+ {% include 'bundles/datatables-js-bs5.html' %}
21
+ {% endblock %}
@@ -0,0 +1,20 @@
1
+ {% extends "fatanalysis/base.html" %}
2
+ {% load i18n %}
3
+ {% load django_bootstrap5 %}
4
+
5
+ {% block fatanalysis_content %}
6
+ <div class="panel panel-default">
7
+ <div class="panel-heading">
8
+ <h3 class="panel-title">{% trans "Import FAT CSV" %}</h3>
9
+ </div>
10
+ <div class="panel-body">
11
+ <p>{% trans "Upload your 30 or 90 days FAT CSV file here. The system will automatically parse all columns, including any dynamic fleet types." %}</p>
12
+ <form method="POST" enctype="multipart/form-data">
13
+ {% csrf_token %}
14
+ {% bootstrap_form form %}
15
+ <button type="submit" class="btn btn-primary">{% trans "Upload" %}</button>
16
+ <a href="{% url 'fatanalysis:index' %}" class="btn btn-default">{% trans "Cancel" %}</a>
17
+ </form>
18
+ </div>
19
+ </div>
20
+ {% endblock %}
@@ -0,0 +1,94 @@
1
+ {% extends "fatanalysis/base.html" %}
2
+ {% load i18n %}
3
+
4
+ {% block fatanalysis_content %}
5
+ <div class="row">
6
+ <div class="col-md-12">
7
+ <a href="{% url 'fatanalysis:period_list' %}" class="btn btn-default pull-right" style="margin-left: 10px;">
8
+ <i class="fas fa-list"></i> {% trans "Manage Periods" %}
9
+ </a>
10
+ <a href="{% url 'fatanalysis:import_csv' %}" class="btn btn-primary pull-right">
11
+ <i class="fas fa-upload"></i> {% trans "Import CSV" %}
12
+ </a>
13
+ </div>
14
+ </div>
15
+ <br>
16
+
17
+ <div class="panel panel-default">
18
+ <div class="panel-heading">
19
+ <h3 class="panel-title">{% trans "FAT Trend Over Time (Alliance Total)" %}</h3>
20
+ </div>
21
+ <div class="panel-body">
22
+ <canvas id="trendChart" height="100"></canvas>
23
+ </div>
24
+ </div>
25
+
26
+ <div class="row">
27
+ <div class="col-md-6">
28
+ <div class="panel panel-default text-center">
29
+ <div class="panel-body">
30
+ <h3>{% trans "30 Days Dashboard" %}</h3>
31
+ <p>{% trans "View the latest 30 days FATs per character." %}</p>
32
+ <a href="{% url 'fatanalysis:overview_30' %}" class="btn btn-primary btn-lg">
33
+ <i class="fas fa-calendar-alt"></i> {% trans "30 Days Overview" %}
34
+ </a>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ <div class="col-md-6">
39
+ <div class="panel panel-default text-center">
40
+ <div class="panel-body">
41
+ <h3>{% trans "90 Days Dashboard" %}</h3>
42
+ <p>{% trans "View the latest 90 days FATs per character." %}</p>
43
+ <a href="{% url 'fatanalysis:overview_90' %}" class="btn btn-primary btn-lg">
44
+ <i class="fas fa-calendar-alt"></i> {% trans "90 Days Overview" %}
45
+ </a>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ </div>
50
+ {% endblock %}
51
+
52
+ {% block extra_javascript %}
53
+ {{ block.super }}
54
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
55
+ <script>
56
+ $(document).ready(function() {
57
+
58
+ // Trend Chart
59
+ const trendCtx = document.getElementById('trendChart').getContext('2d');
60
+ new Chart(trendCtx, {
61
+ type: 'bar',
62
+ data: {
63
+ labels: {{ trend_labels|safe }},
64
+ datasets: [
65
+ {
66
+ label: '{% trans "30 Days FATs" %}',
67
+ data: {{ trend_30|safe }},
68
+ borderColor: '#36A2EB',
69
+ backgroundColor: 'rgba(54, 162, 235, 0.2)',
70
+ tension: 0.1,
71
+ fill: true
72
+ },
73
+ {
74
+ label: '{% trans "90 Days FATs" %}',
75
+ data: {{ trend_90|safe }},
76
+ borderColor: '#FF6384',
77
+ backgroundColor: 'rgba(255, 99, 132, 0.2)',
78
+ tension: 0.1,
79
+ fill: true
80
+ }
81
+ ]
82
+ },
83
+ options: {
84
+ responsive: true,
85
+ scales: {
86
+ y: {
87
+ beginAtZero: true
88
+ }
89
+ }
90
+ }
91
+ });
92
+ });
93
+ </script>
94
+ {% endblock %}
@@ -0,0 +1,141 @@
1
+ {% extends "fatanalysis/base.html" %}
2
+ {% load i18n %}
3
+
4
+ {% block fatanalysis_content %}
5
+ <div class="row">
6
+ <div class="col-md-12">
7
+ <a href="{% url 'fatanalysis:index' %}" class="btn btn-default pull-right">
8
+ <i class="fas fa-arrow-left"></i> {% trans "Back to Dashboard" %}
9
+ </a>
10
+ <h2>{{ title }} <small>({{ period.upload_date|date:"Y-m-d"|default:"No uploads yet" }})</small></h2>
11
+ </div>
12
+ </div>
13
+ {% if period %}
14
+ <div class="row">
15
+ <div class="col-md-12">
16
+ <div class="panel panel-default">
17
+ <div class="panel-heading">
18
+ <h3 class="panel-title">{% trans "Historical FAT Trend" %} ({{ period_type }} {% trans "Days" %})</h3>
19
+ </div>
20
+ <div class="panel-body">
21
+ <canvas id="historicalTrendChart" height="100"></canvas>
22
+ </div>
23
+ </div>
24
+ </div>
25
+ </div>
26
+
27
+ <div class="row">
28
+ <div class="col-md-4">
29
+ <div class="panel panel-default">
30
+ <div class="panel-heading">
31
+ <h3 class="panel-title">{% trans "Top 10 Players" %}</h3>
32
+ </div>
33
+ <div class="panel-body">
34
+ <canvas id="topPlayersChart"></canvas>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ <div class="col-md-8">
39
+ <div class="panel panel-default">
40
+ <div class="panel-heading">
41
+ <h3 class="panel-title">{% trans "All Players" %}</h3>
42
+ </div>
43
+ <div class="panel-body">
44
+ <table class="table table-striped table-hover" id="overview-table">
45
+ <thead>
46
+ <tr>
47
+ <th>{% trans "Character" %}</th>
48
+ <th>{% trans "Total FATs" %}</th>
49
+ {% for header in dynamic_headers %}
50
+ <th>{{ header }}</th>
51
+ {% endfor %}
52
+ </tr>
53
+ </thead>
54
+ <tbody>
55
+ {% for entry in entries %}
56
+ <tr>
57
+ <td>
58
+ <a href="{% url 'fatanalysis:player_detail' character_name=entry.character_name period_type=period_type %}">
59
+ {{ entry.character_name }}
60
+ </a>
61
+ </td>
62
+ <td><strong>{{ entry.total_fats }}</strong></td>
63
+ {% for value in entry.dynamic_values %}
64
+ <td>{{ value }}</td>
65
+ {% endfor %}
66
+ </tr>
67
+ {% empty %}
68
+ <tr>
69
+ <td colspan="{{ dynamic_headers|length|add:2 }}" class="text-center">{% trans "No FAT data available." %}</td>
70
+ </tr>
71
+ {% endfor %}
72
+ </tbody>
73
+ </table>
74
+ </div>
75
+ </div>
76
+ </div>
77
+ </div>
78
+ {% else %}
79
+ <div class="alert alert-info">
80
+ {% trans "No uploads found for this period type yet." %}
81
+ </div>
82
+ {% endif %}
83
+ {% endblock %}
84
+
85
+ {% block extra_javascript %}
86
+ {{ block.super }}
87
+ {% if period %}
88
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
89
+ <script>
90
+ $(document).ready(function() {
91
+ $('#overview-table').DataTable({
92
+ "order": [[ 1, "desc" ]]
93
+ });
94
+
95
+ // Pie Chart for Top Players
96
+ const topCtx = document.getElementById('topPlayersChart').getContext('2d');
97
+ new Chart(topCtx, {
98
+ type: 'pie',
99
+ data: {
100
+ labels: {{ top_labels|safe }},
101
+ datasets: [{
102
+ data: {{ top_data|safe }},
103
+ backgroundColor: [
104
+ '#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF',
105
+ '#FF9F40', '#E7E9ED', '#8AC926', '#1982C4', '#6A4C93'
106
+ ]
107
+ }]
108
+ },
109
+ options: {
110
+ responsive: true
111
+ }
112
+ });
113
+
114
+ // Trend Chart
115
+ const trendCtx = document.getElementById('historicalTrendChart').getContext('2d');
116
+ new Chart(trendCtx, {
117
+ type: 'line',
118
+ data: {
119
+ labels: {{ trend_labels|safe }},
120
+ datasets: [{
121
+ label: '{{ period_type }} {% trans "Days FATs" %}',
122
+ data: {{ trend_data|safe }},
123
+ borderColor: '#36A2EB',
124
+ backgroundColor: 'rgba(54, 162, 235, 0.2)',
125
+ tension: 0.1,
126
+ fill: true
127
+ }]
128
+ },
129
+ options: {
130
+ responsive: true,
131
+ scales: {
132
+ y: {
133
+ beginAtZero: true
134
+ }
135
+ }
136
+ }
137
+ });
138
+ });
139
+ </script>
140
+ {% endif %}
141
+ {% endblock %}
@@ -0,0 +1,24 @@
1
+ {% extends "fatanalysis/base.html" %}
2
+ {% load i18n %}
3
+
4
+ {% block fatanalysis_content %}
5
+ <div class="row">
6
+ <div class="col-md-6 col-md-offset-3">
7
+ <div class="panel panel-danger">
8
+ <div class="panel-heading">
9
+ <h3 class="panel-title">{% trans "Delete Upload Period" %}</h3>
10
+ </div>
11
+ <div class="panel-body">
12
+ <p>{% trans "Are you sure you want to delete the FAT upload for" %} <strong>{{ period.get_period_type_display }}</strong> {% trans "on" %} <strong>{{ period.upload_date|date:"Y-m-d H:i" }}</strong>?</p>
13
+ <p class="text-danger">{% trans "This will also delete all associated FAT entries and data. This action cannot be undone." %}</p>
14
+
15
+ <form method="POST">
16
+ {% csrf_token %}
17
+ <button type="submit" class="btn btn-danger">{% trans "Yes, Delete" %}</button>
18
+ <a href="{% url 'fatanalysis:period_list' %}" class="btn btn-default">{% trans "Cancel" %}</a>
19
+ </form>
20
+ </div>
21
+ </div>
22
+ </div>
23
+ </div>
24
+ {% endblock %}