geo-activity-playground 0.38.2__py3-none-any.whl → 0.39.1__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.
Files changed (116) hide show
  1. geo_activity_playground/__main__.py +5 -47
  2. geo_activity_playground/alembic/README +1 -0
  3. geo_activity_playground/alembic/env.py +76 -0
  4. geo_activity_playground/alembic/script.py.mako +26 -0
  5. geo_activity_playground/alembic/versions/451e7836b53d_add_square_planner_bookmark.py +33 -0
  6. geo_activity_playground/alembic/versions/63d3b7f6f93c_initial_version.py +73 -0
  7. geo_activity_playground/alembic/versions/ab83b9d23127_add_upstream_id.py +28 -0
  8. geo_activity_playground/alembic/versions/b03491c593f6_add_crop_indices.py +30 -0
  9. geo_activity_playground/alembic/versions/e02e27876deb_add_square_planner_bookmark_name.py +28 -0
  10. geo_activity_playground/alembic/versions/script.py.mako +28 -0
  11. geo_activity_playground/core/activities.py +53 -136
  12. geo_activity_playground/core/config.py +3 -3
  13. geo_activity_playground/core/datamodel.py +257 -0
  14. geo_activity_playground/core/enrichment.py +90 -92
  15. geo_activity_playground/core/heart_rate.py +1 -2
  16. geo_activity_playground/core/parametric_plot.py +101 -0
  17. geo_activity_playground/core/paths.py +6 -7
  18. geo_activity_playground/core/raster_map.py +43 -4
  19. geo_activity_playground/core/similarity.py +1 -2
  20. geo_activity_playground/core/tasks.py +2 -2
  21. geo_activity_playground/core/test_meta_search.py +3 -3
  22. geo_activity_playground/core/test_summary_stats.py +1 -1
  23. geo_activity_playground/explorer/grid_file.py +2 -2
  24. geo_activity_playground/explorer/tile_visits.py +8 -10
  25. geo_activity_playground/heatmap_video.py +7 -8
  26. geo_activity_playground/importers/activity_parsers.py +2 -2
  27. geo_activity_playground/importers/directory.py +9 -10
  28. geo_activity_playground/importers/strava_api.py +9 -9
  29. geo_activity_playground/importers/strava_checkout.py +12 -13
  30. geo_activity_playground/importers/test_csv_parser.py +3 -3
  31. geo_activity_playground/importers/test_directory.py +1 -1
  32. geo_activity_playground/importers/test_strava_api.py +1 -1
  33. geo_activity_playground/webui/app.py +96 -86
  34. geo_activity_playground/webui/authenticator.py +1 -1
  35. geo_activity_playground/webui/{activity/controller.py → blueprints/activity_blueprint.py} +246 -108
  36. geo_activity_playground/webui/{auth_blueprint.py → blueprints/auth_blueprint.py} +1 -1
  37. geo_activity_playground/webui/blueprints/bubble_chart_blueprint.py +61 -0
  38. geo_activity_playground/webui/{calendar/controller.py → blueprints/calendar_blueprint.py} +19 -19
  39. geo_activity_playground/webui/{eddington_blueprint.py → blueprints/eddington_blueprint.py} +5 -5
  40. geo_activity_playground/webui/blueprints/entry_views.py +68 -0
  41. geo_activity_playground/webui/{equipment_blueprint.py → blueprints/equipment_blueprint.py} +37 -4
  42. geo_activity_playground/webui/{explorer/controller.py → blueprints/explorer_blueprint.py} +88 -54
  43. geo_activity_playground/webui/blueprints/heatmap_blueprint.py +233 -0
  44. geo_activity_playground/webui/blueprints/plot_builder_blueprint.py +43 -0
  45. geo_activity_playground/webui/{search_blueprint.py → blueprints/search_blueprint.py} +7 -11
  46. geo_activity_playground/webui/blueprints/settings_blueprint.py +446 -0
  47. geo_activity_playground/webui/{square_planner_blueprint.py → blueprints/square_planner_blueprint.py} +31 -6
  48. geo_activity_playground/webui/{summary_blueprint.py → blueprints/summary_blueprint.py} +11 -23
  49. geo_activity_playground/webui/blueprints/tile_blueprint.py +27 -0
  50. geo_activity_playground/webui/{upload_blueprint.py → blueprints/upload_blueprint.py} +13 -18
  51. geo_activity_playground/webui/flasher.py +26 -0
  52. geo_activity_playground/webui/plot_util.py +1 -1
  53. geo_activity_playground/webui/search_util.py +4 -6
  54. geo_activity_playground/webui/static/images/layers-2x.png +0 -0
  55. geo_activity_playground/webui/static/images/layers.png +0 -0
  56. geo_activity_playground/webui/static/images/marker-icon-2x.png +0 -0
  57. geo_activity_playground/webui/static/images/marker-icon.png +0 -0
  58. geo_activity_playground/webui/static/images/marker-shadow.png +0 -0
  59. geo_activity_playground/webui/templates/activity/day.html.j2 +81 -0
  60. geo_activity_playground/webui/templates/activity/edit.html.j2 +38 -0
  61. geo_activity_playground/webui/{activity/templates → templates}/activity/name.html.j2 +29 -27
  62. geo_activity_playground/webui/{activity/templates → templates}/activity/show.html.j2 +57 -33
  63. geo_activity_playground/webui/templates/activity/trim.html.j2 +68 -0
  64. geo_activity_playground/webui/templates/bubble_chart/index.html.j2 +26 -0
  65. geo_activity_playground/webui/templates/calendar/index.html.j2 +48 -0
  66. geo_activity_playground/webui/templates/calendar/month.html.j2 +57 -0
  67. geo_activity_playground/webui/templates/equipment/index.html.j2 +7 -0
  68. geo_activity_playground/webui/templates/home.html.j2 +6 -6
  69. geo_activity_playground/webui/templates/page.html.j2 +2 -1
  70. geo_activity_playground/webui/templates/plot_builder/index.html.j2 +44 -0
  71. geo_activity_playground/webui/{settings/templates → templates}/settings/index.html.j2 +9 -20
  72. geo_activity_playground/webui/templates/settings/manage-equipments.html.j2 +49 -0
  73. geo_activity_playground/webui/templates/settings/manage-kinds.html.j2 +48 -0
  74. geo_activity_playground/webui/{settings/templates → templates}/settings/privacy-zones.html.j2 +2 -0
  75. geo_activity_playground/webui/{settings/templates → templates}/settings/strava.html.j2 +2 -0
  76. geo_activity_playground/webui/templates/square_planner/index.html.j2 +63 -13
  77. {geo_activity_playground-0.38.2.dist-info → geo_activity_playground-0.39.1.dist-info}/METADATA +5 -1
  78. geo_activity_playground-0.39.1.dist-info/RECORD +136 -0
  79. geo_activity_playground/__init__.py +0 -0
  80. geo_activity_playground/core/__init__.py +0 -0
  81. geo_activity_playground/explorer/__init__.py +0 -0
  82. geo_activity_playground/importers/__init__.py +0 -0
  83. geo_activity_playground/webui/__init__.py +0 -0
  84. geo_activity_playground/webui/activity/__init__.py +0 -0
  85. geo_activity_playground/webui/activity/blueprint.py +0 -109
  86. geo_activity_playground/webui/activity/templates/activity/day.html.j2 +0 -80
  87. geo_activity_playground/webui/activity/templates/activity/edit.html.j2 +0 -42
  88. geo_activity_playground/webui/calendar/__init__.py +0 -0
  89. geo_activity_playground/webui/calendar/blueprint.py +0 -23
  90. geo_activity_playground/webui/calendar/templates/calendar/index.html.j2 +0 -46
  91. geo_activity_playground/webui/calendar/templates/calendar/month.html.j2 +0 -55
  92. geo_activity_playground/webui/entry_controller.py +0 -63
  93. geo_activity_playground/webui/explorer/__init__.py +0 -0
  94. geo_activity_playground/webui/explorer/blueprint.py +0 -62
  95. geo_activity_playground/webui/heatmap/__init__.py +0 -0
  96. geo_activity_playground/webui/heatmap/blueprint.py +0 -51
  97. geo_activity_playground/webui/heatmap/heatmap_controller.py +0 -216
  98. geo_activity_playground/webui/settings/blueprint.py +0 -262
  99. geo_activity_playground/webui/settings/controller.py +0 -272
  100. geo_activity_playground/webui/settings/templates/settings/equipment-offsets.html.j2 +0 -44
  101. geo_activity_playground/webui/settings/templates/settings/kind-renames.html.j2 +0 -25
  102. geo_activity_playground/webui/settings/templates/settings/kinds-without-achievements.html.j2 +0 -30
  103. geo_activity_playground/webui/tile_blueprint.py +0 -42
  104. geo_activity_playground-0.38.2.dist-info/RECORD +0 -129
  105. /geo_activity_playground/webui/{activity/templates → templates}/activity/lines.html.j2 +0 -0
  106. /geo_activity_playground/webui/{explorer/templates → templates}/explorer/index.html.j2 +0 -0
  107. /geo_activity_playground/webui/{heatmap/templates → templates}/heatmap/index.html.j2 +0 -0
  108. /geo_activity_playground/webui/{settings/templates → templates}/settings/admin-password.html.j2 +0 -0
  109. /geo_activity_playground/webui/{settings/templates → templates}/settings/color-schemes.html.j2 +0 -0
  110. /geo_activity_playground/webui/{settings/templates → templates}/settings/heart-rate.html.j2 +0 -0
  111. /geo_activity_playground/webui/{settings/templates → templates}/settings/metadata-extraction.html.j2 +0 -0
  112. /geo_activity_playground/webui/{settings/templates → templates}/settings/segmentation.html.j2 +0 -0
  113. /geo_activity_playground/webui/{settings/templates → templates}/settings/sharepic.html.j2 +0 -0
  114. {geo_activity_playground-0.38.2.dist-info → geo_activity_playground-0.39.1.dist-info}/LICENSE +0 -0
  115. {geo_activity_playground-0.38.2.dist-info → geo_activity_playground-0.39.1.dist-info}/WHEEL +0 -0
  116. {geo_activity_playground-0.38.2.dist-info → geo_activity_playground-0.39.1.dist-info}/entry_points.txt +0 -0
