geo-activity-playground 0.45.0__py3-none-any.whl → 1.1.0__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 (75) hide show
  1. geo_activity_playground/alembic/versions/dc8073871da7_add_plotspec_group_by.py +28 -0
  2. geo_activity_playground/core/config.py +1 -0
  3. geo_activity_playground/core/datamodel.py +12 -0
  4. geo_activity_playground/core/export.py +129 -0
  5. geo_activity_playground/core/meta_search.py +1 -1
  6. geo_activity_playground/core/parametric_plot.py +101 -47
  7. geo_activity_playground/webui/app.py +10 -1
  8. geo_activity_playground/webui/authenticator.py +4 -2
  9. geo_activity_playground/webui/blueprints/activity_blueprint.py +11 -10
  10. geo_activity_playground/webui/blueprints/auth_blueprint.py +6 -2
  11. geo_activity_playground/webui/blueprints/bubble_chart_blueprint.py +2 -1
  12. geo_activity_playground/webui/blueprints/calendar_blueprint.py +3 -2
  13. geo_activity_playground/webui/blueprints/eddington_blueprints.py +3 -2
  14. geo_activity_playground/webui/blueprints/entry_views.py +11 -11
  15. geo_activity_playground/webui/blueprints/equipment_blueprint.py +2 -1
  16. geo_activity_playground/webui/blueprints/explorer_blueprint.py +343 -197
  17. geo_activity_playground/webui/blueprints/export_blueprint.py +31 -0
  18. geo_activity_playground/webui/blueprints/hall_of_fame_blueprint.py +79 -0
  19. geo_activity_playground/webui/blueprints/plot_builder_blueprint.py +38 -19
  20. geo_activity_playground/webui/blueprints/summary_blueprint.py +114 -240
  21. geo_activity_playground/webui/blueprints/upload_blueprint.py +9 -0
  22. geo_activity_playground/webui/columns.py +40 -7
  23. geo_activity_playground/webui/static/{browserconfig.xml → favicons/browserconfig.xml} +1 -1
  24. geo_activity_playground/webui/static/{site.webmanifest → favicons/site.webmanifest} +2 -2
  25. geo_activity_playground/webui/static/server-side-explorer.js +60 -0
  26. geo_activity_playground/webui/templates/activity/name.html.j2 +4 -4
  27. geo_activity_playground/webui/templates/activity/show.html.j2 +8 -8
  28. geo_activity_playground/webui/templates/auth/index.html.j2 +1 -0
  29. geo_activity_playground/webui/templates/eddington/distance.html.j2 +3 -3
  30. geo_activity_playground/webui/templates/eddington/elevation_gain.html.j2 +3 -3
  31. geo_activity_playground/webui/templates/elevation_eddington/index.html.j2 +3 -3
  32. geo_activity_playground/webui/templates/equipment/index.html.j2 +1 -1
  33. geo_activity_playground/webui/templates/explorer/server-side.html.j2 +42 -36
  34. geo_activity_playground/webui/templates/export/index.html.j2 +39 -0
  35. geo_activity_playground/webui/templates/hall_of_fame/index.html.j2 +58 -0
  36. geo_activity_playground/webui/templates/home.html.j2 +1 -4
  37. geo_activity_playground/webui/templates/page.html.j2 +26 -43
  38. geo_activity_playground/webui/templates/plot-macros.html.j2 +72 -0
  39. geo_activity_playground/webui/templates/plot_builder/edit.html.j2 +12 -7
  40. geo_activity_playground/webui/templates/plot_builder/import-spec.html.j2 +24 -0
  41. geo_activity_playground/webui/templates/plot_builder/index.html.j2 +5 -0
  42. geo_activity_playground/webui/templates/summary/index.html.j2 +23 -230
  43. geo_activity_playground/webui/templates/summary/vega-chart.html.j2 +3 -0
  44. {geo_activity_playground-0.45.0.dist-info → geo_activity_playground-1.1.0.dist-info}/METADATA +2 -1
  45. {geo_activity_playground-0.45.0.dist-info → geo_activity_playground-1.1.0.dist-info}/RECORD +74 -65
  46. geo_activity_playground/webui/templates/explorer/index.html.j2 +0 -148
  47. /geo_activity_playground/webui/static/{bootstrap-dark-mode.js → bootstrap/bootstrap-dark-mode.js} +0 -0
  48. /geo_activity_playground/webui/static/{bootstrap.bundle.min.js → bootstrap/bootstrap.bundle.min.js} +0 -0
  49. /geo_activity_playground/webui/static/{bootstrap.min.css → bootstrap/bootstrap.min.css} +0 -0
  50. /geo_activity_playground/webui/static/{android-chrome-192x192.png → favicons/android-chrome-192x192.png} +0 -0
  51. /geo_activity_playground/webui/static/{android-chrome-512x512.png → favicons/android-chrome-512x512.png} +0 -0
  52. /geo_activity_playground/webui/static/{apple-touch-icon.png → favicons/apple-touch-icon.png} +0 -0
  53. /geo_activity_playground/webui/static/{favicon-16x16.png → favicons/favicon-16x16.png} +0 -0
  54. /geo_activity_playground/webui/static/{favicon-32x32.png → favicons/favicon-32x32.png} +0 -0
  55. /geo_activity_playground/webui/static/{favicon-48x48.png → favicons/favicon-48x48.png} +0 -0
  56. /geo_activity_playground/webui/static/{favicon.ico → favicons/favicon.ico} +0 -0
  57. /geo_activity_playground/webui/static/{favicon.svg → favicons/favicon.svg} +0 -0
  58. /geo_activity_playground/webui/static/{mstile-150x150.png → favicons/mstile-150x150.png} +0 -0
  59. /geo_activity_playground/webui/static/{web-app-manifest-192x192.png → favicons/web-app-manifest-192x192.png} +0 -0
  60. /geo_activity_playground/webui/static/{web-app-manifest-512x512.png → favicons/web-app-manifest-512x512.png} +0 -0
  61. /geo_activity_playground/webui/static/{Leaflet.fullscreen.min.js → leaflet/Leaflet.fullscreen.min.js} +0 -0
  62. /geo_activity_playground/webui/static/{MarkerCluster.Default.css → leaflet/MarkerCluster.Default.css} +0 -0
  63. /geo_activity_playground/webui/static/{MarkerCluster.css → leaflet/MarkerCluster.css} +0 -0
  64. /geo_activity_playground/webui/static/{fullscreen.png → leaflet/fullscreen.png} +0 -0
  65. /geo_activity_playground/webui/static/{fullscreen@2x.png → leaflet/fullscreen@2x.png} +0 -0
  66. /geo_activity_playground/webui/static/{leaflet.css → leaflet/leaflet.css} +0 -0
  67. /geo_activity_playground/webui/static/{leaflet.fullscreen.css → leaflet/leaflet.fullscreen.css} +0 -0
  68. /geo_activity_playground/webui/static/{leaflet.js → leaflet/leaflet.js} +0 -0
  69. /geo_activity_playground/webui/static/{leaflet.markercluster.js → leaflet/leaflet.markercluster.js} +0 -0
  70. /geo_activity_playground/webui/static/{vega-embed@6 → vega/vega-embed@6.js} +0 -0
  71. /geo_activity_playground/webui/static/{vega-lite@4 → vega/vega-lite@4.js} +0 -0
  72. /geo_activity_playground/webui/static/{vega@5 → vega/vega@5.js} +0 -0
  73. {geo_activity_playground-0.45.0.dist-info → geo_activity_playground-1.1.0.dist-info}/LICENSE +0 -0
  74. {geo_activity_playground-0.45.0.dist-info → geo_activity_playground-1.1.0.dist-info}/WHEEL +0 -0
  75. {geo_activity_playground-0.45.0.dist-info → geo_activity_playground-1.1.0.dist-info}/entry_points.txt +0 -0
