Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
69c76a0
add simple django plotly dash example
davidwyld Jun 24, 2025
a888f7f
rename dash.py to frontend.py
davidwyld Jun 24, 2025
2ca0b01
correctly configure django_plotly_dash
davidwyld Jun 24, 2025
cd77d3f
use direct insertion of app into html; rearrange settings module
davidwyld Jun 24, 2025
2611e41
add standard BAS header in template for now
davidwyld Jun 24, 2025
6e8c149
branding
davidwyld Jun 24, 2025
229ef42
checkpoint
davidwyld Jun 24, 2025
40e8d7d
add basic AMSR 12km display and controls
davidwyld Jun 25, 2025
6f33c8f
add bas footer
davidwyld Jun 26, 2025
db9df2b
add more packages to frontend deps
davidwyld Jun 26, 2025
8112284
prevent linting from picking up import magic
davidwyld Jun 26, 2025
f2aed88
update frontend deps in settings
davidwyld Jun 26, 2025
37b33c1
use layerscontrol for amsr
davidwyld Jun 26, 2025
207c934
make bootstrap work
davidwyld Jun 26, 2025
c62fcf7
reduce duplicaation
davidwyld Jun 26, 2025
d7cbd02
add basic routes table
davidwyld Jun 28, 2025
e889f5e
add dash-bootstrap5 dep
davidwyld Jul 3, 2025
776a91e
chaos checkpoint
davidwyld Jul 3, 2025
4c17cdc
chaos checkpoint
davidwyld Jul 3, 2025
771ca06
table with checkboxes to show routes on map, finally
davidwyld Jul 7, 2025
24f66a7
show both traveltime and fuel optimised routes
davidwyld Jul 7, 2025
164589a
format mouse coordinates
davidwyld Jul 7, 2025
f6c8fa9
use BAS colours
davidwyld Jul 7, 2025
cb022ea
use columns
davidwyld Jul 7, 2025
9b53cba
add map marker interaction
davidwyld Jul 7, 2025
ab24143
fix route updater
davidwyld Jul 8, 2025
b837e98
use coloured markers
davidwyld Jul 8, 2025
6f10345
start form, add responsive breakpoints
davidwyld Jul 8, 2025
57b63d5
use django plotly dash again; write map event handler functions to js…
davidwyld Jul 8, 2025
b46b85d
remove logo
davidwyld Jul 8, 2025
ab36e42
alter way in which marker data store and markers are updated
davidwyld Jul 17, 2025
f69e311
add debug logging in development; handle marker dragging
davidwyld Jul 22, 2025
f3ba936
add ability to request routes
davidwyld Jul 30, 2025
0b0d48f
convert all request coordinates to floats
davidwyld Jul 30, 2025
6faca63
handle route store updates better
davidwyld Jul 30, 2025
df39502
handle route visibility with dedicated store
davidwyld Jul 31, 2025
e43520b
remove debug logging
davidwyld Jul 31, 2025
2d8ef8f
add controls for fuel and time optimised route visibility
davidwyld Jul 31, 2025
355159f
move to frontend module dir; tidy imports
davidwyld Jul 31, 2025
0aa1e3d
use env var for server url
davidwyld Jul 31, 2025
a92d88e
organise frontend module
davidwyld Jul 31, 2025
8ac7d3a
remove_dash_view
davidwyld Jul 31, 2025
4dd44bc
lint
davidwyld Jul 31, 2025
bc0e4d1
remove dash view
davidwyld Jul 31, 2025
202b7bb
use dash components for bas style kit elements
davidwyld Aug 5, 2025
cc10b2c
add data dir
davidwyld Aug 5, 2025
a0450ec
control rendering of frontend in template using environment variable
davidwyld Aug 5, 2025
621f8e0
mention frontend in readme
davidwyld Aug 5, 2025
3f3cc06
reorder logging config
davidwyld Aug 5, 2025
1dfa1af
suppress irritating warning from django plotly dash
davidwyld Aug 5, 2025
dda1eb1
move stores back to memory; add update button
davidwyld Aug 5, 2025
4923232
simplify and fix route update logic
davidwyld Aug 5, 2025
8a10274
add quick and dirty error tooltip
davidwyld Aug 5, 2025
870e979
add markers when displaying routes
davidwyld Aug 5, 2025
6e80522
fix start/end marker display
davidwyld Aug 6, 2025
1cc7028
reposition route refresh button
davidwyld Aug 6, 2025
7d7b93f
remove debugging prints
davidwyld Aug 6, 2025
7064caf
add fuel and time figures to tooltips
davidwyld Aug 6, 2025
f4399c5
add quick and dirty fuel and time figures in table
davidwyld Aug 6, 2025
7e806d0
don't show start and end place name if they're None
davidwyld Aug 6, 2025
23b58e8
Merge branch 'main' into dw/plotly_dash
davidwyld Aug 21, 2025
469bced
protect against missing routes
davidwyld Aug 21, 2025
19f5291
Merge remote-tracking branch 'origin/dw/plotly_dash' into dw/plotly_dash
davidwyld Aug 21, 2025
8ccd1f2
force add mapFunctions.js
davidwyld Aug 21, 2025
75e103b
Merge branch 'main' into dw/plotly_dash
davidwyld Dec 22, 2025
348bb7f
Merge branch 'main' into dw/plotly_dash
davidwyld Dec 22, 2025
4efcb3a
add utilities and docs for debugging with docker
davidwyld Jan 21, 2026
67371e6
use locations endpoint
davidwyld Jan 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,8 @@ GitHub.sublime-settings
# Visual Studio Code #
.vscode/*
.history

# assets used by dash js components
assets/*

data/*
5 changes: 3 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ COPY --chmod=775 docker-entrypoint.sh .

COPY pyproject.toml manage.py /usr/src/app/
COPY polarrouteserver /usr/src/app/polarrouteserver
COPY assets /usr/src/app/assets

ENV SETUPTOOLS_SCM_PRETEND_VERSION=99.99.99
RUN uv pip install --system -e .
RUN uv pip install --system django-debug-toolbar
RUN uv pip install --system -e .[frontend]
RUN uv pip install --system django-debug-toolbar debugpy
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ popd
- Run `docker compose exec app /bin/bash` to open a shell inside the running app container.
- Run `django-admin insert_mesh /usr/src/app/data/mesh/<MESH FILENAME>` to insert the mesh into the database manually.

Test that the app is working using the `request_route` tool (see [Documentation](https://bas-amop.github.io/PolarRoute-server/requesting-routes/#using-the-in-built-route-request-utility-simplest)). The URL of the service should be `localhost:8000`.
Test that the app is working using the demo tool (see [Documentation](https://bas-amop.github.io/PolarRoute-server/requesting-routes/#using-the-in-built-demo-utility-simplest)). The URL of the service should be `localhost:8000`, where the user interface will be served if `POLARROUTE_FRONTEND` is set to `True` (which it is in `compose.yml`).

The django development server supports hot reloading and the source code is bind-mounted into the container, so changes should be reflected in the running app. Any changes to `polarrouteserver.route_api.models.py` will necessitate a migration to the database. To create and run migrations, run:

Expand Down
35 changes: 35 additions & 0 deletions assets/mapFunctions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
window.polarRoute = Object.assign({}, window.polarRoute, {
mapFunctions: {
mousemove: function(e, ctx) {
ctx.setProps({
mouseCoords: {
area: e.latlng
}
})
},
click: function(e, ctx) {

ctx.setProps({
n_clicks: ctx.n_clicks == undefined ? 1 : ctx.n_clicks + 1, // increment counter
clickData: {
latlng: e.latlng,
layerPoint: e.layerPoint,
containerPoint: e.containerPoint
}
});
},
// marker drag end event handler
dragend: function(e, ctx) {

latlng = e.target.getLatLng();

ctx.setProps({
dragEndPosition: {
lat:latlng.lat,
lon:latlng.lng,
}
});
}

}
});
7 changes: 7 additions & 0 deletions compose.debug.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
services:
app:
ports:
- 5678:5678
command: >
python -m debugpy --listen 0.0.0.0:5678 --wait-for-client
manage.py runserver 0.0.0.0:8000 --noreload
3 changes: 3 additions & 0 deletions compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ services:
POLARROUTE_MESH_DIR: /usr/src/app/mesh
POLARROUTE_DB_HOST: db
POLARROUTE_DB_PORT: 5432
POLARROUTE_FRONTEND: True
POLARROUTE_LOG_LEVEL: DEBUG
POLARROUTE_SUPERUSER_USERNAME: admin
POLARROUTE_SUPERUSER_PASSWORD: password
entrypoint: /usr/src/app/docker-entrypoint.sh
Expand All @@ -17,6 +19,7 @@ services:
- ./manage.py:/usr/src/app/manage.py
- ./polarrouteserver:/usr/src/app/polarrouteserver
- ./data/mesh:/usr/src/app/data/mesh
- ./assets:/usr/src/app/assets
depends_on:
- db
- celery
Expand Down
2 changes: 1 addition & 1 deletion docs/apischema.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
openapi: 3.0.3
info:
title: PolarRoute-Server
version: 0.2.7
version: 0.2.1.dev121+g8ccd1f2f8.d20251222
description: Backend server for serving PolarRoute and MeshiPhi assets
paths:
/api/evaluate_route:
Expand Down
1 change: 1 addition & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ The following are inherited from Django and more information can be found on the
- `POLARROUTE_LOG_LEVEL` - sets the logging level from standard log level options: INFO, DEBUG, ERROR, WARNING etc. (Default: `INFO`)
- `POLARROUTE_LOG_DIR` - sets the output directory for logs. By default only used in production settings environment.
- `POLARROUTE_STATIC_ROOT` - the path to directory used for static file serving in production, e.g. `"/var/www/example.com/static/"` (Default: `None`) Note this is only used for the admin panel in this application.
- `POLARROUTE_FRONTEND` - boolean switch to disable the frontend dashboard if, for instance, PolarRoute-server is being used exclusively as a headless app. Set to `False` to disable. (Default: `True`)

## Database settings

Expand Down
32 changes: 32 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,38 @@ A number of helpful development tools are made available through the `Makefile`,

**Important**: Please ensure all changes are included in `CHANGELOG.md` in a human-friendly format.

## Debugging with docker compose

To run using a debugger in e.g. vs code, run with the additional compose file `compose.debug.yml` which adds some additional settings to enable this.

Do so with: `docker compose -f compose.yml -f compose.debug.yml up`

This will launch the containers, but the `app` service will stop until a debugger is attached.

For VS Code, the launch config should look like:

```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Dockerised Django",
"type": "debugpy",
"request": "attach",
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/usr/src/app"
}
],
"connect": {"host": "127.0.0.1", "port": 5678},
}
]
}
```

Run the debugger using this config to run the debugger listening to the debugging port configured.

## Release/Versioning

Version numbers should be used in tagging commits on the `main` branch and reflected in the `pyproject.toml` file and should be of the form `v0.1.7` using the semantic versioning convention.
Expand Down
135 changes: 135 additions & 0 deletions polarrouteserver/frontend/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import logging
import warnings

from dash import dcc
import dash_bootstrap_components as dbc
import dash_leaflet as dl
from django_plotly_dash import DjangoDash
from dash_extensions.enrich import html
from dash_extensions.javascript import Namespace

from .callbacks import register_callbacks
from .components import amsr_layer, header, footer, site_development_notice
from .layouts import route_request_form
from .utils import default_sic_date

logger = logging.getLogger(__name__)
FORMAT = "[%(filename)s . %(funcName)20s() ] %(message)s"
logging.basicConfig(format=FORMAT)

stylesheets = [
"https://cdn.web.bas.ac.uk/bas-style-kit/0.7.3/css/bas-style-kit.min.css",
dbc.themes.BOOTSTRAP,
dbc.icons.BOOTSTRAP,
]

with warnings.catch_warnings():
warnings.simplefilter("ignore")
app = DjangoDash(
"PolarRoute",
add_bootstrap_links=True,
update_title=None,
external_stylesheets=stylesheets,
)

register_callbacks(app)

ns = Namespace("polarRoute", "mapFunctions")

eventHandlers = dict(
mousemove=ns("mousemove"),
click=ns("click"),
)


def serve_layout():
return html.Div(
children=[
dcc.Store(id="routes-store", data=[], storage_type="memory"),
dcc.Store(id="route-visibility-store", data=[], storage_type="memory"),
dcc.Store(id="marker-store", storage_type="memory", data={}),
dcc.Interval(id="recent-routes-interval", interval=10000),
# dcc.Interval(id="route-request-form-interval", interval=1, n_intervals=0, max_intervals=1),
html.Header(header),
site_development_notice,
dl.Map(
[
dl.TileLayer(
id="basemap",
attribution=("© OpenStreetMap contributors"),
zIndex=0,
),
dl.FullScreenControl(),
dl.LayersControl(
[
dl.Overlay(
amsr_layer(default_sic_date),
name="AMSR",
checked=False,
id="amsr-overlay",
),
],
id="layers-control",
),
dl.FeatureGroup(id="routes-fg"),
dl.FeatureGroup(id="marker-fg", children=[]),
],
center=[-60, -67],
zoom=3,
style={"height": "50vh", "cursor": "crosshair"},
id="map",
eventHandlers=eventHandlers,
),
html.Span(" ", id="mouse-coords-container"),
dcc.Slider(
min=-30,
max=0,
step=1,
value=0,
id="amsr-date-slider",
marks=None,
tooltip={"placement": "top", "always_visible": False},
),
html.Span("", id="test-output-container"),
dbc.Row(
[
dbc.Col(
[
dbc.Row(
[
dbc.Col(html.H2("Recent Routes"), width=4),
dbc.Col(
dbc.Button(
html.I(
className="bi bi-arrow-clockwise me-2"
),
id="refresh-routes-button",
class_name="bsk-btn bsk-btn-primary",
)
),
],
justify="start",
),
dcc.Loading([html.Div(id="recent-routes-table")]),
html.Div(id="recent-routes-tooltips"),
],
class_name="col-12 col-md-6",
),
dbc.Col(
[
html.H2("Request Route"),
html.Span(
"Select start and end points from dropdown or by clicking on map."
),
html.Div(route_request_form(), id="route-request"),
],
class_name="col-12 col-md-6",
),
]
),
html.Footer(footer),
],
)


app.layout = serve_layout
Loading