@@ -1,109 +0,0 @@
1
- import json
2
- import urllib.parse
3
-
4
- from flask import Blueprint
5
- from flask import redirect
6
- from flask import render_template
7
- from flask import request
8
- from flask import Response
9
- from flask import url_for
10
-
11
- from geo_activity_playground.core.activities import ActivityRepository
12
- from geo_activity_playground.core.paths import activity_meta_override_dir
13
- from geo_activity_playground.webui.activity.controller import ActivityController
14
- from geo_activity_playground.webui.authenticator import Authenticator
15
- from geo_activity_playground.webui.authenticator import needs_authentication
16
-
17
-
18
- def make_activity_blueprint(
19
- activity_controller: ActivityController,
20
- repository: ActivityRepository,
21
- authenticator: Authenticator,
22
- ) -> Blueprint:
23
- blueprint = Blueprint("activity", __name__, template_folder="templates")
24
-
25
- @blueprint.route("/all")
26
- def all():
27
- return render_template(
28
- "activity/lines.html.j2", **activity_controller.render_all()
29
- )
30
-
31
- @blueprint.route("/<id>")
32
- def show(id: str):
33
- return render_template(
34
- "activity/show.html.j2", **activity_controller.render_activity(int(id))
35
- )
36
-
37
- @blueprint.route("/<id>/sharepic.png")
38
- def sharepic(id: str):
39
- return Response(
40
- activity_controller.render_sharepic(int(id)),
41
- mimetype="image/png",
42
- )
43
-
44
- @blueprint.route("/day/<year>/<month>/<day>")
45
- def day(year: str, month: str, day: str):
46
- return render_template(
47
- "activity/day.html.j2",
48
- **activity_controller.render_day(int(year), int(month), int(day)),
49
- )
50
-
51
- @blueprint.route("/day-sharepic/<year>/<month>/<day>/sharepic.png")
52
- def day_sharepic(year: str, month: str, day: str):
53
- return Response(
54
- activity_controller.render_day_sharepic(int(year), int(month), int(day)),
55
- mimetype="image/png",
56
- )
57
-
58
- @blueprint.route("/name/<name>")
59
- def name(name: str):
60
- return render_template(
61
- "activity/name.html.j2",
62
- **activity_controller.render_name(urllib.parse.unquote(name)),
63
- )
64
-
65
- @blueprint.route("/edit/<id>", methods=["GET", "POST"])
66
- @needs_authentication(authenticator)
67
- def edit(id: str):
68
- activity_id = int(id)
69
- activity = repository.get_activity_by_id(activity_id)
70
- override_file = activity_meta_override_dir() / f"{activity_id}.json"
71
- if override_file.exists():
72
- with open(override_file) as f:
73
- override = json.load(f)
74
- else:
75
- override = {}
76
-
77
- if request.method == "POST":
78
- override = {}
79
- if value := request.form.get("name"):
80
- override["name"] = value
81
- repository.meta.loc[activity_id, "name"] = value
82
- if value := request.form.get("kind"):
83
- override["kind"] = value
84
- repository.meta.loc[activity_id, "kind"] = value
85
- if value := request.form.get("equipment"):
86
- override["equipment"] = value
87
- repository.meta.loc[activity_id, "equipment"] = value
88
- if value := request.form.get("commute"):
89
- override["commute"] = True
90
- repository.meta.loc[activity_id, "commute"] = True
91
- if value := request.form.get("consider_for_achievements"):
92
- override["consider_for_achievements"] = True
93
- repository.meta.loc[activity_id, "consider_for_achievements"] = True
94
-
95
- with open(override_file, "w") as f:
96
- json.dump(override, f, ensure_ascii=False, indent=4, sort_keys=True)
97
-
98
- repository.save()
99
-
100
- return redirect(url_for(".show", id=activity_id))
101
-
102
- return render_template(
103
- "activity/edit.html.j2",
104
- activity_id=activity_id,
105
- activity=activity,
106
- override=override,
107
- )
108
-
109
- return blueprint
@@ -1,80 +0,0 @@
1
- {% extends "page.html.j2" %}
2
-
3
- {% block container %}
4
- <div class="row mb-3">
5
- <div class="col">
6
- <h1>{{ date }}</h1>
7
- </div>
8
- </div>
9
-
10
-
11
- <div class="row mb-3">
12
- <div class="col-12">
13
- <div id="activity-map" style="height: 500px;"></div>
14
- <script>
15
- var map = L.map('activity-map', {
16
- fullscreenControl: true
17
- });
18
- L.tileLayer('/tile/grayscale/{z}/{x}/{y}.png', {
19
- maxZoom: 19,
20
- attribution: '{{ map_tile_attribution|safe }}'
21
- }).addTo(map);
22
-
23
- let geojson = L.geoJSON({{ geojson| safe }}, {
24
- style: function (feature) { return { color: feature.properties.color } }
25
- }).addTo(map)
26
- map.fitBounds(geojson.getBounds());
27
- </script>
28
- </div>
29
- </div>
30
-
31
- <div class="row mb-3">
32
- <div class="col">
33
- <h2>Activities</h2>
34
-
35
- <table class="table table-sort table-arrows">
36
- <thead>
37
- <tr>
38
- <th>Name</th>
39
- <th>Date</th>
40
- <th>Distance / km</th>
41
- <th>Elapsed time</th>
42
- <th>Speed / km/h</th>
43
- <th>Equipment</th>
44
- <th>Kind</th>
45
- </tr>
46
- </thead>
47
- <tbody>
48
- {% for activity in activities %}
49
- <tr>
50
- <td><span style="color: {{ activity['color'] }};">█</span> <a
51
- href="{{ url_for('activity.show', id=activity.id) }}">{{
52
- activity.name }}</a></td>
53
- <td>{{ activity.start|dt }}</td>
54
- <td>{{ activity.distance_km | round(1) }}</td>
55
- <td>{{ activity.elapsed_time|td }}</td>
56
- <td>{{ activity.average_speed_moving_kmh|round(1) }}</td>
57
- <td>{{ activity["equipment"] }}</td>
58
- <td>{{ activity["kind"] }}</td>
59
- </tr>
60
- {% endfor %}
61
- {% if activities|length > 1 %}
62
- <tr>
63
- <td><b>Total</b></td>
64
- <td></td>
65
- <td><b>{{ total_distance | round(1) }}</b></td>
66
- <td><b>{{ total_elapsed_time|td }}</b></td>
67
- <td></td>
68
- <td></td>
69
- </tr>
70
- {% endif %}
71
- </tbody>
72
- </table>
73
- </div>
74
- </div>
75
-
76
- <h2>Share picture</h2>
77
-
78
- <p><img class="img-fluid" src="{{ url_for('.day_sharepic', year=year, month=month, day=day) }}" /></p>
79
-
80
- {% endblock %}
@@ -1,42 +0,0 @@
1
- {% extends "page.html.j2" %}
2
-
3
- {% block container %}
4
-
5
- <h1 class="mb-3">Edit Activity</h1>
6
-
7
- <form method="POST">
8
- <div class="mb-3">
9
- <label for="name" class="form-label">Name</label>
10
- <input type="text" class="form-control" id="name" name="name" value="{{ override['name'] }}" />
11
- </div>
12
-
13
- <div class="mb-3">
14
- <label for="kind" class="form-label">Kind</label>
15
- <input type="text" class="form-control" id="kind" name="kind" value="{{ override['kind'] }}" />
16
- </div>
17
-
18
- <div class="mb-3">
19
- <label for="equipment" class="form-label">Equipment</label>
20
- <input type="text" class="form-control" id="equipment" name="equipment" value="{{ override['equipment'] }}" />
21
- </div>
22
-
23
- <div class="mb-3">
24
- <div class="form-check">
25
- <input type="checkbox" class="form-check-input" id="commute" name="commute" {% if override['commute'] %}
26
- checked {% endif %} />
27
- <label for="commute" class="form-check-label">Commute</label>
28
- </div>
29
- </div>
30
-
31
- <div class="mb-3">
32
- <div class="form-check">
33
- <input type="checkbox" class="form-check-input" id="consider_for_achievements"
34
- name="consider_for_achievements" {% if override['consider_for_achievements'] %} checked {% endif %} />
35
- <label for="consider_for_achievements" class="form-check-label">Consider for achievements</label>
36
- </div>
37
- </div>
38
-
39
- <button type="submit" class="btn btn-primary">Save</button>
40
- </form>
41
-
42
- {% endblock %}
File without changes
@@ -1,23 +0,0 @@
1
- from flask import Blueprint
2
- from flask import render_template
3
-
4
- from geo_activity_playground.webui.calendar.controller import CalendarController
5
-
6
-
7
- def make_calendar_blueprint(calendar_controller: CalendarController) -> Blueprint:
8
- blueprint = Blueprint("calendar", __name__, template_folder="templates")
9
-
10
- @blueprint.route("/")
11
- def index():
12
- return render_template(
13
- "calendar/index.html.j2", **calendar_controller.render_overview()
14
- )
15
-
16
- @blueprint.route("/<year>/<month>")
17
- def month(year: str, month: str):
18
- return render_template(
19
- "calendar/month.html.j2",
20
- **calendar_controller.render_month(int(year), int(month))
21
- )
22
-
23
- return blueprint
@@ -1,46 +0,0 @@
1
- {% extends "page.html.j2" %}
2
-
3
- {% block container %}
4
- <div class="row mb-1">
5
- <div class="col">
6
- <h1>Calendar</h1>
7
- </div>
8
- </div>
9
-
10
- <div class="row mb-1">
11
- <div class="col">
12
- <table class="table">
13
- <thead>
14
- <tr>
15
- <th>Year</th>
16
- {% for i in range(1, 13) %}
17
- <th style="text-align: right;">{{ i }}</th>
18
- {% endfor %}
19
- <th style="text-align: right;">Total</th>
20
- </tr>
21
- </thead>
22
- <tbody>
23
- {% for year, month_data in monthly_distances.items() %}
24
- {% set year_int = year|round(0)|int %}
25
- <tr>
26
- <td>{{ year_int }}</td>
27
- {% for month in range(1, 13) %}
28
- <td align="right">
29
- {% set distance = month_data[month] %}
30
- {% if distance %}
31
- <a href="{{ url_for(".month", year=year_int, month=month) }}">{{ distance|int() }} km</a>
32
- {% else %}
33
- 0 km
34
- {% endif %}
35
- </td>
36
- {% endfor %}
37
- <td align="right">{{ yearly_distances[year]|int() }} km</td>
38
- </tr>
39
- {% endfor %}
40
- </tbody>
41
- </table>
42
- </div>
43
- </div>
44
-
45
-
46
- {% endblock %}
@@ -1,55 +0,0 @@
1
- {% extends "page.html.j2" %}
2
-
3
- {% block container %}
4
- <div class="row mb-1">
5
- <div class="col">
6
- <h1>Calendar {{ year }}-{{ "{0:02d}".format(month) }}</h1>
7
- </div>
8
- </div>
9
-
10
- <div class="row mb-1">
11
- <div class="col">
12
- <table class="table">
13
- <thead>
14
- <tr>
15
- <th>Week</th>
16
- <th>Monday</th>
17
- <th>Tuesday</th>
18
- <th>Wednesday</th>
19
- <th>Thursday</th>
20
- <th>Friday</th>
21
- <th>Saturday</th>
22
- <th>Sunday</th>
23
- </tr>
24
- </thead>
25
- <tbody>
26
- {% for week, week_data in weeks.items() %}
27
- <tr>
28
- <td>{{ week }}</td>
29
- {% for day in range(1, 8) %}
30
- <td>
31
- {% if weeks[week][day] %}
32
- <a href="{{ url_for('activity.day', year=year, month=month, day=day_of_month[week][day]) }}"><b>{{
33
- day_of_month[week][day] }}.</b></a>
34
- {% elif day_of_month[week][day] %}
35
- <b>{{ day_of_month[week][day] }}.</b>
36
- {% endif %}
37
-
38
- {% if weeks[week][day] %}
39
- <ul>
40
- {% for activity in weeks[week][day] %}
41
- <li><a href="{{ url_for('activity.show', id=activity.id) }}">{{ activity.name }}</a></li>
42
- {% endfor %}
43
- </ul>
44
- {% endif %}
45
- </td>
46
- {% endfor %}
47
- </tr>
48
- {% endfor %}
49
- </tbody>
50
- </table>
51
- </div>
52
- </div>
53
-
54
-
55
- {% endblock %}
@@ -1,63 +0,0 @@
1
- import datetime
2
- import itertools
3
-
4
- import altair as alt
5
- import pandas as pd
6
-
7
- from geo_activity_playground.core.activities import ActivityRepository
8
- from geo_activity_playground.core.activities import make_geojson_from_time_series
9
- from geo_activity_playground.core.config import Config
10
- from geo_activity_playground.webui.plot_util import make_kind_scale
11
-
12
-
13
- class EntryController:
14
- def __init__(self, repository: ActivityRepository, config: Config) -> None:
15
- self._repository = repository
16
- self._config = config
17
-
18
- def render(self) -> dict:
19
- result = {"latest_activities": []}
20
-
21
- if len(self._repository):
22
- kind_scale = make_kind_scale(self._repository.meta, self._config)
23
- result["distance_last_30_days_plot"] = distance_last_30_days_meta_plot(
24
- self._repository.meta, kind_scale
25
- )
26
-
27
- for activity in itertools.islice(
28
- self._repository.iter_activities(dropna=True), 15
29
- ):
30
- time_series = self._repository.get_time_series(activity["id"])
31
- result["latest_activities"].append(
32
- {
33
- "line_geojson": make_geojson_from_time_series(time_series),
34
- "activity": activity,
35
- }
36
- )
37
- return result
38
-
39
-
40
- def distance_last_30_days_meta_plot(meta: pd.DataFrame, kind_scale: alt.Scale) -> str:
41
- before_30_days = pd.to_datetime(
42
- datetime.datetime.now() - datetime.timedelta(days=31)
43
- )
44
- return (
45
- alt.Chart(
46
- meta.loc[meta["start"] > before_30_days],
47
- width=700,
48
- height=200,
49
- title="Distance per day",
50
- )
51
- .mark_bar()
52
- .encode(
53
- alt.X("yearmonthdate(start)", title="Date"),
54
- alt.Y("sum(distance_km)", title="Distance / km"),
55
- alt.Color("kind", scale=kind_scale, title="Kind"),
56
- [
57
- alt.Tooltip("yearmonthdate(start)", title="Date"),
58
- alt.Tooltip("kind", title="Kind"),
59
- alt.Tooltip("sum(distance_km)", format=".1f", title="Distance / km"),
60
- ],
61
- )
62
- .to_json(format="vega")
63
- )
File without changes
@@ -1,62 +0,0 @@
1
- from flask import Blueprint
2
- from flask import redirect
3
- from flask import render_template
4
- from flask import Response
5
- from flask import url_for
6
-
7
- from geo_activity_playground.webui.authenticator import Authenticator
8
- from geo_activity_playground.webui.authenticator import needs_authentication
9
- from geo_activity_playground.webui.explorer.controller import ExplorerController
10
-
11
-
12
- def make_explorer_blueprint(
13
- explorer_controller: ExplorerController,
14
- authenticator: Authenticator,
15
- ) -> Blueprint:
16
- blueprint = Blueprint("explorer", __name__, template_folder="templates")
17
-
18
- @blueprint.route("/<zoom>")
19
- def map(zoom: str):
20
- return render_template(
21
- "explorer/index.html.j2", **explorer_controller.render(int(zoom))
22
- )
23
-
24
- @blueprint.route("/enable-zoom-level/<zoom>")
25
- @needs_authentication(authenticator)
26
- def enable_zoom_level(zoom: str):
27
- explorer_controller.enable_zoom_level(int(zoom))
28
- return redirect(url_for(".map", zoom=zoom))
29
-
30
- @blueprint.route("/<zoom>/<north>/<east>/<south>/<west>/explored.<suffix>")
31
- def download(zoom: str, north: str, east: str, south: str, west: str, suffix: str):
32
- mimetypes = {"geojson": "application/json", "gpx": "application/xml"}
33
- return Response(
34
- explorer_controller.export_explored_tiles(
35
- int(zoom),
36
- float(north),
37
- float(east),
38
- float(south),
39
- float(west),
40
- suffix,
41
- ),
42
- mimetype=mimetypes[suffix],
43
- headers={"Content-disposition": "attachment"},
44
- )
45
-
46
- @blueprint.route("/<zoom>/<north>/<east>/<south>/<west>/missing.<suffix>")
47
- def missing(zoom: str, north: str, east: str, south: str, west: str, suffix: str):
48
- mimetypes = {"geojson": "application/json", "gpx": "application/xml"}
49
- return Response(
50
- explorer_controller.export_missing_tiles(
51
- int(zoom),
52
- float(north),
53
- float(east),
54
- float(south),
55
- float(west),
56
- suffix,
57
- ),
58
- mimetype=mimetypes[suffix],
59
- headers={"Content-disposition": "attachment"},
60
- )
61
-
62
- return blueprint
File without changes
@@ -1,51 +0,0 @@
1
- import dateutil.parser
2
- from flask import Blueprint
3
- from flask import render_template
4
- from flask import request
5
- from flask import Response
6
-
7
- from geo_activity_playground.core.activities import ActivityRepository
8
- from geo_activity_playground.core.config import Config
9
- from geo_activity_playground.explorer.tile_visits import TileVisitAccessor
10
- from geo_activity_playground.webui.heatmap.heatmap_controller import HeatmapController
11
- from geo_activity_playground.webui.search_util import search_query_from_form
12
- from geo_activity_playground.webui.search_util import SearchQueryHistory
13
-
14
-
15
- def make_heatmap_blueprint(
16
- repository: ActivityRepository,
17
- tile_visit_accessor: TileVisitAccessor,
18
- config: Config,
19
- search_query_history: SearchQueryHistory,
20
- ) -> Blueprint:
21
- heatmap_controller = HeatmapController(repository, tile_visit_accessor, config)
22
- blueprint = Blueprint("heatmap", __name__, template_folder="templates")
23
-
24
- @blueprint.route("/")
25
- def index():
26
- query = search_query_from_form(request.args)
27
- search_query_history.register_query(query)
28
- return render_template(
29
- "heatmap/index.html.j2", **heatmap_controller.render(query)
30
- )
31
-
32
- @blueprint.route("/tile/<int:z>/<int:x>/<int:y>.png")
33
- def tile(x: int, y: int, z: int):
34
- query = search_query_from_form(request.args)
35
- return Response(
36
- heatmap_controller.render_tile(x, y, z, query),
37
- mimetype="image/png",
38
- )
39
-
40
- @blueprint.route(
41
- "/download/<float:north>/<float:east>/<float:south>/<float:west>/heatmap.png"
42
- )
43
- def download(north: float, east: float, south: float, west: float):
44
- query = search_query_from_form(request.args)
45
- return Response(
46
- heatmap_controller.download_heatmap(north, east, south, west, query),
47
- mimetype="image/png",
48
- headers={"Content-disposition": 'attachment; filename="heatmap.png"'},
49
- )
50
-
51
- return blueprint