irie 0.0.27__py3-none-any.whl → 0.0.28__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.

Files changed (41) hide show
  1. irie/apps/admin_dash/__init__.py +1 -0
  2. irie/apps/admin_dash/admin.py +0 -0
  3. irie/apps/admin_dash/apps.py +6 -0
  4. irie/apps/admin_dash/forms.py +67 -0
  5. irie/apps/admin_dash/models.py +1 -0
  6. irie/apps/admin_dash/templatetags/__init__.py +0 -0
  7. irie/apps/admin_dash/templatetags/admin_material.py +86 -0
  8. irie/apps/admin_dash/templatetags/replace_value.py +8 -0
  9. irie/apps/admin_dash/urls.py +36 -0
  10. irie/apps/admin_dash/utils.py +462 -0
  11. irie/apps/admin_dash/views.py +113 -0
  12. irie/apps/events/views.py +4 -5
  13. irie/apps/inventory/filters.py +1 -1
  14. irie/apps/inventory/migrations/0003_asset_notes.py +18 -0
  15. irie/apps/inventory/models.py +11 -5
  16. irie/apps/inventory/urls.py +1 -0
  17. irie/apps/inventory/views.py +72 -33
  18. irie/apps/static/assets/css/brace.css +22272 -14509
  19. irie/apps/static/assets/css/brace.css.map +1 -1
  20. irie/apps/static/assets/css/brace.min.css +32 -1
  21. irie/apps/static/assets/img/twin.png +0 -0
  22. irie/apps/static/assets/js/brace.js +858 -38
  23. irie/apps/templates/events/event-table.html +1 -2
  24. irie/apps/templates/includes/asset-event-table.html +1 -1
  25. irie/apps/templates/includes/navigation.html +1 -1
  26. irie/apps/templates/includes/sidebar.html +4 -4
  27. irie/apps/templates/inventory/asset-profile.html +6 -1
  28. irie/apps/templates/inventory/asset-table.html +12 -2
  29. irie/apps/templates/inventory/dashboard.html +0 -1
  30. irie/apps/templates/layouts/base.html +1 -0
  31. irie/apps/templates/site/index.html +9 -9
  32. irie/apps/templates/site/robots.txt +42 -1
  33. irie/core/settings.py +1 -0
  34. irie/init/calid.py +95 -95
  35. irie/init/management/commands/init_assets.py +1 -11
  36. irie/init/management/commands/init_cesmd.py +19 -8
  37. {irie-0.0.27.dist-info → irie-0.0.28.dist-info}/METADATA +3 -2
  38. {irie-0.0.27.dist-info → irie-0.0.28.dist-info}/RECORD +41 -28
  39. {irie-0.0.27.dist-info → irie-0.0.28.dist-info}/WHEEL +1 -1
  40. {irie-0.0.27.dist-info → irie-0.0.28.dist-info}/entry_points.txt +0 -0
  41. {irie-0.0.27.dist-info → irie-0.0.28.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"] = "event-table.html"
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
- # Paginator for 10 items per page
36
- paginator = Paginator(events, 15)
34
+
35
+ paginator = Paginator(events, 5)
37
36
 
38
37
 
39
38
  # reversed(sorted(Event.objects.all(),
@@ -4,7 +4,7 @@ from django.forms import CheckboxInput
4
4
  class AssetFilter(django_filters.FilterSet):
5
5
  search = django_filters.CharFilter(
6
6
  lookup_expr="icontains",
7
- field_name="name",
7
+ field_name="calid",
8
8
  label='Search'
9
9
  )
10
10
 
@@ -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
+ ]
@@ -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, blank=True)
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
 
@@ -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"
@@ -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
- markers.append(folium.Marker(
458
- location=[lat, lon],
459
- popup=popup,
460
- icon=folium.Icon(icon="cloud", color="blue" if not b.is_complete else "beige"),
461
- z_index_offset=1000
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(folium.CircleMarker(
465
- location=[lat, lon],
466
- popup=popup,
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