Drones to use AGL
This commit is contained in:
@@ -0,0 +1,34 @@
|
|||||||
|
"""Rename drone request altitude to AGL
|
||||||
|
|
||||||
|
Revision ID: 010_drone_request_agl_altitude
|
||||||
|
Revises: 009_drone_requests
|
||||||
|
Create Date: 2026-06-29 00:00:00.000000
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
revision = '010_drone_request_agl_altitude'
|
||||||
|
down_revision = '009_drone_requests'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
op.alter_column(
|
||||||
|
'drone_requests',
|
||||||
|
'maximum_elevation_ft_amsl',
|
||||||
|
new_column_name='maximum_elevation_ft_agl',
|
||||||
|
existing_type=sa.Integer(),
|
||||||
|
existing_nullable=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
op.alter_column(
|
||||||
|
'drone_requests',
|
||||||
|
'maximum_elevation_ft_agl',
|
||||||
|
new_column_name='maximum_elevation_ft_amsl',
|
||||||
|
existing_type=sa.Integer(),
|
||||||
|
existing_nullable=False,
|
||||||
|
)
|
||||||
@@ -52,7 +52,7 @@ async def _send_drone_email(drone_request, subject: str, message: str):
|
|||||||
"takeoff_time": drone_request.estimated_takeoff_at.strftime("%Y-%m-%d %H:%M"),
|
"takeoff_time": drone_request.estimated_takeoff_at.strftime("%Y-%m-%d %H:%M"),
|
||||||
"completion_time": drone_request.estimated_completion_at.strftime("%Y-%m-%d %H:%M"),
|
"completion_time": drone_request.estimated_completion_at.strftime("%Y-%m-%d %H:%M"),
|
||||||
"location": drone_request.location_description or f"{drone_request.location_latitude}, {drone_request.location_longitude}",
|
"location": drone_request.location_description or f"{drone_request.location_latitude}, {drone_request.location_longitude}",
|
||||||
"maximum_elevation_ft_amsl": drone_request.maximum_elevation_ft_amsl,
|
"maximum_elevation_ft_agl": drone_request.maximum_elevation_ft_agl,
|
||||||
"edit_url": f"{settings.base_url}/drone-request.html?token={drone_request.public_token}" if drone_request.public_token else None,
|
"edit_url": f"{settings.base_url}/drone-request.html?token={drone_request.public_token}" if drone_request.public_token else None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -70,7 +70,7 @@ async def _send_drone_submitted_email(drone_request):
|
|||||||
"takeoff_time": drone_request.estimated_takeoff_at.strftime("%Y-%m-%d %H:%M"),
|
"takeoff_time": drone_request.estimated_takeoff_at.strftime("%Y-%m-%d %H:%M"),
|
||||||
"completion_time": drone_request.estimated_completion_at.strftime("%Y-%m-%d %H:%M"),
|
"completion_time": drone_request.estimated_completion_at.strftime("%Y-%m-%d %H:%M"),
|
||||||
"location": drone_request.location_description or f"{drone_request.location_latitude}, {drone_request.location_longitude}",
|
"location": drone_request.location_description or f"{drone_request.location_latitude}, {drone_request.location_longitude}",
|
||||||
"maximum_elevation_ft_amsl": drone_request.maximum_elevation_ft_amsl,
|
"maximum_elevation_ft_agl": drone_request.maximum_elevation_ft_agl,
|
||||||
"edit_url": f"{settings.base_url}/drone-request.html?token={drone_request.public_token}" if drone_request.public_token else None,
|
"edit_url": f"{settings.base_url}/drone-request.html?token={drone_request.public_token}" if drone_request.public_token else None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -93,7 +93,7 @@ async def _send_drone_tower_notification(drone_request):
|
|||||||
"takeoff_time": drone_request.estimated_takeoff_at.strftime("%Y-%m-%d %H:%M"),
|
"takeoff_time": drone_request.estimated_takeoff_at.strftime("%Y-%m-%d %H:%M"),
|
||||||
"completion_time": drone_request.estimated_completion_at.strftime("%Y-%m-%d %H:%M"),
|
"completion_time": drone_request.estimated_completion_at.strftime("%Y-%m-%d %H:%M"),
|
||||||
"location": drone_request.location_description or f"{drone_request.location_latitude}, {drone_request.location_longitude}",
|
"location": drone_request.location_description or f"{drone_request.location_latitude}, {drone_request.location_longitude}",
|
||||||
"maximum_elevation_ft_amsl": drone_request.maximum_elevation_ft_amsl,
|
"maximum_elevation_ft_agl": drone_request.maximum_elevation_ft_agl,
|
||||||
"inside_frz": "Yes" if drone_request.location_inside_frz else "No",
|
"inside_frz": "Yes" if drone_request.location_inside_frz else "No",
|
||||||
"notes": drone_request.applicant_notes,
|
"notes": drone_request.applicant_notes,
|
||||||
"requests_url": f"{settings.base_url}/drone-requests",
|
"requests_url": f"{settings.base_url}/drone-requests",
|
||||||
@@ -115,7 +115,7 @@ async def _send_drone_approved_email(drone_request, message: Optional[str] = Non
|
|||||||
"takeoff_time": drone_request.estimated_takeoff_at.strftime("%Y-%m-%d %H:%M"),
|
"takeoff_time": drone_request.estimated_takeoff_at.strftime("%Y-%m-%d %H:%M"),
|
||||||
"completion_time": drone_request.estimated_completion_at.strftime("%Y-%m-%d %H:%M"),
|
"completion_time": drone_request.estimated_completion_at.strftime("%Y-%m-%d %H:%M"),
|
||||||
"location": drone_request.location_description or f"{drone_request.location_latitude}, {drone_request.location_longitude}",
|
"location": drone_request.location_description or f"{drone_request.location_latitude}, {drone_request.location_longitude}",
|
||||||
"maximum_elevation_ft_amsl": drone_request.maximum_elevation_ft_amsl,
|
"maximum_elevation_ft_agl": drone_request.maximum_elevation_ft_agl,
|
||||||
"edit_url": f"{settings.base_url}/drone-request.html?token={drone_request.public_token}" if drone_request.public_token else None,
|
"edit_url": f"{settings.base_url}/drone-request.html?token={drone_request.public_token}" if drone_request.public_token else None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class DroneRequest(Base):
|
|||||||
estimated_completion_time = Column(String(8), nullable=True)
|
estimated_completion_time = Column(String(8), nullable=True)
|
||||||
estimated_takeoff_at = Column(DateTime, nullable=False, index=True)
|
estimated_takeoff_at = Column(DateTime, nullable=False, index=True)
|
||||||
estimated_completion_at = Column(DateTime, nullable=False, index=True)
|
estimated_completion_at = Column(DateTime, nullable=False, index=True)
|
||||||
maximum_elevation_ft_amsl = Column(Integer, nullable=False)
|
maximum_elevation_ft_agl = Column(Integer, nullable=False)
|
||||||
|
|
||||||
location_description = Column(Text, nullable=True)
|
location_description = Column(Text, nullable=True)
|
||||||
location_latitude = Column(Float, nullable=False)
|
location_latitude = Column(Float, nullable=False)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from datetime import date, datetime
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
from pydantic import BaseModel, EmailStr, Field, validator
|
from pydantic import AliasChoices, BaseModel, EmailStr, Field, validator
|
||||||
|
|
||||||
|
|
||||||
class DroneRequestStatus(str, Enum):
|
class DroneRequestStatus(str, Enum):
|
||||||
@@ -20,7 +20,11 @@ class DroneRequestBase(BaseModel):
|
|||||||
flight_date: Optional[date] = None
|
flight_date: Optional[date] = None
|
||||||
estimated_takeoff_time: Optional[str] = Field(None, max_length=8)
|
estimated_takeoff_time: Optional[str] = Field(None, max_length=8)
|
||||||
estimated_completion_time: Optional[str] = Field(None, max_length=8)
|
estimated_completion_time: Optional[str] = Field(None, max_length=8)
|
||||||
maximum_elevation_ft_amsl: int = Field(..., ge=0)
|
maximum_elevation_ft_agl: int = Field(
|
||||||
|
...,
|
||||||
|
ge=0,
|
||||||
|
validation_alias=AliasChoices("maximum_elevation_ft_agl", "maximum_elevation_ft_amsl"),
|
||||||
|
)
|
||||||
location_description: Optional[str] = None
|
location_description: Optional[str] = None
|
||||||
location_latitude: float = Field(..., ge=-90, le=90)
|
location_latitude: float = Field(..., ge=-90, le=90)
|
||||||
location_longitude: float = Field(..., ge=-180, le=180)
|
location_longitude: float = Field(..., ge=-180, le=180)
|
||||||
@@ -68,7 +72,11 @@ class DroneRequestUpdate(BaseModel):
|
|||||||
estimated_completion_time: Optional[str] = Field(None, max_length=8)
|
estimated_completion_time: Optional[str] = Field(None, max_length=8)
|
||||||
estimated_takeoff_at: Optional[datetime] = None
|
estimated_takeoff_at: Optional[datetime] = None
|
||||||
estimated_completion_at: Optional[datetime] = None
|
estimated_completion_at: Optional[datetime] = None
|
||||||
maximum_elevation_ft_amsl: Optional[int] = Field(None, ge=0)
|
maximum_elevation_ft_agl: Optional[int] = Field(
|
||||||
|
None,
|
||||||
|
ge=0,
|
||||||
|
validation_alias=AliasChoices("maximum_elevation_ft_agl", "maximum_elevation_ft_amsl"),
|
||||||
|
)
|
||||||
location_description: Optional[str] = None
|
location_description: Optional[str] = None
|
||||||
location_latitude: Optional[float] = Field(None, ge=-90, le=90)
|
location_latitude: Optional[float] = Field(None, ge=-90, le=90)
|
||||||
location_longitude: Optional[float] = Field(None, ge=-180, le=180)
|
location_longitude: Optional[float] = Field(None, ge=-180, le=180)
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding: 12px; border: 1px solid #dfe5eb; background: #f8fafc;"><strong>Max elevation</strong></td>
|
<td style="padding: 12px; border: 1px solid #dfe5eb; background: #f8fafc;"><strong>Max elevation</strong></td>
|
||||||
<td style="padding: 12px; border: 1px solid #dfe5eb;">{{ maximum_elevation_ft_amsl }} ft AMSL</td>
|
<td style="padding: 12px; border: 1px solid #dfe5eb;">{{ maximum_elevation_ft_agl }} ft AGL</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding: 12px; border: 1px solid #dfe5eb; background: #f8fafc;"><strong>Max elevation</strong></td>
|
<td style="padding: 12px; border: 1px solid #dfe5eb; background: #f8fafc;"><strong>Max elevation</strong></td>
|
||||||
<td style="padding: 12px; border: 1px solid #dfe5eb;">{{ maximum_elevation_ft_amsl }} ft AMSL</td>
|
<td style="padding: 12px; border: 1px solid #dfe5eb;">{{ maximum_elevation_ft_agl }} ft AGL</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
<tr><td style="padding: 10px; border: 1px solid #dfe5eb; font-weight: bold;">Completion</td><td style="padding: 10px; border: 1px solid #dfe5eb;">{{ completion_time }}</td></tr>
|
<tr><td style="padding: 10px; border: 1px solid #dfe5eb; font-weight: bold;">Completion</td><td style="padding: 10px; border: 1px solid #dfe5eb;">{{ completion_time }}</td></tr>
|
||||||
<tr><td style="padding: 10px; border: 1px solid #dfe5eb; font-weight: bold;">Location</td><td style="padding: 10px; border: 1px solid #dfe5eb;">{{ location }}</td></tr>
|
<tr><td style="padding: 10px; border: 1px solid #dfe5eb; font-weight: bold;">Location</td><td style="padding: 10px; border: 1px solid #dfe5eb;">{{ location }}</td></tr>
|
||||||
<tr><td style="padding: 10px; border: 1px solid #dfe5eb; font-weight: bold;">Inside FRZ</td><td style="padding: 10px; border: 1px solid #dfe5eb;">{{ inside_frz }}</td></tr>
|
<tr><td style="padding: 10px; border: 1px solid #dfe5eb; font-weight: bold;">Inside FRZ</td><td style="padding: 10px; border: 1px solid #dfe5eb;">{{ inside_frz }}</td></tr>
|
||||||
<tr><td style="padding: 10px; border: 1px solid #dfe5eb; font-weight: bold;">Max elevation</td><td style="padding: 10px; border: 1px solid #dfe5eb;">{{ maximum_elevation_ft_amsl }} ft AMSL</td></tr>
|
<tr><td style="padding: 10px; border: 1px solid #dfe5eb; font-weight: bold;">Max elevation</td><td style="padding: 10px; border: 1px solid #dfe5eb;">{{ maximum_elevation_ft_agl }} ft AGL</td></tr>
|
||||||
<tr><td style="padding: 10px; border: 1px solid #dfe5eb; font-weight: bold;">Applicant notes</td><td style="padding: 10px; border: 1px solid #dfe5eb;">{{ notes or '-' }}</td></tr>
|
<tr><td style="padding: 10px; border: 1px solid #dfe5eb; font-weight: bold;">Applicant notes</td><td style="padding: 10px; border: 1px solid #dfe5eb;">{{ notes or '-' }}</td></tr>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding: 12px; border: 1px solid #dfe5eb; background: #f8fafc;"><strong>Max elevation</strong></td>
|
<td style="padding: 12px; border: 1px solid #dfe5eb; background: #f8fafc;"><strong>Max elevation</strong></td>
|
||||||
<td style="padding: 12px; border: 1px solid #dfe5eb;">{{ maximum_elevation_ft_amsl }} ft AMSL</td>
|
<td style="padding: 12px; border: 1px solid #dfe5eb;">{{ maximum_elevation_ft_agl }} ft AGL</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ def drone_payload(**overrides):
|
|||||||
"estimated_completion_time": "10:30",
|
"estimated_completion_time": "10:30",
|
||||||
"estimated_takeoff_at": "2026-06-20T10:00:00",
|
"estimated_takeoff_at": "2026-06-20T10:00:00",
|
||||||
"estimated_completion_at": "2026-06-20T10:30:00",
|
"estimated_completion_at": "2026-06-20T10:30:00",
|
||||||
"maximum_elevation_ft_amsl": 250,
|
"maximum_elevation_ft_agl": 250,
|
||||||
"location_description": "North apron",
|
"location_description": "North apron",
|
||||||
"location_latitude": 51.623389,
|
"location_latitude": 51.623389,
|
||||||
"location_longitude": -4.069231,
|
"location_longitude": -4.069231,
|
||||||
@@ -81,6 +81,23 @@ def test_public_drone_request_create_edit_cancel_and_journal(client, db, monkeyp
|
|||||||
assert client.delete("/api/v1/drone-requests/public/cancel/missing-token").status_code == 404
|
assert client.delete("/api/v1/drone-requests/public/cancel/missing-token").status_code == 404
|
||||||
|
|
||||||
|
|
||||||
|
def test_drone_request_accepts_legacy_amsl_altitude_key(client, db, monkeypatch):
|
||||||
|
async def fake_send_email(**kwargs):
|
||||||
|
return True
|
||||||
|
|
||||||
|
monkeypatch.setattr("app.api.endpoints.drone_requests.email_service.send_email", fake_send_email)
|
||||||
|
|
||||||
|
payload = drone_payload()
|
||||||
|
payload["maximum_elevation_ft_amsl"] = payload.pop("maximum_elevation_ft_agl")
|
||||||
|
|
||||||
|
create_response = client.post("/api/v1/drone-requests/public", json=payload)
|
||||||
|
|
||||||
|
assert create_response.status_code == 200
|
||||||
|
assert create_response.json()["maximum_elevation_ft_agl"] == 250
|
||||||
|
db_request = db.query(DroneRequest).filter(DroneRequest.id == create_response.json()["id"]).one()
|
||||||
|
assert db_request.maximum_elevation_ft_agl == 250
|
||||||
|
|
||||||
|
|
||||||
def test_authenticated_drone_request_list_update_status_comment_and_journal(auth_client, db, monkeypatch):
|
def test_authenticated_drone_request_list_update_status_comment_and_journal(auth_client, db, monkeypatch):
|
||||||
sent_emails = []
|
sent_emails = []
|
||||||
|
|
||||||
@@ -100,7 +117,7 @@ def test_authenticated_drone_request_list_update_status_comment_and_journal(auth
|
|||||||
get_response = auth_client.get(f"/api/v1/drone-requests/{created['id']}")
|
get_response = auth_client.get(f"/api/v1/drone-requests/{created['id']}")
|
||||||
update_response = auth_client.patch(
|
update_response = auth_client.patch(
|
||||||
f"/api/v1/drone-requests/{created['id']}",
|
f"/api/v1/drone-requests/{created['id']}",
|
||||||
json={"operator_comments": "Needs tower review", "maximum_elevation_ft_amsl": 200},
|
json={"operator_comments": "Needs tower review", "maximum_elevation_ft_agl": 200},
|
||||||
)
|
)
|
||||||
status_response = auth_client.patch(
|
status_response = auth_client.patch(
|
||||||
f"/api/v1/drone-requests/{created['id']}/status",
|
f"/api/v1/drone-requests/{created['id']}/status",
|
||||||
@@ -116,7 +133,7 @@ def test_authenticated_drone_request_list_update_status_comment_and_journal(auth
|
|||||||
assert [request["id"] for request in list_response.json()] == [created["id"]]
|
assert [request["id"] for request in list_response.json()] == [created["id"]]
|
||||||
assert get_response.status_code == 200
|
assert get_response.status_code == 200
|
||||||
assert update_response.status_code == 200
|
assert update_response.status_code == 200
|
||||||
assert update_response.json()["maximum_elevation_ft_amsl"] == 200
|
assert update_response.json()["maximum_elevation_ft_agl"] == 200
|
||||||
assert status_response.status_code == 200
|
assert status_response.status_code == 200
|
||||||
assert status_response.json()["status"] == "APPROVED"
|
assert status_response.json()["status"] == "APPROVED"
|
||||||
assert status_response.json()["operator_comments"] == "Approved below 200ft"
|
assert status_response.json()["operator_comments"] == "Approved below 200ft"
|
||||||
@@ -133,7 +150,7 @@ def test_authenticated_drone_request_list_update_status_comment_and_journal(auth
|
|||||||
def test_drone_request_not_found_and_validation_paths(auth_client, client):
|
def test_drone_request_not_found_and_validation_paths(auth_client, client):
|
||||||
invalid_response = client.post(
|
invalid_response = client.post(
|
||||||
"/api/v1/drone-requests/public",
|
"/api/v1/drone-requests/public",
|
||||||
json=drone_payload(operator_name=" ", location_latitude=100, maximum_elevation_ft_amsl=-1),
|
json=drone_payload(operator_name=" ", location_latitude=100, maximum_elevation_ft_agl=-1),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert invalid_response.status_code == 422
|
assert invalid_response.status_code == 422
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ def drone_payload(operator_name):
|
|||||||
"estimated_completion_time": "10:30",
|
"estimated_completion_time": "10:30",
|
||||||
"estimated_takeoff_at": "2026-06-21T10:00:00",
|
"estimated_takeoff_at": "2026-06-21T10:00:00",
|
||||||
"estimated_completion_at": "2026-06-21T10:30:00",
|
"estimated_completion_at": "2026-06-21T10:30:00",
|
||||||
"maximum_elevation_ft_amsl": 200,
|
"maximum_elevation_ft_agl": 200,
|
||||||
"location_description": "E2E north apron survey",
|
"location_description": "E2E north apron survey",
|
||||||
"location_latitude": 51.623389,
|
"location_latitude": 51.623389,
|
||||||
"location_longitude": -4.069231,
|
"location_longitude": -4.069231,
|
||||||
|
|||||||
@@ -149,8 +149,8 @@
|
|||||||
<input id="estimated_completion_at" type="datetime-local" required>
|
<input id="estimated_completion_at" type="datetime-local" required>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="maximum_elevation_ft_amsl">Maximum elevation ft AMSL</label>
|
<label for="maximum_elevation_ft_agl">Maximum elevation ft AGL</label>
|
||||||
<input id="maximum_elevation_ft_amsl" type="number" min="0" required>
|
<input id="maximum_elevation_ft_agl" type="number" min="0" required>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="location_inside_frz">Inside FRZ</label>
|
<label for="location_inside_frz">Inside FRZ</label>
|
||||||
@@ -228,7 +228,7 @@
|
|||||||
setValue('phone', request.phone);
|
setValue('phone', request.phone);
|
||||||
setValue('estimated_takeoff_at', toLocalInputValue(request.estimated_takeoff_at));
|
setValue('estimated_takeoff_at', toLocalInputValue(request.estimated_takeoff_at));
|
||||||
setValue('estimated_completion_at', toLocalInputValue(request.estimated_completion_at));
|
setValue('estimated_completion_at', toLocalInputValue(request.estimated_completion_at));
|
||||||
setValue('maximum_elevation_ft_amsl', request.maximum_elevation_ft_amsl);
|
setValue('maximum_elevation_ft_agl', request.maximum_elevation_ft_agl);
|
||||||
setValue('location_inside_frz', request.location_inside_frz ? 'Yes' : 'No');
|
setValue('location_inside_frz', request.location_inside_frz ? 'Yes' : 'No');
|
||||||
setValue('location_latitude', request.location_latitude);
|
setValue('location_latitude', request.location_latitude);
|
||||||
setValue('location_longitude', request.location_longitude);
|
setValue('location_longitude', request.location_longitude);
|
||||||
@@ -260,7 +260,7 @@
|
|||||||
phone: value('phone') || null,
|
phone: value('phone') || null,
|
||||||
estimated_takeoff_at: fromLocalInputValue(value('estimated_takeoff_at')),
|
estimated_takeoff_at: fromLocalInputValue(value('estimated_takeoff_at')),
|
||||||
estimated_completion_at: fromLocalInputValue(value('estimated_completion_at')),
|
estimated_completion_at: fromLocalInputValue(value('estimated_completion_at')),
|
||||||
maximum_elevation_ft_amsl: Number(value('maximum_elevation_ft_amsl')),
|
maximum_elevation_ft_agl: Number(value('maximum_elevation_ft_agl')),
|
||||||
location_latitude: Number(value('location_latitude')),
|
location_latitude: Number(value('location_latitude')),
|
||||||
location_longitude: Number(value('location_longitude')),
|
location_longitude: Number(value('location_longitude')),
|
||||||
location_description: value('location_description') || null,
|
location_description: value('location_description') || null,
|
||||||
|
|||||||
@@ -795,7 +795,7 @@
|
|||||||
${field('Flyer ID', selectedRequest.flyer_id)}
|
${field('Flyer ID', selectedRequest.flyer_id)}
|
||||||
${field('Takeoff', formatDateTime(selectedRequest.estimated_takeoff_at))}
|
${field('Takeoff', formatDateTime(selectedRequest.estimated_takeoff_at))}
|
||||||
${field('Completion', formatDateTime(selectedRequest.estimated_completion_at))}
|
${field('Completion', formatDateTime(selectedRequest.estimated_completion_at))}
|
||||||
${field('Max Elevation', `${selectedRequest.maximum_elevation_ft_amsl} ft AMSL`)}
|
${field('Max Elevation', `${selectedRequest.maximum_elevation_ft_agl} ft AGL`)}
|
||||||
${field('Inside FRZ', selectedRequest.location_inside_frz === null ? '-' : (selectedRequest.location_inside_frz ? 'Yes' : 'No'))}
|
${field('Inside FRZ', selectedRequest.location_inside_frz === null ? '-' : (selectedRequest.location_inside_frz ? 'Yes' : 'No'))}
|
||||||
${field('Latitude', selectedRequest.location_latitude)}
|
${field('Latitude', selectedRequest.location_latitude)}
|
||||||
${field('Longitude', selectedRequest.location_longitude)}
|
${field('Longitude', selectedRequest.location_longitude)}
|
||||||
@@ -862,7 +862,7 @@
|
|||||||
addLayer(L.marker(point).addTo(map).bindPopup(`
|
addLayer(L.marker(point).addTo(map).bindPopup(`
|
||||||
<strong>${escapeHtml(selectedRequest.reference_number)}</strong><br>
|
<strong>${escapeHtml(selectedRequest.reference_number)}</strong><br>
|
||||||
${escapeHtml(selectedRequest.operator_name)}<br>
|
${escapeHtml(selectedRequest.operator_name)}<br>
|
||||||
${selectedRequest.maximum_elevation_ft_amsl} ft AMSL
|
${selectedRequest.maximum_elevation_ft_agl} ft AGL
|
||||||
`));
|
`));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user