Skip to content

Commit

Permalink
Add "Autocomplete from ..." button to Device, Sector, Node and Buildi…
Browse files Browse the repository at this point in the history
…ng (#396)

* Add "Autocomplete from ..." button to Device, Sector, Node and Building

* Add geocoding endpoint

* Refactor front-end to use new geocode API

* Use e.args[0] instead of str(e) to make the security bot happy

* Formatting fixes

* Add missing dep

* Tweak wording on non-nyc registration message
  • Loading branch information
Andrew-Dickinson authored Aug 6, 2024
1 parent b6c2415 commit d903912
Show file tree
Hide file tree
Showing 17 changed files with 641 additions and 92 deletions.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ dependencies = [
"py3-validate-email@git+https://gitea.ksol.io/karolyi/py3-validate-email#[email protected]",
"phonenumbers==8.13.*",
"requests==2.32.*",
"requests-mock==1.12.*",
"geopy==2.4.*",
"django-cors-headers==4.3.*",
"nameparser==1.1.*",
Expand Down
45 changes: 0 additions & 45 deletions src/meshapi/admin/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,3 @@
admin.site.site_header = "MeshDB Admin"
admin.site.site_title = "MeshDB Admin Portal"
admin.site.index_title = "Welcome to MeshDB Admin Portal"

device_fieldsets = [
(
"Details",
{
"fields": [
"status",
"name",
"ssid",
"ip_address",
"node",
]
},
),
(
"Location",
{
"fields": [
"latitude",
"longitude",
"altitude",
]
},
),
(
"Dates",
{
"fields": [
"install_date",
"abandon_date",
]
},
),
(
"Misc",
{
"fields": [
"model",
"type",
"uisp_id",
"notes",
]
},
),
]
21 changes: 18 additions & 3 deletions src/meshapi/admin/building.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
from typing import Iterable
from typing import Any, Iterable, Optional, Type

from django import forms
from django.contrib import admin
from django.contrib.admin import ModelAdmin
from django.db.models import QuerySet
from django.forms import ModelForm
from django.http import HttpRequest
from import_export.admin import ExportActionMixin, ImportExportModelAdmin

from meshapi.admin.inlines import BuildingLOSInline, InstallInline
from meshapi.models import Building
from meshapi.widgets import PanoramaViewer
from meshapi.widgets import AutoPopulateLocationWidget, PanoramaViewer


class BoroughFilter(admin.SimpleListFilter):
Expand Down Expand Up @@ -40,6 +41,11 @@ def queryset(self, request: HttpRequest, queryset: QuerySet[Building]) -> QueryS


class BuildingAdminForm(forms.ModelForm):
auto_populate_location_field = forms.Field(
required=False,
widget=AutoPopulateLocationWidget("Address"),
)

class Meta:
model = Building
fields = "__all__"
Expand Down Expand Up @@ -90,9 +96,10 @@ class BuildingAdmin(ImportExportModelAdmin, ExportActionMixin):
},
),
(
"NYC Information",
"Coordinates & NYC BIN",
{
"fields": [
"auto_populate_location_field",
"bin",
"latitude",
"longitude",
Expand Down Expand Up @@ -120,4 +127,12 @@ class BuildingAdmin(ImportExportModelAdmin, ExportActionMixin):
),
]
inlines = [InstallInline, BuildingLOSInline]

def get_form(
self, request: HttpRequest, obj: Optional[Any] = None, change: bool = False, **kwargs: Any
) -> Type[ModelForm]:
form = super().get_form(request, obj, **kwargs)
form.base_fields["auto_populate_location_field"].label = ""
return form

filter_horizontal = ("nodes",)
64 changes: 61 additions & 3 deletions src/meshapi/admin/device.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
from typing import Any, Optional, Type

from django import forms
from django.contrib import admin
from django.db.models import QuerySet
from django.forms import ModelForm
from django.http import HttpRequest
from import_export.admin import ExportActionMixin, ImportExportModelAdmin

from meshapi.admin.admin import device_fieldsets
from meshapi.admin.inlines import DeviceLinkInline
from meshapi.models import Device
from meshapi.widgets import DeviceIPAddressWidget
from meshapi.widgets import AutoPopulateLocationWidget, DeviceIPAddressWidget


class DeviceAdminForm(forms.ModelForm):
auto_populate_location_field = forms.Field(
required=False,
widget=AutoPopulateLocationWidget("Node"),
)

class Meta:
model = Device
fields = "__all__"
Expand All @@ -34,9 +41,60 @@ class DeviceAdmin(ImportExportModelAdmin, ExportActionMixin):
"install_date",
"model",
]
fieldsets = device_fieldsets # type: ignore[assignment]
fieldsets = [
(
"Details",
{
"fields": [
"status",
"name",
"ssid",
"ip_address",
"node",
]
},
),
(
"Location",
{
"fields": [
"auto_populate_location_field",
"latitude",
"longitude",
"altitude",
]
},
),
(
"Dates",
{
"fields": [
"install_date",
"abandon_date",
]
},
),
(
"Misc",
{
"fields": [
"model",
"type",
"uisp_id",
"notes",
]
},
),
]
inlines = [DeviceLinkInline]

