irie 0.0.27__py3-none-any.whl → 0.0.29__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 irie might be problematic. Click here for more details.
- irie/apps/admin_dash/__init__.py +1 -0
- irie/apps/admin_dash/admin.py +0 -0
- irie/apps/admin_dash/apps.py +6 -0
- irie/apps/admin_dash/forms.py +67 -0
- irie/apps/admin_dash/models.py +1 -0
- irie/apps/admin_dash/templatetags/__init__.py +0 -0
- irie/apps/admin_dash/templatetags/admin_material.py +86 -0
- irie/apps/admin_dash/templatetags/replace_value.py +8 -0
- irie/apps/admin_dash/urls.py +36 -0
- irie/apps/admin_dash/utils.py +462 -0
- irie/apps/admin_dash/views.py +113 -0
- irie/apps/events/views.py +4 -5
- irie/apps/inventory/filters.py +1 -1
- irie/apps/inventory/migrations/0003_asset_notes.py +18 -0
- irie/apps/inventory/models.py +11 -5
- irie/apps/inventory/urls.py +1 -0
- irie/apps/inventory/views.py +72 -33
- irie/apps/static/assets/css/brace.css +22272 -14509
- irie/apps/static/assets/css/brace.css.map +1 -1
- irie/apps/static/assets/css/brace.min.css +32 -1
- irie/apps/static/assets/img/twin.png +0 -0
- irie/apps/static/assets/js/brace.js +858 -38
- irie/apps/templates/events/event-table.html +1 -2
- irie/apps/templates/includes/asset-event-table.html +1 -1
- irie/apps/templates/includes/navigation.html +1 -1
- irie/apps/templates/includes/sidebar.html +4 -4
- irie/apps/templates/inventory/asset-profile.html +6 -1
- irie/apps/templates/inventory/asset-table.html +12 -2
- irie/apps/templates/inventory/dashboard.html +0 -1
- irie/apps/templates/layouts/base.html +1 -0
- irie/apps/templates/site/index.html +10 -10
- irie/apps/templates/site/robots.txt +42 -1
- irie/core/settings.py +1 -0
- irie/init/calid.py +95 -95
- irie/init/management/commands/init_assets.py +1 -11
- irie/init/management/commands/init_cesmd.py +19 -8
- {irie-0.0.27.dist-info → irie-0.0.29.dist-info}/METADATA +3 -2
- {irie-0.0.27.dist-info → irie-0.0.29.dist-info}/RECORD +41 -28
- {irie-0.0.27.dist-info → irie-0.0.29.dist-info}/WHEEL +1 -1
- {irie-0.0.27.dist-info → irie-0.0.29.dist-info}/entry_points.txt +0 -0
- {irie-0.0.27.dist-info → irie-0.0.29.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
from django.shortcuts import render, redirect
|
|
2
|
+
from irie.apps.admin_dash.forms import LoginForm, RegistrationForm, UserPasswordResetForm, UserSetPasswordForm, UserPasswordChangeForm
|
|
3
|
+
from django.contrib.auth import logout
|
|
4
|
+
from django.contrib.auth import views as auth_views
|
|
5
|
+
|
|
6
|
+
def index(request):
|
|
7
|
+
context = {
|
|
8
|
+
'segment': 'dashboard'
|
|
9
|
+
}
|
|
10
|
+
return render(request, 'pages/index.html', context)
|
|
11
|
+
|
|
12
|
+
def tables(request):
|
|
13
|
+
context = {
|
|
14
|
+
'segment': 'tables'
|
|
15
|
+
}
|
|
16
|
+
return render(request, 'pages/tables.html', context)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def billing(request):
|
|
20
|
+
context = {
|
|
21
|
+
'segment': 'billing'
|
|
22
|
+
}
|
|
23
|
+
return render(request, 'pages/billing.html', context)
|
|
24
|
+
|
|
25
|
+
def virtual_reality(request):
|
|
26
|
+
context = {
|
|
27
|
+
'segment': 'virtual_reality'
|
|
28
|
+
}
|
|
29
|
+
return render(request, 'pages/virtual-reality.html', context)
|
|
30
|
+
|
|
31
|
+
def rtl(request):
|
|
32
|
+
context = {
|
|
33
|
+
'segment': 'rtl'
|
|
34
|
+
}
|
|
35
|
+
return render(request, 'pages/rtl.html', context)
|
|
36
|
+
|
|
37
|
+
def notifications(request):
|
|
38
|
+
context = {
|
|
39
|
+
'segment': 'notifications'
|
|
40
|
+
}
|
|
41
|
+
return render(request, 'pages/notifications.html', context)
|
|
42
|
+
|
|
43
|
+
def profile(request):
|
|
44
|
+
context = {
|
|
45
|
+
'segment': 'profile'
|
|
46
|
+
}
|
|
47
|
+
return render(request, 'pages/profile.html', context)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def map(request):
|
|
51
|
+
context = {
|
|
52
|
+
'segment': 'map'
|
|
53
|
+
}
|
|
54
|
+
return render(request, 'pages/map.html', context)
|
|
55
|
+
|
|
56
|
+
def typography(request):
|
|
57
|
+
context = {
|
|
58
|
+
'segment': 'typography'
|
|
59
|
+
}
|
|
60
|
+
return render(request, 'pages/typography.html', context)
|
|
61
|
+
|
|
62
|
+
def icons(request):
|
|
63
|
+
context = {
|
|
64
|
+
'segment': 'icons'
|
|
65
|
+
}
|
|
66
|
+
return render(request, 'pages/icons.html', context)
|
|
67
|
+
|
|
68
|
+
def template(request):
|
|
69
|
+
context = {
|
|
70
|
+
'segment': 'template'
|
|
71
|
+
}
|
|
72
|
+
return render(request, 'pages/template.html', context)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class UserLoginView(auth_views.LoginView):
|
|
76
|
+
template_name = 'pages/sign-in.html'
|
|
77
|
+
form_class = LoginForm
|
|
78
|
+
success_url = '/'
|
|
79
|
+
|
|
80
|
+
def register(request):
|
|
81
|
+
if request.method == 'POST':
|
|
82
|
+
form = RegistrationForm(request.POST)
|
|
83
|
+
if form.is_valid():
|
|
84
|
+
form.save()
|
|
85
|
+
print('Account created successfully!')
|
|
86
|
+
return redirect('/accounts/login/')
|
|
87
|
+
else:
|
|
88
|
+
print("Registration failed!")
|
|
89
|
+
else:
|
|
90
|
+
form = RegistrationForm()
|
|
91
|
+
|
|
92
|
+
context = {'form': form}
|
|
93
|
+
return render(request, 'pages/sign-up.html', context)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class UserPasswordResetView(auth_views.PasswordResetView):
|
|
97
|
+
template_name = 'accounts/forgot-password.html'
|
|
98
|
+
form_class = UserPasswordResetForm
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class UserPasswordResetConfirmView(auth_views.PasswordResetConfirmView):
|
|
102
|
+
template_name = 'accounts/recover-password.html'
|
|
103
|
+
form_class = UserSetPasswordForm
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class UserPasswordChangeView(auth_views.PasswordChangeView):
|
|
107
|
+
template_name = 'accounts/password_change.html'
|
|
108
|
+
form_class = UserPasswordChangeForm
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def user_logout_view(request):
|
|
112
|
+
logout(request)
|
|
113
|
+
return redirect('/accounts/login/')
|
irie/apps/events/views.py
CHANGED
|
@@ -15,14 +15,14 @@ def event_table(request):
|
|
|
15
15
|
"""
|
|
16
16
|
context = {}
|
|
17
17
|
page_template = "event-table.html"
|
|
18
|
-
context["segment"] = "
|
|
18
|
+
context["segment"] = "events"
|
|
19
19
|
|
|
20
20
|
page = request.GET.get("page", 1)
|
|
21
21
|
try:
|
|
22
22
|
page = int(page)
|
|
23
23
|
except:
|
|
24
24
|
page = 1
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
asset = request.GET.get("asset", None)
|
|
27
27
|
|
|
28
28
|
if asset is not None:
|
|
@@ -31,9 +31,8 @@ def event_table(request):
|
|
|
31
31
|
else:
|
|
32
32
|
events = [i for i in sorted(EventRecord.objects.all(),
|
|
33
33
|
key=lambda x: x.motion_data["event_date"], reverse=True)]
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
paginator = Paginator(events, 15)
|
|
34
|
+
|
|
35
|
+
paginator = Paginator(events, 5)
|
|
37
36
|
|
|
38
37
|
|
|
39
38
|
# reversed(sorted(Event.objects.all(),
|
irie/apps/inventory/filters.py
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 5.1.2 on 2024-12-31 17:45
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('irie_apps_inventory', '0002_alter_asset_bridge_sensors_and_more'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AddField(
|
|
14
|
+
model_name='asset',
|
|
15
|
+
name='notes',
|
|
16
|
+
field=models.CharField(blank=True, max_length=1024, null=True),
|
|
17
|
+
),
|
|
18
|
+
]
|
irie/apps/inventory/models.py
CHANGED
|
@@ -24,21 +24,27 @@ class Corridor(models.Model):
|
|
|
24
24
|
|
|
25
25
|
class _Sensor: # (models.Model):
|
|
26
26
|
class Status:
|
|
27
|
-
active: bool
|
|
27
|
+
active: bool
|
|
28
28
|
|
|
29
|
-
status = None
|
|
29
|
+
status = None
|
|
30
30
|
|
|
31
31
|
class Station: # (models.Model):
|
|
32
|
-
sensors = None
|
|
32
|
+
sensors = None
|
|
33
33
|
assets = None
|
|
34
34
|
network = None
|
|
35
35
|
events = None
|
|
36
36
|
|
|
37
|
+
class Vulnerability: # (models.Model):
|
|
38
|
+
type = None
|
|
39
|
+
asset = None
|
|
40
|
+
notes = models.CharField(max_length=1024, blank=True, null=True)
|
|
41
|
+
|
|
37
42
|
class Asset(models.Model):
|
|
38
43
|
id = models.BigAutoField(primary_key=True)
|
|
39
44
|
cesmd = models.CharField(max_length=7, blank=True, null=True)
|
|
40
45
|
calid = models.CharField(max_length=15)
|
|
41
|
-
name = models.CharField(max_length=100,
|
|
46
|
+
name = models.CharField(max_length=100, blank=True)
|
|
47
|
+
notes = models.CharField(max_length=1024, blank=True, null=True)
|
|
42
48
|
|
|
43
49
|
is_complete = models.BooleanField(help_text="Is the asset a complete digital twin")
|
|
44
50
|
|
|
@@ -55,7 +61,7 @@ class Asset(models.Model):
|
|
|
55
61
|
|
|
56
62
|
def __str__(self):
|
|
57
63
|
return f"{self.calid} - {self.name}"
|
|
58
|
-
|
|
64
|
+
|
|
59
65
|
def get_absolute_url(self):
|
|
60
66
|
return reverse("asset_profile", args=[self.calid])
|
|
61
67
|
|
irie/apps/inventory/urls.py
CHANGED
|
@@ -18,6 +18,7 @@ urlpatterns = [
|
|
|
18
18
|
|
|
19
19
|
path("asset-table.html", views.asset_table),
|
|
20
20
|
path("asset-table/", views.asset_table, name="asset_table"),
|
|
21
|
+
path("asset_table/export", views.asset_table_export, name="asset_table_export_csv"),
|
|
21
22
|
re_path(
|
|
22
23
|
"^evaluations/(?P<event>[0-9 A-Z-]*)/(?P<cesmd>[0-9 A-Z-]*)/.*", views.asset_event_summary,
|
|
23
24
|
name="asset_event_summary"
|
irie/apps/inventory/views.py
CHANGED
|
@@ -339,6 +339,47 @@ def _make_tables(asset):
|
|
|
339
339
|
return tables
|
|
340
340
|
|
|
341
341
|
|
|
342
|
+
def _filter_asset_table(request):
|
|
343
|
+
# Copy the GET parameters and remove the 'page' parameter
|
|
344
|
+
page_query = request.GET.copy()
|
|
345
|
+
page_query.pop('page', None)
|
|
346
|
+
|
|
347
|
+
filter_set = AssetFilter(request.GET, queryset=Asset.objects.all())
|
|
348
|
+
order_query = page_query.copy()
|
|
349
|
+
if order := order_query.pop("order", None):
|
|
350
|
+
try:
|
|
351
|
+
assets = filter_set.qs.order_by(order[0])
|
|
352
|
+
except:
|
|
353
|
+
assets = sorted(filter_set.qs, key=lambda x: getattr(x, order[0]), reverse=True)
|
|
354
|
+
else:
|
|
355
|
+
assets = filter_set.qs
|
|
356
|
+
return assets, (order_query, page_query, filter_set)
|
|
357
|
+
|
|
358
|
+
# @login_required(login_url="/login/")
|
|
359
|
+
def asset_table_export(request):
|
|
360
|
+
"""
|
|
361
|
+
Returns a table of all assets in the database, paginated
|
|
362
|
+
"""
|
|
363
|
+
import csv
|
|
364
|
+
|
|
365
|
+
assets, _ = _filter_asset_table(request)
|
|
366
|
+
|
|
367
|
+
# Create HTTP response with content type as CSV
|
|
368
|
+
response = HttpResponse(content_type='text/csv')
|
|
369
|
+
response['Content-Disposition'] = 'attachment; filename="assets.csv"'
|
|
370
|
+
|
|
371
|
+
# Write to CSV
|
|
372
|
+
writer = csv.writer(response)
|
|
373
|
+
# Write headers (replace with your model field names)
|
|
374
|
+
writer.writerow(['ID', 'CGS ID', 'Name', 'District', 'Event Count'])
|
|
375
|
+
|
|
376
|
+
# Write data rows (customize according to your model fields)
|
|
377
|
+
for asset in assets:
|
|
378
|
+
district = asset.nbi_data["NBI_BRIDGE"]["Highway Agency District"].split(" - ")[-1]
|
|
379
|
+
writer.writerow([asset.calid, asset.cesmd, asset.name, district, asset.event_count])
|
|
380
|
+
|
|
381
|
+
return response
|
|
382
|
+
|
|
342
383
|
|
|
343
384
|
# @login_required(login_url="/login/")
|
|
344
385
|
def asset_table(request):
|
|
@@ -349,26 +390,13 @@ def asset_table(request):
|
|
|
349
390
|
context = {}
|
|
350
391
|
context["segment"] = "assets"
|
|
351
392
|
|
|
393
|
+
assets, (order_query, page_query, filter_set) = _filter_asset_table(request)
|
|
352
394
|
page = request.GET.get("page", 1)
|
|
353
395
|
try:
|
|
354
396
|
page = int(page)
|
|
355
397
|
except:
|
|
356
398
|
page = 1
|
|
357
399
|
|
|
358
|
-
# Copy the GET parameters and remove the 'page' parameter
|
|
359
|
-
page_query = request.GET.copy()
|
|
360
|
-
page_query.pop('page', None)
|
|
361
|
-
|
|
362
|
-
filter_set = AssetFilter(request.GET, queryset=Asset.objects.all())
|
|
363
|
-
order_query = page_query.copy()
|
|
364
|
-
if order := order_query.pop("order", None):
|
|
365
|
-
try:
|
|
366
|
-
assets = filter_set.qs.order_by(order[0])
|
|
367
|
-
except:
|
|
368
|
-
assets = sorted(filter_set.qs, key=lambda x: getattr(x, order[0]), reverse=True)
|
|
369
|
-
else:
|
|
370
|
-
assets = filter_set.qs
|
|
371
|
-
|
|
372
400
|
context["page_query"] = page_query.urlencode()
|
|
373
401
|
context["order_query"] = order_query.urlencode()
|
|
374
402
|
context["bridges"] = Paginator(assets, 10).get_page(page)
|
|
@@ -440,6 +468,7 @@ class AssetMap:
|
|
|
440
468
|
colors = {}
|
|
441
469
|
|
|
442
470
|
markers = []
|
|
471
|
+
top_markers = []
|
|
443
472
|
for b in assets:
|
|
444
473
|
lat, lon = b.coordinates
|
|
445
474
|
popup = folium.Popup(
|
|
@@ -447,30 +476,40 @@ class AssetMap:
|
|
|
447
476
|
'<a style="display: inline;" target="_blank" href="/inventory/{calid}/">{label}</a>'.format(
|
|
448
477
|
calid=b.calid,
|
|
449
478
|
label=b.calid
|
|
450
|
-
),
|
|
479
|
+
),
|
|
451
480
|
script=True
|
|
452
481
|
),
|
|
453
482
|
min_width= 50,
|
|
454
483
|
max_width=100
|
|
455
484
|
)
|
|
485
|
+
|
|
486
|
+
marker = folium.CircleMarker(
|
|
487
|
+
location=[lat, lon],
|
|
488
|
+
popup=popup,
|
|
489
|
+
color = "blue" if b.is_complete else "black",
|
|
490
|
+
fill_color=colors.get(b.id, "blue" if b.is_complete else "gray"),
|
|
491
|
+
fill=True,
|
|
492
|
+
opacity=1,
|
|
493
|
+
fill_opacity=1,
|
|
494
|
+
radius=2,
|
|
495
|
+
weight=1,
|
|
496
|
+
z_index_offset=10 if b.is_complete else 100000
|
|
497
|
+
)
|
|
456
498
|
if b.is_complete:
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
499
|
+
marker = folium.Marker(
|
|
500
|
+
location=[lat, lon],
|
|
501
|
+
popup=popup,
|
|
502
|
+
icon=folium.Icon(icon="cloud", color="blue" if not b.is_complete else "beige"),
|
|
503
|
+
z_index_offset=1000
|
|
504
|
+
)
|
|
505
|
+
top_markers.append(marker)
|
|
506
|
+
elif b.calid in {"33-0526G", "33-0395L", "33-0525G", "33-0189L", "33-0523K", "33-0443", "33-0202F", "33-0202R", "33-0524F"}:
|
|
507
|
+
pass
|
|
463
508
|
else:
|
|
464
|
-
markers.append(
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
color="black",
|
|
468
|
-
fill_color=colors.get(b.id, "gray"),
|
|
469
|
-
fill=True,
|
|
470
|
-
opacity=1,
|
|
471
|
-
fill_opacity=1,
|
|
472
|
-
radius=4,
|
|
473
|
-
weight=1,
|
|
474
|
-
z_index_offset=800
|
|
475
|
-
))
|
|
509
|
+
markers.append(marker)
|
|
510
|
+
|
|
511
|
+
markers.extend(top_markers)
|
|
476
512
|
return markers
|
|
513
|
+
|
|
514
|
+
# top_markers.extend(markers)
|
|
515
|
+
# return top_markers
|