NEMO-CE 7.3.5__py3-none-any.whl → 7.3.7__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.
- NEMO/admin.py +12 -1
- NEMO/migrations/0141_toolqualificationexpiration.py +103 -0
- NEMO/models.py +81 -15
- NEMO/templates/calendar/calendar.html +3 -1
- NEMO/templates/customizations/customizations_tool.html +5 -88
- NEMO/templates/customizations/customizations_training.html +9 -0
- NEMO/templates/tool_control/tool_status.html +2 -2
- NEMO/templates/tool_control/usage_data.html +46 -6
- NEMO/templates/training_new/training_base.html +11 -8
- NEMO/tests/test_tools/test_tool_qualification_expiration.py +40 -30
- NEMO/views/api.py +6 -1
- NEMO/views/calendar.py +2 -3
- NEMO/views/customization.py +2 -9
- NEMO/views/timed_services.py +37 -28
- NEMO/views/tool_control.py +52 -24
- NEMO/views/training_new.py +4 -0
- {nemo_ce-7.3.5.dist-info → nemo_ce-7.3.7.dist-info}/METADATA +1 -1
- {nemo_ce-7.3.5.dist-info → nemo_ce-7.3.7.dist-info}/RECORD +22 -21
- {nemo_ce-7.3.5.dist-info → nemo_ce-7.3.7.dist-info}/WHEEL +1 -1
- {nemo_ce-7.3.5.dist-info → nemo_ce-7.3.7.dist-info}/entry_points.txt +0 -0
- {nemo_ce-7.3.5.dist-info → nemo_ce-7.3.7.dist-info}/licenses/LICENSE +0 -0
- {nemo_ce-7.3.5.dist-info → nemo_ce-7.3.7.dist-info}/top_level.txt +0 -0
NEMO/admin.py
CHANGED
|
@@ -287,7 +287,7 @@ class ToolAdmin(admin.ModelAdmin):
|
|
|
287
287
|
"parent_tool",
|
|
288
288
|
"_category",
|
|
289
289
|
"_operation_mode",
|
|
290
|
-
"
|
|
290
|
+
"qualified_users",
|
|
291
291
|
"_problem_shutdown_enabled",
|
|
292
292
|
"_reservation_required",
|
|
293
293
|
"_logout_grace_period",
|
|
@@ -342,6 +342,17 @@ class ToolAdmin(admin.ModelAdmin):
|
|
|
342
342
|
)
|
|
343
343
|
},
|
|
344
344
|
),
|
|
345
|
+
(
|
|
346
|
+
"Qualification expiration",
|
|
347
|
+
{
|
|
348
|
+
"fields": (
|
|
349
|
+
"_qualification_reminder_days",
|
|
350
|
+
"_qualification_expiration_days",
|
|
351
|
+
"_qualification_expiration_never_used_days",
|
|
352
|
+
"_qualification_notification_email",
|
|
353
|
+
)
|
|
354
|
+
},
|
|
355
|
+
),
|
|
345
356
|
(
|
|
346
357
|
"Area Access",
|
|
347
358
|
{
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Generated by Django 4.2.27 on 2026-01-26 20:42
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
import django.core.validators
|
|
6
|
+
import django.db.models.deletion
|
|
7
|
+
from django.db import migrations, models
|
|
8
|
+
|
|
9
|
+
import NEMO.fields
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def migrate_tool_qualification_expiration_forward(apps, schema_editor):
|
|
13
|
+
Tool = apps.get_model("NEMO", "Tool")
|
|
14
|
+
Customization = apps.get_model("NEMO", "Customization")
|
|
15
|
+
tool_qualification_reminder_days = Customization.objects.filter(name="tool_qualification_reminder_days").first()
|
|
16
|
+
tool_qualification_expiration_days = Customization.objects.filter(name="tool_qualification_expiration_days").first()
|
|
17
|
+
tool_qualification_expiration_never_used_days = Customization.objects.filter(
|
|
18
|
+
name="tool_qualification_expiration_never_used_days"
|
|
19
|
+
).first()
|
|
20
|
+
tool_qualification_notification = Customization.objects.filter(name="tool_qualification_cc").first()
|
|
21
|
+
for tool in Tool.objects.filter(_qualifications_never_expire=False, parent_tool__isnull=True):
|
|
22
|
+
if tool_qualification_expiration_days or tool_qualification_expiration_never_used_days:
|
|
23
|
+
if tool_qualification_reminder_days and tool_qualification_reminder_days.value:
|
|
24
|
+
tool._qualification_reminder_days = tool_qualification_reminder_days.value
|
|
25
|
+
if tool_qualification_expiration_days and tool_qualification_expiration_days.value:
|
|
26
|
+
tool._qualification_expiration_days = tool_qualification_expiration_days.value
|
|
27
|
+
if tool_qualification_expiration_never_used_days and tool_qualification_expiration_never_used_days.value:
|
|
28
|
+
tool._qualification_expiration_never_used_days = tool_qualification_expiration_never_used_days.value
|
|
29
|
+
if tool_qualification_notification and tool_qualification_notification.value:
|
|
30
|
+
tool._qualification_notification_email = tool_qualification_notification.value
|
|
31
|
+
tool.save()
|
|
32
|
+
if tool_qualification_reminder_days:
|
|
33
|
+
tool_qualification_reminder_days.delete()
|
|
34
|
+
if tool_qualification_expiration_days:
|
|
35
|
+
tool_qualification_expiration_days.delete()
|
|
36
|
+
if tool_qualification_expiration_never_used_days:
|
|
37
|
+
tool_qualification_expiration_never_used_days.delete()
|
|
38
|
+
if tool_qualification_notification:
|
|
39
|
+
tool_qualification_notification.delete()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class Migration(migrations.Migration):
|
|
43
|
+
|
|
44
|
+
dependencies = [
|
|
45
|
+
("NEMO", "0140_alter_user_options"),
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
operations = [
|
|
49
|
+
migrations.AddField(
|
|
50
|
+
model_name="tool",
|
|
51
|
+
name="_qualification_expiration_days",
|
|
52
|
+
field=models.PositiveIntegerField(
|
|
53
|
+
db_column="qualification_expiration_days",
|
|
54
|
+
blank=True,
|
|
55
|
+
help_text="The number of days from the user’s last tool use until the qualification expires.",
|
|
56
|
+
null=True,
|
|
57
|
+
),
|
|
58
|
+
),
|
|
59
|
+
migrations.AddField(
|
|
60
|
+
model_name="tool",
|
|
61
|
+
name="_qualification_expiration_never_used_days",
|
|
62
|
+
field=models.PositiveIntegerField(
|
|
63
|
+
db_column="qualification_expiration_never_used_days",
|
|
64
|
+
blank=True,
|
|
65
|
+
help_text="Number of days from the user's first qualification until the qualification expires (if the user never used the tool).",
|
|
66
|
+
null=True,
|
|
67
|
+
),
|
|
68
|
+
),
|
|
69
|
+
migrations.AddField(
|
|
70
|
+
model_name="tool",
|
|
71
|
+
name="_qualification_notification_email",
|
|
72
|
+
field=NEMO.fields.MultiEmailField(
|
|
73
|
+
db_column="qualification_notification_email",
|
|
74
|
+
blank=True,
|
|
75
|
+
help_text="The email addresses to cc on tool qualification expiration and on reminders. Separate multiple emails with commas.",
|
|
76
|
+
max_length=2000,
|
|
77
|
+
null=True,
|
|
78
|
+
),
|
|
79
|
+
),
|
|
80
|
+
migrations.AddField(
|
|
81
|
+
model_name="tool",
|
|
82
|
+
name="_qualification_reminder_days",
|
|
83
|
+
field=models.CharField(
|
|
84
|
+
db_column="qualification_reminder_days",
|
|
85
|
+
blank=True,
|
|
86
|
+
help_text="The (optional) number of days to send a reminder prior to the user's tool qualification expiration (below). A comma-separated list can be used for multiple reminders. This applies to both expiration cases.",
|
|
87
|
+
max_length=255,
|
|
88
|
+
null=True,
|
|
89
|
+
validators=[
|
|
90
|
+
django.core.validators.RegexValidator(
|
|
91
|
+
re.compile("^\\d+(?:,\\d+)*\\Z"),
|
|
92
|
+
code="invalid",
|
|
93
|
+
message="Enter only digits separated by commas.",
|
|
94
|
+
)
|
|
95
|
+
],
|
|
96
|
+
),
|
|
97
|
+
),
|
|
98
|
+
migrations.RunPython(migrate_tool_qualification_expiration_forward, migrations.RunPython.noop),
|
|
99
|
+
migrations.RemoveField(
|
|
100
|
+
model_name="tool",
|
|
101
|
+
name="_qualifications_never_expire",
|
|
102
|
+
),
|
|
103
|
+
]
|
NEMO/models.py
CHANGED
|
@@ -1349,10 +1349,32 @@ class Tool(SerializationByNameModel):
|
|
|
1349
1349
|
_interlock = models.OneToOneField(
|
|
1350
1350
|
"Interlock", db_column="interlock_id", blank=True, null=True, on_delete=models.SET_NULL
|
|
1351
1351
|
)
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
db_column="
|
|
1355
|
-
|
|
1352
|
+
# Qualification expiration fields
|
|
1353
|
+
_qualification_reminder_days = models.CharField(
|
|
1354
|
+
db_column="qualification_reminder_days",
|
|
1355
|
+
null=True,
|
|
1356
|
+
blank=True,
|
|
1357
|
+
max_length=CHAR_FIELD_MEDIUM_LENGTH,
|
|
1358
|
+
validators=[validate_comma_separated_integer_list],
|
|
1359
|
+
help_text="The (optional) number of days to send a reminder prior to the user's tool qualification expiration (below). A comma-separated list can be used for multiple reminders. This applies to both expiration cases.",
|
|
1360
|
+
)
|
|
1361
|
+
_qualification_expiration_days = models.PositiveIntegerField(
|
|
1362
|
+
db_column="qualification_expiration_days",
|
|
1363
|
+
null=True,
|
|
1364
|
+
blank=True,
|
|
1365
|
+
help_text="The number of days from the user’s last tool use until the qualification expires.",
|
|
1366
|
+
)
|
|
1367
|
+
_qualification_expiration_never_used_days = models.PositiveIntegerField(
|
|
1368
|
+
db_column="qualification_expiration_never_used_days",
|
|
1369
|
+
null=True,
|
|
1370
|
+
blank=True,
|
|
1371
|
+
help_text="Number of days from the user's first qualification until the qualification expires (if the user never used the tool).",
|
|
1372
|
+
)
|
|
1373
|
+
_qualification_notification_email = fields.MultiEmailField(
|
|
1374
|
+
db_column="qualification_notification_email",
|
|
1375
|
+
null=True,
|
|
1376
|
+
blank=True,
|
|
1377
|
+
help_text="The email addresses to cc on tool qualification expiration and on reminders. Separate multiple emails with commas.",
|
|
1356
1378
|
)
|
|
1357
1379
|
# Policy fields:
|
|
1358
1380
|
_requires_area_access = TreeForeignKey(
|
|
@@ -1530,17 +1552,6 @@ class Tool(SerializationByNameModel):
|
|
|
1530
1552
|
self.raise_setter_error_if_child_tool("category")
|
|
1531
1553
|
self._category = value
|
|
1532
1554
|
|
|
1533
|
-
@property
|
|
1534
|
-
def qualifications_never_expire(self):
|
|
1535
|
-
return (
|
|
1536
|
-
self.parent_tool.qualifications_never_expire if self.is_child_tool() else self._qualifications_never_expire
|
|
1537
|
-
)
|
|
1538
|
-
|
|
1539
|
-
@qualifications_never_expire.setter
|
|
1540
|
-
def qualifications_never_expire(self, value):
|
|
1541
|
-
self.raise_setter_error_if_child_tool("qualifications_never_expire")
|
|
1542
|
-
self._qualifications_never_expire = value
|
|
1543
|
-
|
|
1544
1555
|
@property
|
|
1545
1556
|
def description(self):
|
|
1546
1557
|
return self.parent_tool.description if self.is_child_tool() else self._description
|
|
@@ -1689,6 +1700,56 @@ class Tool(SerializationByNameModel):
|
|
|
1689
1700
|
self.raise_setter_error_if_child_tool("interlock")
|
|
1690
1701
|
self._interlock = value
|
|
1691
1702
|
|
|
1703
|
+
@property
|
|
1704
|
+
def qualification_reminder_days(self):
|
|
1705
|
+
return (
|
|
1706
|
+
self.parent_tool.qualification_reminder_days if self.is_child_tool() else self._qualification_reminder_days
|
|
1707
|
+
)
|
|
1708
|
+
|
|
1709
|
+
@qualification_reminder_days.setter
|
|
1710
|
+
def qualification_reminder_days(self, value):
|
|
1711
|
+
self.raise_setter_error_if_child_tool("qualification_reminder_days")
|
|
1712
|
+
self._qualification_reminder_days = value
|
|
1713
|
+
|
|
1714
|
+
@property
|
|
1715
|
+
def qualification_expiration_days(self):
|
|
1716
|
+
return (
|
|
1717
|
+
self.parent_tool.qualification_expiration_days
|
|
1718
|
+
if self.is_child_tool()
|
|
1719
|
+
else self._qualification_expiration_days
|
|
1720
|
+
)
|
|
1721
|
+
|
|
1722
|
+
@qualification_expiration_days.setter
|
|
1723
|
+
def qualification_expiration_days(self, value):
|
|
1724
|
+
self.raise_setter_error_if_child_tool("qualification_expiration_days")
|
|
1725
|
+
self._qualification_expiration_days = value
|
|
1726
|
+
|
|
1727
|
+
@property
|
|
1728
|
+
def qualification_expiration_never_used_days(self):
|
|
1729
|
+
return (
|
|
1730
|
+
self.parent_tool.qualification_expiration_never_used_days
|
|
1731
|
+
if self.is_child_tool()
|
|
1732
|
+
else self._qualification_expiration_never_used_days
|
|
1733
|
+
)
|
|
1734
|
+
|
|
1735
|
+
@qualification_expiration_never_used_days.setter
|
|
1736
|
+
def qualification_expiration_never_used_days(self, value):
|
|
1737
|
+
self.raise_setter_error_if_child_tool("qualification_expiration_never_used_days")
|
|
1738
|
+
self._qualification_expiration_never_used_days = value
|
|
1739
|
+
|
|
1740
|
+
@property
|
|
1741
|
+
def qualification_notification_email(self):
|
|
1742
|
+
return (
|
|
1743
|
+
self.parent_tool.qualification_notification_email
|
|
1744
|
+
if self.is_child_tool()
|
|
1745
|
+
else self._qualification_notification_email
|
|
1746
|
+
)
|
|
1747
|
+
|
|
1748
|
+
@qualification_notification_email.setter
|
|
1749
|
+
def qualification_notification_email(self, value):
|
|
1750
|
+
self.raise_setter_error_if_child_tool("qualification_notification_email")
|
|
1751
|
+
self._qualification_notification_email = value
|
|
1752
|
+
|
|
1692
1753
|
@property
|
|
1693
1754
|
def requires_area_access(self):
|
|
1694
1755
|
return self.parent_tool.requires_area_access if self.is_child_tool() else self._requires_area_access
|
|
@@ -2379,6 +2440,11 @@ class Tool(SerializationByNameModel):
|
|
|
2379
2440
|
else:
|
|
2380
2441
|
raise ValueError(f"A {'project' if user else 'user'} must be provided for usage questions")
|
|
2381
2442
|
|
|
2443
|
+
def get_qualification_reminder_days(self) -> List[int]:
|
|
2444
|
+
if not self.qualification_reminder_days:
|
|
2445
|
+
return []
|
|
2446
|
+
return [int(days) for days in self.qualification_reminder_days.split(",") if days]
|
|
2447
|
+
|
|
2382
2448
|
def clean(self):
|
|
2383
2449
|
errors = {}
|
|
2384
2450
|
if self.parent_tool_id:
|
|
@@ -646,7 +646,7 @@ function create_calendar()
|
|
|
646
646
|
{
|
|
647
647
|
"header":
|
|
648
648
|
{
|
|
649
|
-
left: "prev,next today{% if user.is_staff or user.is_tool_staff %} proxyReservation scheduledOutage{% endif %}{% if customizations|get_item:"training_module_enabled" == "enabled" %}{% if user|is_trainer %} scheduleTraining{% endif %} requestTraining{% endif %} login logout",
|
|
649
|
+
left: "prev,next today{% if user.is_staff or user.is_tool_staff %} proxyReservation scheduledOutage{% endif %}{% if customizations|get_item:"training_module_enabled" == "enabled" %}{% if user|is_trainer %} scheduleTraining{% endif %} {% if customizations|get_item:"training_requests_enabled" == "enabled" %}requestTraining{% endif %}{% endif %} login logout",
|
|
650
650
|
center: "title",
|
|
651
651
|
right: "agendaDay,agendaWeek,month"
|
|
652
652
|
},
|
|
@@ -752,6 +752,7 @@ function reserve_for_someone_else_callback(response, status, xml_http_request)
|
|
|
752
752
|
|
|
753
753
|
function request_training()
|
|
754
754
|
{
|
|
755
|
+
{% if customizations|get_item:"training_requests_enabled" == "enabled" %}
|
|
755
756
|
let item = get_selected_item();
|
|
756
757
|
if (item && item !== "personal_schedule" && item !== "all_tools" && item !== "all_areas" && item !== "all_areastools")
|
|
757
758
|
{
|
|
@@ -779,6 +780,7 @@ function request_training()
|
|
|
779
780
|
}
|
|
780
781
|
ajax_get(url, event_changes, function(response, status, xml_http_request) { return event_creation_success_callback(response, status, xml_http_request, post_data, callback) }, [ajax_failure_callback("Training request creation failed")])
|
|
781
782
|
}
|
|
783
|
+
{% endif %}
|
|
782
784
|
}
|
|
783
785
|
|
|
784
786
|
function login_to_area()
|
|
@@ -623,97 +623,14 @@
|
|
|
623
623
|
</div>
|
|
624
624
|
</div>
|
|
625
625
|
<div class="customization-separation" style="margin-bottom: 15px"></div>
|
|
626
|
-
<
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
<p>
|
|
630
|
-
The <a href="{% url 'customization' 'templates' %}?#tool_qualification_expiration_email_id">user tool qualification expiration email</a> need to be set to enable this feature.
|
|
631
|
-
</p>
|
|
632
|
-
<br />
|
|
633
|
-
<div class="form-group {% if errors.tool_qualification_reminder_days %}has-error{% endif %}">
|
|
634
|
-
<label class="control-label col-md-3" for="tool_qualification_reminder_days">Reminder days</label>
|
|
635
|
-
<div class="col-md-5">
|
|
636
|
-
<input type="text"
|
|
637
|
-
id="tool_qualification_reminder_days"
|
|
638
|
-
name="tool_qualification_reminder_days"
|
|
639
|
-
class="form-control"
|
|
640
|
-
value="{% if errors.tool_qualification_reminder_days %}{{ errors.tool_qualification_reminder_days.value }}{% else %}{{ tool_qualification_reminder_days }}{% endif %}" />
|
|
641
|
-
</div>
|
|
642
|
-
<div class="col-md-offset-3 col-md-9 help-block light-grey">
|
|
643
|
-
{% if errors.tool_qualification_reminder_days %}
|
|
644
|
-
{{ errors.tool_qualification_reminder_days.error }}
|
|
645
|
-
{% else %}
|
|
646
|
-
The (optional) number of days to send a reminder prior to the user's tool qualification expiration (below). A comma-separated list can be used for multiple reminders. This applies to both expiration cases.
|
|
647
|
-
{% endif %}
|
|
648
|
-
</div>
|
|
649
|
-
</div>
|
|
650
|
-
<div class="form-group {% if errors.tool_qualification_expiration_days %}has-error{% endif %}">
|
|
651
|
-
<label class="control-label col-md-3" for="tool_qualification_expiration_days">
|
|
652
|
-
Expiration days (previous tool usage)
|
|
653
|
-
</label>
|
|
654
|
-
<div class="col-md-5">
|
|
655
|
-
<input type="number"
|
|
656
|
-
step="1"
|
|
657
|
-
id="tool_qualification_expiration_days"
|
|
658
|
-
name="tool_qualification_expiration_days"
|
|
659
|
-
class="form-control"
|
|
660
|
-
value="{% if errors.tool_qualification_expiration_days %}{{ errors.tool_qualification_expiration_days.value }}{% else %}{{ tool_qualification_expiration_days }}{% endif %}" />
|
|
661
|
-
</div>
|
|
662
|
-
<div class="col-md-offset-3 col-md-9 help-block light-grey">
|
|
663
|
-
{% if errors.tool_qualification_expiration_days %}
|
|
664
|
-
{{ errors.tool_qualification_expiration_days.error }}
|
|
665
|
-
{% else %}
|
|
666
|
-
The number of days before the user's tool qualification expires since the user last used the tool.
|
|
667
|
-
{% endif %}
|
|
668
|
-
</div>
|
|
669
|
-
</div>
|
|
670
|
-
<div class="form-group {% if errors.tool_qualification_expiration_never_used_days %}has-error{% endif %}">
|
|
671
|
-
<label class="control-label col-md-3" for="tool_qualification_expiration_never_used_days">
|
|
672
|
-
Expiration days (no tool usage)
|
|
673
|
-
</label>
|
|
674
|
-
<div class="col-md-5">
|
|
675
|
-
<input type="number"
|
|
676
|
-
step="1"
|
|
677
|
-
id="tool_qualification_expiration_never_used_days"
|
|
678
|
-
name="tool_qualification_expiration_never_used_days"
|
|
679
|
-
class="form-control"
|
|
680
|
-
value="{% if errors.tool_qualification_expiration_never_used_days %}{{ errors.tool_qualification_expiration_never_used_days.value }}{% else %}{{ tool_qualification_expiration_never_used_days }}{% endif %}" />
|
|
681
|
-
</div>
|
|
682
|
-
<div class="col-md-offset-3 col-md-9 help-block light-grey">
|
|
683
|
-
{% if errors.tool_qualification_expiration_never_used_days %}
|
|
684
|
-
{{ errors.tool_qualification_expiration_never_used_days.error }}
|
|
685
|
-
{% else %}
|
|
686
|
-
The number of days before the user's tool qualification expires since the user qualified for the first time.
|
|
687
|
-
{% endif %}
|
|
688
|
-
</div>
|
|
689
|
-
</div>
|
|
690
|
-
<div class="form-group {% if errors.tool_qualification_cc %}has-error{% endif %}">
|
|
691
|
-
<label class="control-label col-md-3" for="tool_qualification_cc">Reminder/expiration CC</label>
|
|
692
|
-
<div class="col-md-5">
|
|
693
|
-
<input type="text"
|
|
694
|
-
id="tool_qualification_cc"
|
|
695
|
-
name="tool_qualification_cc"
|
|
696
|
-
class="form-control"
|
|
697
|
-
value="{% if errors.tool_qualification_cc %}{{ errors.tool_qualification_cc.value }}{% else %}{{ tool_qualification_cc }}{% endif %}"
|
|
698
|
-
placeholder="information@example.org" />
|
|
699
|
-
</div>
|
|
700
|
-
<div class="col-md-offset-3 col-md-9 help-block light-grey">
|
|
701
|
-
{% if errors.tool_qualification_cc %}
|
|
702
|
-
{{ errors.tool_qualification_cc.error }}
|
|
703
|
-
{% else %}
|
|
704
|
-
Extra email address to copy when a user's tool qualification reminder/expiration email is sent. A comma-separated list can be used.
|
|
705
|
-
{% endif %}
|
|
706
|
-
</div>
|
|
707
|
-
</div>
|
|
708
|
-
<div class="customization-separation" style="margin-bottom: 15px"></div>
|
|
709
|
-
<div class="text-center">{% button type="save" value="Save settings" %}</div>
|
|
710
|
-
</div>
|
|
711
|
-
<script type="text/javascript">
|
|
626
|
+
<div class="text-center">{% button type="save" value="Save settings" %}</div>
|
|
627
|
+
</div>
|
|
628
|
+
<script type="text/javascript">
|
|
712
629
|
$("#tool-tab-link").click(function() {setTimeout(on_tool_tab_show, 50)});
|
|
713
630
|
function on_tool_tab_show()
|
|
714
631
|
{
|
|
715
632
|
auto_size_textarea(document.getElementById('tool_control_configuration_setting_template'))
|
|
716
633
|
}
|
|
717
634
|
on_tool_tab_show();
|
|
718
|
-
|
|
719
|
-
|
|
635
|
+
</script>
|
|
636
|
+
</form>
|
|
@@ -82,6 +82,15 @@
|
|
|
82
82
|
Enable training requests/sessions scheduling
|
|
83
83
|
</label>
|
|
84
84
|
<br />
|
|
85
|
+
<input type="hidden" name="training_requests_enabled" value="off" />
|
|
86
|
+
<label>
|
|
87
|
+
<input type="checkbox"
|
|
88
|
+
name="training_requests_enabled"
|
|
89
|
+
{% if training_requests_enabled == "enabled" %}checked{% endif %}
|
|
90
|
+
value="enabled">
|
|
91
|
+
Allow users to request training (via calendar or training module)
|
|
92
|
+
</label>
|
|
93
|
+
<br />
|
|
85
94
|
<label>
|
|
86
95
|
<input type="checkbox"
|
|
87
96
|
name="training_show_in_user_requests"
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
History</a>
|
|
18
18
|
</li>
|
|
19
19
|
{% endif %}
|
|
20
|
-
{% if
|
|
20
|
+
{% if not hide_data_history or user.is_any_part_of_staff %}
|
|
21
21
|
<li style="width: 48%; text-align: center">
|
|
22
22
|
<a href="#usage_data" style="padding: 10px 5px;" onclick="load_usage_data('{{ tool.id }}');">Usage Data History</a>
|
|
23
23
|
</li>
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
<a href="#config" onclick="load_config_history('{{ tool.id }}');">Config History</a>
|
|
51
51
|
</li>
|
|
52
52
|
{% endif %}
|
|
53
|
-
{% if
|
|
53
|
+
{% if not hide_data_history or user.is_any_part_of_staff %}
|
|
54
54
|
<li>
|
|
55
55
|
<a href="#usage_data" onclick="load_usage_data('{{ tool.id }}');">Run Data History</a>
|
|
56
56
|
</li>
|
|
@@ -98,21 +98,61 @@
|
|
|
98
98
|
</div>
|
|
99
99
|
</div>
|
|
100
100
|
</form>
|
|
101
|
-
{% if run_data_table.rows or pre_run_data_table.rows %}
|
|
101
|
+
{% if data_table.rows or run_data_table.rows or pre_run_data_table.rows %}
|
|
102
102
|
<ul class="nav nav-tabs" id="usage-tabs">
|
|
103
|
+
{% if data_table.rows %}
|
|
104
|
+
<li class="active">
|
|
105
|
+
<a data-toggle="tab" href="#run-data-tab">Usage history</a>
|
|
106
|
+
</li>
|
|
107
|
+
{% endif %}
|
|
103
108
|
{% if pre_run_data_table.rows %}
|
|
104
|
-
<li
|
|
109
|
+
<li>
|
|
105
110
|
<a data-toggle="tab" href="#pre-run-data-tab">Pre-Run Data</a>
|
|
106
111
|
</li>
|
|
107
112
|
{% endif %}
|
|
108
113
|
{% if run_data_table.rows %}
|
|
109
|
-
<li
|
|
110
|
-
<a data-toggle="tab" href="#run-data-tab">Run Data</a>
|
|
114
|
+
<li>
|
|
115
|
+
<a data-toggle="tab" href="#post-run-data-tab">Post-Run Data</a>
|
|
111
116
|
</li>
|
|
112
117
|
{% endif %}
|
|
113
118
|
</ul>
|
|
114
119
|
<div class="tab-content" style="margin-bottom: 0;">
|
|
115
|
-
<div class="tab-pane
|
|
120
|
+
<div class="tab-pane active" id="run-data-tab">
|
|
121
|
+
<div class="col-md-12">
|
|
122
|
+
<div class="form-group pull-right extra-side-padding" style="padding-top: 10px">
|
|
123
|
+
{% button type="export" value="Export" onclick="load_usage_data('"|concat:tool_id|concat:"', 'all');" %}
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
<div class="panel-body">
|
|
127
|
+
{% if data_table.rows %}
|
|
128
|
+
<table class="table table-bordered table-condensed" style="margin-top: 10px">
|
|
129
|
+
<thead>
|
|
130
|
+
<tr>
|
|
131
|
+
{% for header in data_table.flat_headers %}<th>{{ header }}</th>{% endfor %}
|
|
132
|
+
</tr>
|
|
133
|
+
</thead>
|
|
134
|
+
<tbody>
|
|
135
|
+
{% for row in data_table.flat_rows %}
|
|
136
|
+
<tr>
|
|
137
|
+
{% for item in row %}
|
|
138
|
+
<td>
|
|
139
|
+
{% if item|class_name == "list" %}
|
|
140
|
+
{{ item|join:", " }}
|
|
141
|
+
{% else %}
|
|
142
|
+
{{ item|default_if_none:"" }}
|
|
143
|
+
{% endif %}
|
|
144
|
+
</td>
|
|
145
|
+
{% endfor %}
|
|
146
|
+
</tr>
|
|
147
|
+
{% endfor %}
|
|
148
|
+
</tbody>
|
|
149
|
+
</table>
|
|
150
|
+
{% else %}
|
|
151
|
+
<span class="italic">No run data was found between these dates</span>
|
|
152
|
+
{% endif %}
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
<div class="tab-pane" id="pre-run-data-tab">
|
|
116
156
|
<div class="col-md-12">
|
|
117
157
|
<div class="form-group pull-right extra-side-padding" style="padding-top: 10px">
|
|
118
158
|
{% button type="export" value="Export" onclick="load_usage_data('"|concat:tool_id|concat:"', 'pre-run');" %}
|
|
@@ -147,7 +187,7 @@
|
|
|
147
187
|
{% endif %}
|
|
148
188
|
</div>
|
|
149
189
|
</div>
|
|
150
|
-
<div class="tab-pane
|
|
190
|
+
<div class="tab-pane" id="post-run-data-tab">
|
|
151
191
|
<div class="col-md-12">
|
|
152
192
|
<div class="form-group pull-right extra-side-padding" style="padding-top: 10px">
|
|
153
193
|
{% button type="export" value="Export" onclick="load_usage_data('"|concat:tool_id|concat:"', 'run');" %}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{% extends "base.html" %}
|
|
2
2
|
{% load training_tags %}
|
|
3
|
+
{% load custom_tags_and_filters %}
|
|
3
4
|
{% block extrahead %}
|
|
4
5
|
{% load static %}
|
|
5
6
|
<script type="text/javascript" src="{% static "datetimepicker/bootstrap-datetimepicker.js" %}"></script>
|
|
@@ -13,14 +14,16 @@
|
|
|
13
14
|
{% block content %}
|
|
14
15
|
<h1 style="margin-top: 0; margin-bottom: 25px">Training dashboard</h1>
|
|
15
16
|
<ul class="nav nav-tabs">
|
|
16
|
-
{%
|
|
17
|
-
|
|
18
|
-
<
|
|
19
|
-
{
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
{% if customizations|get_item:"training_requests_enabled" == "enabled" %}
|
|
18
|
+
{% url 'training_requests' as training_requests_url %}
|
|
19
|
+
<li class="nav-item{% if training_requests_url in request.path %} active{% endif %}">
|
|
20
|
+
<a class="nav-link" href="{{ training_requests_url }}">My training requests
|
|
21
|
+
{% if training_invitation_notification_count %}
|
|
22
|
+
<span class="badge badge-tab-top">{{ training_invitation_notification_count }}</span>
|
|
23
|
+
{% endif %}
|
|
24
|
+
</a>
|
|
25
|
+
</li>
|
|
26
|
+
{% endif %}
|
|
24
27
|
{% url 'training_history' as training_history_url %}
|
|
25
28
|
<li class="nav-item{% if training_history_url in request.path %} active{% endif %}">
|
|
26
29
|
<a class="nav-link" href="{{ training_history_url }}">Training history</a>
|