@@ -15,19 +15,44 @@ column_distance = ColumnDescription(
15
15
  unit="km",
16
16
  format=".1f",
17
17
  )
18
-
19
- column_elevation = ColumnDescription(
20
- name="elevation",
21
- display_name="Elevation",
22
- unit="m",
23
- format=".0f",
24
- )
25
18
  column_elevation_gain = ColumnDescription(
26
19
  name="elevation_gain",
27
20
  display_name="Elevation Gain",
28
21
  unit="m",
29
22
  format=".0f",
30
23
  )
24
+ column_hours = ColumnDescription(
25
+ name="hours",
26
+ display_name="Elapsed time",
27
+ unit="h",
28
+ format=".1f",
29
+ )
30
+ column_hours_moving = ColumnDescription(
31
+ name="hours_moving",
32
+ display_name="Moving time",
33
+ unit="h",
34
+ format=".1f",
35
+ )
36
+ column_calories = ColumnDescription(
37
+ name="calories",
38
+ display_name="Energy",
39
+ unit="kcal",
40
+ format=".1f",
41
+ )
42
+ column_steps = ColumnDescription(
43
+ name="steps",
44
+ display_name="Steps",
45
+ unit="1",
46
+ format=".1f",
47
+ )
48
+ META_COLUMNS = [
49
+ column_distance,
50
+ column_elevation_gain,
51
+ column_hours,
52
+ column_hours_moving,
53
+ column_calories,
54
+ column_steps,
55
+ ]
31
56
 