def get_form(
self, request: HttpRequest, obj: Optional[Any] = None, change: bool = False, **kwargs: Any
) -> Type[ModelForm]:
form = super().get_form(request, obj, **kwargs)
form.base_fields["auto_populate_location_field"].label = ""
return form

def get_queryset(self, request: HttpRequest) -> QuerySet[Device]:
# Get the base queryset
queryset = super().get_queryset(request)
Expand Down
18 changes: 17 additions & 1 deletion src/meshapi/admin/node.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from typing import Any, Optional
from typing import Any, Optional, Type

import tablib
from django import forms
from django.contrib import admin
from django.forms import ModelForm
from django.http import HttpRequest
from import_export import resources
from import_export.admin import ExportActionMixin, ImportExportModelAdmin

Expand All @@ -16,6 +18,7 @@
SectorInline,
)
from meshapi.models import Building, Node
from meshapi.widgets import AutoPopulateLocationWidget

admin.site.site_header = "MeshDB Admin"
admin.site.site_title = "MeshDB Admin Portal"
Expand All @@ -34,6 +37,11 @@ class Meta:


class NodeAdminForm(forms.ModelForm):
auto_populate_location_field = forms.Field(
required=False,
widget=AutoPopulateLocationWidget("Building"),
)

class Meta:
model = Node
fields = "__all__"
Expand Down Expand Up @@ -66,6 +74,7 @@ class NodeAdmin(ImportExportModelAdmin, ExportActionMixin):
"Location",
{
"fields": [
"auto_populate_location_field",
"latitude",
"longitude",
"altitude",
Expand Down Expand Up @@ -100,5 +109,12 @@ class NodeAdmin(ImportExportModelAdmin, ExportActionMixin):
NodeLinkInline,
]

def get_form(
self, request: HttpRequest, obj: Optional[Any] = None, change: bool = False, **kwargs: Any
) -> Type[ModelForm]:
form = super().get_form(request, obj, **kwargs)
form.base_fields["auto_populate_location_field"].label = ""
return form

def address(self, obj: Node) -> Optional[Building]:
return obj.buildings.first()
18 changes: 14 additions & 4 deletions src/meshapi/admin/sector.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
from django import forms
from typing import Any, Optional, Type

from django.contrib import admin
from django.forms import ModelForm
from django.http import HttpRequest
from import_export.admin import ExportActionMixin, ImportExportModelAdmin

from meshapi.admin.admin import device_fieldsets
from meshapi.admin.device import DeviceAdmin, DeviceAdminForm
from meshapi.admin.inlines import DeviceLinkInline
from meshapi.models import Sector


class SectorAdminForm(forms.ModelForm):
class SectorAdminForm(DeviceAdminForm):
class Meta:
model = Sector
fields = "__all__"
Expand All @@ -29,7 +32,7 @@ class SectorAdmin(ImportExportModelAdmin, ExportActionMixin):
"model",
]
inlines = [DeviceLinkInline]
fieldsets = device_fieldsets + [
fieldsets = DeviceAdmin.fieldsets + [
(
"Sector Attributes",
{
Expand All @@ -41,3 +44,10 @@ class SectorAdmin(ImportExportModelAdmin, ExportActionMixin):
},
),
] # type: ignore[assignment]

def get_form(
self, request: HttpRequest, obj: Optional[Any] = None, change: bool = False, **kwargs: Any
) -> Type[ModelForm]:
form = super().get_form(request, obj, change, **kwargs)
form.base_fields["auto_populate_location_field"].label = ""
return form
Binary file added src/meshapi/static/admin/magic_wand.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions src/meshapi/static/widgets/auto_populate_location.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

.disabled-button {
background-color: #ddd; /* Light gray background */
color: #999; /* Dim text color */
border: 1px solid #ccc; /* Light gray border */
cursor: not-allowed; /* Change cursor to indicate not clickable */
opacity: 0.6; /* Reduce opacity to visually indicate disabled state */
pointer-events: none; /* Disable pointer events */
}

.geocode-error {
margin-top: 20px;
padding: 10px;
border: 1px red;
color: red;
background: pink;
}
Loading

0 comments on commit d903912

Please sign in to comment.