32
57
  column_speed = ColumnDescription(
33
58
  name="speed",
@@ -35,3 +60,11 @@ column_speed = ColumnDescription(
35
60
  unit="km/h",
36
61
  format=".1f",
37
62
  )
63
+ column_elevation = ColumnDescription(
64
+ name="elevation",
65
+ display_name="Elevation",
66
+ unit="m",
67
+ format=".0f",
68
+ )
69
+
70
+ TIME_SERIES_COLUMNS = [column_speed, column_elevation]
@@ -2,7 +2,7 @@
2
2
  <browserconfig>
3
3
  <msapplication>
4
4
  <tile>
5
- <square150x150logo src="/static/mstile-150x150.png"/>
5
+ <square150x150logo src="/static/favicons/mstile-150x150.png"/>
6
6
  <TileColor>#da532c</TileColor>
7
7
  </tile>
8
8
  </msapplication>
@@ -3,13 +3,13 @@
3
3
  "short_name": "MySite",
4
4
  "icons": [
5
5
  {
6
- "src": "/static/web-app-manifest-192x192.png",
6
+ "src": "/static/favicons/web-app-manifest-192x192.png",
7
7
  "sizes": "192x192",
8
8
  "type": "image/png",
9
9
  "purpose": "maskable"
10
10
  },
11
11
  {
12
- "src": "/static/web-app-manifest-512x512.png",
12
+ "src": "/static/favicons/web-app-manifest-512x512.png",
13
13
  "sizes": "512x512",
14
14
  "type": "image/png",
15
15
  "purpose": "maskable"
@@ -0,0 +1,60 @@
1
+
2
+ let tile_layer = null
3
+
4
+ function changeColor(method) {
5
+ if (tile_layer) {
6
+ map.removeLayer(tile_layer)
7
+ }
8
+ tile_layer = L.tileLayer(`/explorer/${zoom}/tile/{z}/{x}/{y}.png?color_strategy=${method}`, {
9
+ maxZoom: 19,
10
+ attribution: map_tile_attribution
11
+ }).addTo(map)
12
+ }
13
+
14
+ let map = L.map('explorer-map', {
15
+ fullscreenControl: true,
16
+ center: [center_latitude, center_longitude],
17
+ zoom: 12
18
+ });
19
+
20
+ changeColor('default')
21
+
22
+ if (bbox) {
23
+ map.fitBounds(L.geoJSON(bbox).getBounds())
24
+ }
25
+
26
+ map.on('click', e => {
27
+ fetch(`/explorer/${zoom}/info/${e.latlng.lat}/${e.latlng.lng}`)
28
+ .then(response => response.json())
29
+ .then(data => {
30
+ if (!data.tile_xy) {
31
+ return;
32
+ }
33
+ console.debug(data);
34
+
35
+ let lines = [
36
+ `<dt>Tile</dt>`,
37
+ `<dd>${data.tile_xy}</dd>`,
38
+ `<dt>First visit</dt>`,
39
+ `<dd>${data.first_time}</br><a href=/activity/${data.first_activity_id}>${data.first_activity_name}</a></dd>`,
40
+ `<dt>Last visit</dt>`,
41
+ `<dd>${data.last_time}</br><a href=/activity/${data.last_activity_id}>${data.last_activity_name}</a></dd>`,
42
+ `<dt>Number of visits</dt>`,
43
+ `<dd>${data.num_visits}</dd>`,
44
+ ]
45
+ if (data.this_cluster_size) {
46
+ lines.push(`<dt>This cluster size</dt><dd>${data.this_cluster_size}</dd>`)
47
+ }
48
+
49
+ L.popup()
50
+ .setLatLng(e.latlng)
51
+ .setContent('<dl>' + lines.join('') + '</dl>')
52
+ .openOn(map);
53
+ }
54
+ );
55
+ });
56
+
57
+ function downloadAs(suffix) {
58
+ bounds = map.getBounds();
59
+ window.location.href = `/explorer/${zoom}/${bounds.getNorth()}/${bounds.getEast()}/${bounds.getSouth()}/${bounds.getWest()}/${suffix}`
60
+ }
@@ -30,19 +30,19 @@
30
30
 
31
31
  <div class="row mb-3">
32
32
  <div class="col-md-4">
33
- {{ vega_direct("tick_plot", tick_plot) }}
33
+ {{ vega_direct(tick_plot) }}
34
34
  </div>
35
35
  <div class="col-md-4">
36
- {{ vega_direct("equipment_plot", equipment_plot) }}
36
+ {{ vega_direct(equipment_plot) }}
37
37
  </div>
38
38
  </div>
39
39
 
40
40
  <div class="row mb-3">
41
41
  <div class="col-md-4">
42
- {{ vega_direct("distance_plot", distance_plot) }}
42
+ {{ vega_direct(distance_plot) }}
43
43
  </div>
44
44
  <div class="col-md-4">
45
- {{ vega_direct("minutes_plot", minutes_plot) }}
45
+ {{ vega_direct(minutes_plot) }}
46
46
  </div>
47
47
  </div>
48
48
 
@@ -182,13 +182,13 @@
182
182
 
183
183
  <div class="row mb-3">
184
184
  <div class="col-md-4">
185
- {{ vega_direct("distance_time_plot", distance_time_plot) }}
185
+ {{ vega_direct(distance_time_plot) }}
186
186
  </div>
187
187
  <div class="col-md-4">
188
- {{ vega_direct("speed_time_plot", speed_time_plot) }}
188
+ {{ vega_direct(speed_time_plot) }}
189
189
  </div>
190
190
  <div class="col-md-4">
191
- {{ vega_direct("speed_distribution_plot", speed_distribution_plot) }}
191
+ {{ vega_direct(speed_distribution_plot) }}
192
192
  </div>
193
193
  </div>
194
194
 
@@ -201,11 +201,11 @@
201
201
 
202
202
  <div class="row mb-3">
203
203
  <div class="col-md-4">
204
- {{ vega_direct("elevation_time_plot", elevation_time_plot) }}
204
+ {{ vega_direct(elevation_time_plot) }}
205
205
  </div>
206
206
  {% if elevation_gain_cum_plot is defined %}
207
207
  <div class="col-md-4">
208
- {{ vega_direct("elevation_gain_cum_plot", elevation_gain_cum_plot) }}
208
+ {{ vega_direct(elevation_gain_cum_plot) }}
209
209
  </div>
210
210
  {% endif %}
211
211
  </div>
@@ -216,11 +216,11 @@
216
216
 
217
217
  <div class="row mb-3">
218
218
  <div class="col-md-4">
219
- {{ vega_direct("heartrate_time_plot", heartrate_time_plot) }}
219
+ {{ vega_direct(heartrate_time_plot) }}
220
220
  </div>
221
221
  <div class="col-md-4">
222
222
  {% if heart_zones_plot is defined %}
223
- {{ vega_direct("heart_zones_plot", heart_zones_plot) }}
223
+ {{ vega_direct(heart_zones_plot) }}
224
224
  {% else %}
225
225
  <p>Your activity has heart data, but this program doesn't know your maximum heart rate (or birth year) and
226
226
  therefore cannot compute the heart rate zones. Go to the <a
@@ -235,7 +235,7 @@
235
235
 
236
236
  <div class="row mb-3">
237
237
  <div class="col-md-4">
238
- {{ vega_direct("cadence_time_plot", cadence_time_plot) }}
238
+ {{ vega_direct(cadence_time_plot) }}
239
239
  </div>
240
240
  </div>
241
241
  {% endif %}
@@ -14,6 +14,7 @@
14
14
  <input type="password" class="form-control" id="password" name="password" />
15
15
  </div>
16
16
 
17
+ <input type="hidden" name="redirect" value="{{ redirect }}" />
17
18
  <button type="submit" class="btn btn-primary">Log In</button>
18
19
  </form>
19
20
  {% endif %}
@@ -54,7 +54,7 @@
54
54
  <p>In a graphical representation, the Eddington number is the distance where the red line intersects with the
55
55
  blue area.</p>
56
56
 
57
- {{ vega_direct("logarithmic_plot", logarithmic_plot) }}
57
+ {{ vega_direct(logarithmic_plot) }}
58
58
  </div>
59
59
  </div>
60
60
 
@@ -63,7 +63,7 @@
63
63
 
64
64
  <p>How did the Eddington number evolve over time?</p>
65
65
 
66
- {{ vega_direct("eddington_number_history_plot", eddington_number_history_plot) }}
66
+ {{ vega_direct(eddington_number_history_plot) }}
67
67
  </div>
68
68
 
69
69
  <div class="mb-3">
@@ -94,7 +94,7 @@
94
94
 
95
95
  <div class="row mb-3">
96
96
  <div class="col-md-8">
97
- {{ vega_direct("eddington_per_week_plot", eddington_per_week_plot) }}
97
+ {{ vega_direct(eddington_per_week_plot) }}
98
98
  </div>
99
99
 
100
100
  <div class="col-md-4">
@@ -76,7 +76,7 @@
76
76
  <p>In a graphical representation, the Eddington number is the elevation gain where the red line intersects with the
77
77
  blue area.</p>
78
78
 
79
- {{ vega_direct("logarithmic_plot", logarithmic_plot) }}
79
+ {{ vega_direct(logarithmic_plot) }}
80
80
  </div>
81
81
  </div>
82
82
 
@@ -85,7 +85,7 @@
85
85
 
86
86
  <p>How did the Eddington number evolve over time?</p>
87
87
 
88
- {{ vega_direct("eddington_number_history_plot", eddington_number_history_plot) }}
88
+ {{ vega_direct(eddington_number_history_plot) }}
89
89
  </div>
90
90
 
91
91
  <div class="mb-3">
@@ -116,7 +116,7 @@
116
116
 
117
117
  <div class="row mb-3">
118
118
  <div class="col-md-8">
119
- {{ vega_direct("eddington_per_week_plot", eddington_per_week_plot) }}
119
+ {{ vega_direct(eddington_per_week_plot) }}
120
120
  </div>
121
121
 
122
122
  <div class="col-md-4">
@@ -80,7 +80,7 @@
80
80
  the
81
81
  blue area.</p>
82
82
 
83
- {{ vega_direct("logarithmic_plot", logarithmic_plot) }}
83
+ {{ vega_direct(logarithmic_plot) }}
84
84
  </div>
85
85
  </div>
86
86
 
@@ -89,7 +89,7 @@
89
89
 
90
90
  <p>How did the Eddington number evolve over time?</p>
91
91
 
92
- {{ vega_direct("eddington_number_history_plot", eddington_number_history_plot) }}
92
+ {{ vega_direct(eddington_number_history_plot) }}
93
93
  </div>
94
94
 
95
95
  <div class="mb-3">
@@ -120,7 +120,7 @@
120
120
 
121
121
  <div class="row mb-3">
122
122
  <div class="col-md-8">
123
- {{ vega_direct("eddington_per_week_plot", eddington_per_week_plot) }}
123
+ {{ vega_direct(eddington_per_week_plot) }}
124
124
  </div>
125
125
 
126
126
  <div class="col-md-4">
@@ -35,7 +35,7 @@
35
35
  <div class="row mb-3">
36
36
  <div class="col">
37
37
  <h2>Monthly Equipment Usage</h2>
38
- {{ vega_direct("stacked_area_chart", stacked_area_chart) }}
38
+ {{ vega_direct(stacked_area_chart) }}
39
39
  </div>
40
40
  </div>
41
41
 
@@ -14,10 +14,24 @@
14
14
 
15
15
  <div class="row mb-3">
16
16
  <div class="col">
17
- <h2>Map with explored tiles</h2>
17
+ <p>You have {{ num_tiles }} explored tiles. There are {{ num_cluster_tiles }} cluster tiles in
18
+ total. Your largest cluster consists of {{ max_cluster_size }} tiles. Your largest square has size
19
+ {{ square_size }}².
20
+ </p>
21
+ <p>Open the <a
22
+ href="{{ url_for('square_planner.index', zoom=zoom, x=square_x, y=square_y, size=square_size) }}">Square
23
+ Planner</a> to plan the next extension.</p>
18
24
  </div>
19
25
  </div>
20
26
 
27
+ <div class="btn-group mb-3" role="group">
28
+ <button type="button" class="btn btn-primary" onclick="changeColor('colorful_cluster')">Colorful Cluster</button>
29
+ <button type="button" class="btn btn-primary" onclick="changeColor('max_cluster')">Max Cluster</button>
30
+ <button type="button" class="btn btn-primary" onclick="changeColor('first')">First Visit</button>
31
+ <button type="button" class="btn btn-primary" onclick="changeColor('last')">Last Visit</button>
32
+ <button type="button" class="btn btn-primary" onclick="changeColor('visits')">Number of Visits</button>
33
+ </div>
34
+
21
35
  <div class="row mb-3">
22
36
  <div class="col">
23
37
  <div id="explorer-map" class="mb-1" style="height: 800px;"></div>
@@ -26,47 +40,39 @@
26
40
  onclick="downloadAs('missing.geojson')">Missing as GeoJSON</a> or <a href="#"
27
41
  onclick="downloadAs('missing.gpx')"">Missing as GPX</a>.</p>
28
42
  <script>
29
- let map = L.map('explorer-map', {
30
- fullscreenControl: true,
31
- center: [{{ center.latitude }}, {{ center.longitude }}],
32
- zoom: 12
33
- });
34
- L.tileLayer('/explorer/{{ zoom }}/tile/{z}/{x}/{y}.png', {
35
- maxZoom: 19,
36
- attribution: '{{ map_tile_attribution|safe }}'
37
- }).addTo(map)
38
-
39
- let bbox = {{ center.bbox| safe }}
40
- if (bbox) {
41
- map.fitBounds(L.geoJSON(bbox).getBounds())
42
- }
43
+ const center_latitude = {{ center.latitude }};
44
+ const center_longitude = {{ center.longitude }};
45
+ const zoom = {{ zoom }};
46
+ const bbox = {{ center.bbox | safe }};
47
+ const map_tile_attribution = '{{ map_tile_attribution|safe }}';
43
48
  </script>
49
+ <script src=" /static/server-side-explorer.js"></script>
44
50
  </div>
45
51
  </div>
46
52
 
47
53
  <div class=" row mb-3">
48
- <div class="col">
49
- <h2>Tile history</h2>
50
- </div>
54
+ <div class="col">
55
+ <h2>Tile history</h2>
51
56
  </div>
57
+ </div>
52
58
 
53
- <div class="row mb-3">
54
- <div class="col-md-4">
55
- {% if plot_tile_evolution|length > 0 %}
56
- {{ vega_direct("plot_tile_evolution", plot_tile_evolution) }}
57
- {% endif %}
58
- </div>
59
- <div class="col-md-4">
60
- {% if plot_cluster_evolution|length > 0 %}
61
- {{ vega_direct("plot_cluster_evolution", plot_cluster_evolution) }}
62
- {% endif %}
63
- </div>
64
- <div class="col-md-4">
65
- {% if plot_square_evolution|length > 0 %}
66
- {{ vega_direct("plot_square_evolution", plot_square_evolution) }}
67
- {% endif %}
68
- </div>
59
+ <div class="row mb-3">
60
+ <div class="col-md-4">
61
+ {% if plot_tile_evolution|length > 0 %}
62
+ {{ vega_direct(plot_tile_evolution) }}
63
+ {% endif %}
64
+ </div>
65
+ <div class="col-md-4">
66
+ {% if plot_cluster_evolution|length > 0 %}
67
+ {{ vega_direct(plot_cluster_evolution) }}
68
+ {% endif %}
69
69
  </div>
70
+ <div class="col-md-4">
71
+ {% if plot_square_evolution|length > 0 %}
72
+ {{ vega_direct(plot_square_evolution) }}
73
+ {% endif %}
74
+ </div>
75
+ </div>
70
76
 
71
- {% endif %}
72
- {% endblock %}
77
+ {% endif %}
78
+ {% endblock %}
@@ -0,0 +1,39 @@
1
+ {% extends "page.html.j2" %}
2
+
3
+ {% block container %}
4
+
5
+ <h1>Export metadata and activities</h1>
6
+
7
+ <p>Here you can export all metadata and activities as a ZIP file. Depending on the file format chosen, exporting an
8
+ activity can take around one second. You can observe a progress bar in the terminal.</p>
9
+
10
+ <form method="get" enctype="multipart/form-data" action="{{ url_for('.export') }}">
11
+ <div class="mb-3">
12
+ <label for="meta_format" class="form-label">Metadata format</label>
13
+ <select name="meta_format" id="meta_format" class="form-select" aria-label="Metadata format">
14
+ <option value="parquet">Parquet</option>
15
+ {# <option value="json">JSON</option> #}
16
+ <option value="csv">CSV</option>
17
+ <option value="xlsx">Excel</option>
18
+ <option value="ods">OpenDocument Spreadsheet (LibreOffice)</option>
19
+ </select>
20
+ </div>
21
+
22
+ <div class="mb-3">
23
+ <label for="activity_format" class="form-label">Activity time series format</label>
24
+ <select name="activity_format" id="activity_format" class="form-select"
25
+ aria-label="Activity time series format">
26
+ <option value="">No export of activities</option>
27
+ <option value="parquet">Parquet</option>
28
+ <option value="csv">CSV</option>
29
+ <option value="geojson">GeoJSON</option>
30
+ <option value="gpx">GPX</option>
31
+ <option value="xlsx">Excel</option>
32
+ <option value="ods">OpenDocument Spreadsheet (LibreOffice)</option>
33
+ </select>
34
+ </div>
35
+ <button type="submit" class="btn btn-primary">Export</button>
36
+ </form>
37
+
38
+
39
+ {% endblock %}
@@ -0,0 +1,58 @@
1
+ {% extends "page.html.j2" %}
2
+
3
+ {% block container %}
4
+
5
+ <h1>Hall of Fame</h1>
6
+
7
+ <div class="mb-3">
8
+ {% include "search_form.html.j2" %}
9
+ </div>
10
+
11
+ <script>
12
+ function add_map(id, geojson) {
13
+ let map = L.map(`map-${id}`, {
14
+ fullscreenControl: true
15
+ })
16
+ L.tileLayer('/tile/color/{z}/{x}/{y}.png', {
17
+ maxZoom: 19,
18
+ attribution: '{{ map_tile_attribution|safe }}'
19
+ }).addTo(map)
20
+
21
+ let geojson_layer = L.geoJSON(geojson).addTo(map)
22
+ map.fitBounds(geojson_layer.getBounds())
23
+ return map
24
+ }
25
+ </script>
26
+
27
+ {% for activity_batch in nominations|batch(3) %}
28
+ <div class="row row-cols-1 row-cols-md-3 g-4 mb-3">
29
+ {% for activity, reasons, line_geojson in activity_batch %}
30
+ <div class="col">
31
+ <div class="card">
32
+ <div class="card-img-top" id="map-{{ activity.id }}" style="height: 200px; width: 100%;"></div>
33
+ <script>
34
+ let map{{ activity.id }} = add_map("{{ activity.id }}", {{ line_geojson | safe }})
35
+ </script>
36
+ <div class="card-body">
37
+ <a href="{{ url_for('activity.show', id=activity.id) }}">
38
+ <h5 class="card-title">{{ activity["name"] }}</h5>
39
+ </a>
40
+ <p class="card-text">
41
+ <ul style='list-style-type: "🏆 "'>
42
+ {% for reason in reasons %}
43
+ <li>{{ reason }}</li>
44
+ {% endfor %}
45
+ </ul>
46
+ </p>
47
+ <p class="card-text"><small class="text-body-secondary"></small>{{ activity.kind }} with {{
48
+ (activity.distance_km)|round(1) }} km / {{activity.elevation_gain|round|int}} m in {{
49
+ activity.elapsed_time|td }} on {{ activity.start|dt }}</small></p>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ {% endfor %}
54
+ </div>
55
+ {% endfor %}
56
+
57
+
58
+ {% endblock %}
@@ -8,10 +8,7 @@
8
8
  <div class="row mb-3">
9
9
  <div class="col">
10
10
  <h2>Last 30 days</h2>
11
- {{ vega_direct("distance-last-30-days", distance_last_30_days_plot) }}
12
- {% if elevation_gain_last_30_days_plot %}
13
- {{ vega_direct("elevation-gain-last-30-days", elevation_gain_last_30_days_plot) }}
14
- {% endif %}
11
+ {{ tabbed_vega(last_30_days_plot) }}
15
12
  </div>
16
13
  </div>
17
14