geo-activity-playground 1.1.0__tar.gz → 1.2.0__tar.gz

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 (168) hide show
  1. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/PKG-INFO +1 -1
  2. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/datamodel.py +35 -6
  3. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/photo_blueprint.py +65 -56
  4. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/settings_blueprint.py +17 -0
  5. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/equipment/index.html.j2 +3 -3
  6. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/hall_of_fame/index.html.j2 +2 -3
  7. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/home.html.j2 +1 -8
  8. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/photo/new.html.j2 +1 -1
  9. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/settings/index.html.j2 +9 -0
  10. geo_activity_playground-1.2.0/geo_activity_playground/webui/templates/settings/tile-source.html.j2 +33 -0
  11. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/pyproject.toml +1 -1
  12. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/LICENSE +0 -0
  13. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/__init__.py +0 -0
  14. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/__main__.py +0 -0
  15. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/alembic/README +0 -0
  16. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/alembic/env.py +0 -0
  17. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/alembic/script.py.mako +0 -0
  18. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/alembic/versions/0f02b92c4f94_add_tag_color.py +0 -0
  19. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/alembic/versions/38882503dc7c_add_tags_to_activities.py +0 -0
  20. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/alembic/versions/451e7836b53d_add_square_planner_bookmark.py +0 -0
  21. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/alembic/versions/63d3b7f6f93c_initial_version.py +0 -0
  22. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/alembic/versions/93cc82ad1b60_add_parametricplotspec.py +0 -0
  23. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/alembic/versions/ab83b9d23127_add_upstream_id.py +0 -0
  24. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/alembic/versions/b03491c593f6_add_crop_indices.py +0 -0
  25. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/alembic/versions/da2cba03b71d_add_photos.py +0 -0
  26. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/alembic/versions/dc8073871da7_add_plotspec_group_by.py +0 -0
  27. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/alembic/versions/e02e27876deb_add_square_planner_bookmark_name.py +0 -0
  28. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/alembic/versions/script.py.mako +0 -0
  29. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/__init__.py +0 -0
  30. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/activities.py +0 -0
  31. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/config.py +0 -0
  32. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/coordinates.py +0 -0
  33. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/enrichment.py +0 -0
  34. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/export.py +0 -0
  35. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/heart_rate.py +0 -0
  36. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/meta_search.py +0 -0
  37. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/missing_values.py +0 -0
  38. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/parametric_plot.py +0 -0
  39. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/paths.py +0 -0
  40. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/privacy_zones.py +0 -0
  41. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/raster_map.py +0 -0
  42. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/similarity.py +0 -0
  43. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/summary_stats.py +0 -0
  44. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/tasks.py +0 -0
  45. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/test_datamodel.py +0 -0
  46. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/test_meta_search.py +0 -0
  47. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/test_missing_values.py +0 -0
  48. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/test_summary_stats.py +0 -0
  49. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/test_tiles.py +0 -0
  50. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/test_time_conversion.py +0 -0
  51. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/tiles.py +0 -0
  52. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/core/time_conversion.py +0 -0
  53. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/explorer/__init__.py +0 -0
  54. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/explorer/grid_file.py +0 -0
  55. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/explorer/tile_visits.py +0 -0
  56. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/explorer/video.py +0 -0
  57. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/heatmap_video.py +0 -0
  58. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/importers/__init__.py +0 -0
  59. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/importers/activity_parsers.py +0 -0
  60. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/importers/csv_parser.py +0 -0
  61. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/importers/directory.py +0 -0
  62. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/importers/strava_api.py +0 -0
  63. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/importers/strava_checkout.py +0 -0
  64. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/importers/test_csv_parser.py +0 -0
  65. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/importers/test_directory.py +0 -0
  66. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/importers/test_strava_api.py +0 -0
  67. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/__init__.py +0 -0
  68. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/app.py +0 -0
  69. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/authenticator.py +0 -0
  70. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/__init__.py +0 -0
  71. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/activity_blueprint.py +0 -0
  72. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/auth_blueprint.py +0 -0
  73. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/bubble_chart_blueprint.py +0 -0
  74. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/calendar_blueprint.py +0 -0
  75. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/eddington_blueprints.py +0 -0
  76. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/entry_views.py +0 -0
  77. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/equipment_blueprint.py +0 -0
  78. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/explorer_blueprint.py +0 -0
  79. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/export_blueprint.py +0 -0
  80. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/hall_of_fame_blueprint.py +0 -0
  81. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/heatmap_blueprint.py +0 -0
  82. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/plot_builder_blueprint.py +0 -0
  83. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/search_blueprint.py +0 -0
  84. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/square_planner_blueprint.py +0 -0
  85. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/summary_blueprint.py +0 -0
  86. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/tile_blueprint.py +0 -0
  87. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/blueprints/upload_blueprint.py +0 -0
  88. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/columns.py +0 -0
  89. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/flasher.py +0 -0
  90. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/plot_util.py +0 -0
  91. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/search_util.py +0 -0
  92. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/bootstrap/bootstrap-dark-mode.js +0 -0
  93. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/bootstrap/bootstrap.bundle.min.js +0 -0
  94. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/bootstrap/bootstrap.min.css +0 -0
  95. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/favicons/android-chrome-192x192.png +0 -0
  96. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/favicons/android-chrome-512x512.png +0 -0
  97. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/favicons/apple-touch-icon.png +0 -0
  98. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/favicons/browserconfig.xml +0 -0
  99. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/favicons/favicon-16x16.png +0 -0
  100. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/favicons/favicon-32x32.png +0 -0
  101. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/favicons/favicon-48x48.png +0 -0
  102. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/favicons/favicon.ico +0 -0
  103. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/favicons/favicon.svg +0 -0
  104. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/favicons/mstile-150x150.png +0 -0
  105. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/favicons/site.webmanifest +0 -0
  106. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/favicons/web-app-manifest-192x192.png +0 -0
  107. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/favicons/web-app-manifest-512x512.png +0 -0
  108. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/images/layers-2x.png +0 -0
  109. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/images/layers.png +0 -0
  110. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/images/marker-icon-2x.png +0 -0
  111. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/images/marker-icon.png +0 -0
  112. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/images/marker-shadow.png +0 -0
  113. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/leaflet/Leaflet.fullscreen.min.js +0 -0
  114. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/leaflet/MarkerCluster.Default.css +0 -0
  115. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/leaflet/MarkerCluster.css +0 -0
  116. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/leaflet/fullscreen.png +0 -0
  117. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/leaflet/fullscreen@2x.png +0 -0
  118. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/leaflet/leaflet.css +0 -0
  119. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/leaflet/leaflet.fullscreen.css +0 -0
  120. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/leaflet/leaflet.js +0 -0
  121. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/leaflet/leaflet.markercluster.js +0 -0
  122. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/server-side-explorer.js +0 -0
  123. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/table-sort.min.js +0 -0
  124. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/vega/vega-embed@6.js +0 -0
  125. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/vega/vega-lite@4.js +0 -0
  126. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/static/vega/vega@5.js +0 -0
  127. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/activity/day.html.j2 +0 -0
  128. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/activity/edit.html.j2 +0 -0
  129. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/activity/lines.html.j2 +0 -0
  130. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/activity/name.html.j2 +0 -0
  131. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/activity/show.html.j2 +0 -0
  132. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/activity/trim.html.j2 +0 -0
  133. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/auth/index.html.j2 +0 -0
  134. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/bubble_chart/index.html.j2 +0 -0
  135. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/calendar/index.html.j2 +0 -0
  136. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/calendar/month.html.j2 +0 -0
  137. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/eddington/distance.html.j2 +0 -0
  138. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/eddington/elevation_gain.html.j2 +0 -0
  139. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/elevation_eddington/index.html.j2 +0 -0
  140. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/explorer/server-side.html.j2 +0 -0
  141. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/export/index.html.j2 +0 -0
  142. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/heatmap/index.html.j2 +0 -0
  143. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/page.html.j2 +0 -0
  144. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/photo/map.html.j2 +0 -0
  145. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/plot-macros.html.j2 +0 -0
  146. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/plot_builder/edit.html.j2 +0 -0
  147. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/plot_builder/import-spec.html.j2 +0 -0
  148. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/plot_builder/index.html.j2 +0 -0
  149. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/search/index.html.j2 +0 -0
  150. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/search_form.html.j2 +0 -0
  151. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/settings/admin-password.html.j2 +0 -0
  152. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/settings/color-schemes.html.j2 +0 -0
  153. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/settings/heart-rate.html.j2 +0 -0
  154. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/settings/manage-equipments.html.j2 +0 -0
  155. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/settings/manage-kinds.html.j2 +0 -0
  156. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/settings/metadata-extraction.html.j2 +0 -0
  157. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/settings/privacy-zones.html.j2 +0 -0
  158. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/settings/segmentation.html.j2 +0 -0
  159. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/settings/sharepic.html.j2 +0 -0
  160. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/settings/strava.html.j2 +0 -0
  161. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/settings/tags-edit.html.j2 +0 -0
  162. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/settings/tags-list.html.j2 +0 -0
  163. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/settings/tags-new.html.j2 +0 -0
  164. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/square_planner/index.html.j2 +0 -0
  165. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/summary/index.html.j2 +0 -0
  166. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/summary/vega-chart.html.j2 +0 -0
  167. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/upload/index.html.j2 +0 -0
  168. {geo_activity_playground-1.1.0 → geo_activity_playground-1.2.0}/geo_activity_playground/webui/templates/upload/reload.html.j2 +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: geo-activity-playground
3
- Version: 1.1.0
3
+ Version: 1.2.0
4
4
  Summary: Analysis of geo data activities like rides, runs or hikes.
5
5
  License: MIT
6
6
  Author: Martin Ueding
@@ -32,6 +32,17 @@ logger = logging.getLogger(__name__)
32
32
  DEFAULT_UNKNOWN_NAME = "Unknown"
33
33
 
34
34
 
35
+ def format_timedelta(v: datetime.timedelta):
36
+ if pd.isna(v):
37
+ return "—"
38
+ else:
39
+ seconds = v.total_seconds()
40
+ h = int(seconds // 3600)
41
+ m = int(seconds // 60 % 60)
42
+ s = int(seconds // 1 % 60)
43
+ return f"{h}:{m:02d}:{s:02d}"
44
+
45
+
35
46
  class ActivityMeta(TypedDict):
36
47
  average_speed_elapsed_kmh: float
37
48
  average_speed_moving_kmh: float
@@ -165,6 +176,23 @@ class Activity(DB.Model):
165
176
  else:
166
177
  return self.raw_time_series
167
178
 
179
+ @property
180
+ def emoji_string(self) -> str:
181
+ bits = []
182
+ if self.kind:
183
+ bits.append(f"{self.kind.name} with")
184
+ if self.distance_km:
185
+ bits.append(f"📏 {round(self.distance_km, 1)} km")
186
+ if self.elapsed_time:
187
+ bits.append(f"⏱️ {format_timedelta(self.elapsed_time)} h")
188
+ if self.elevation_gain:
189
+ bits.append(f"⛰️ {round(self.elevation_gain, 1)} m")
190
+ if self.calories:
191
+ bits.append(f"🍭 {self.calories} kcal")
192
+ if self.steps:
193
+ bits.append(f"👣 {self.steps}")
194
+ return " ".join(bits)
195
+
168
196
  def delete_data(self) -> None:
169
197
  for path in [
170
198
  TIME_SERIES_DIR() / f"{self.id}.parquet",
@@ -229,14 +257,15 @@ def query_activity_meta(clauses: list = []) -> pd.DataFrame:
229
257
  .order_by(Activity.start)
230
258
  ).all()
231
259
  df = pd.DataFrame(rows)
232
- # If the search yields only activities without time information, the dtype isn't derived correctly.
233
- df["start"] = pd.to_datetime(df["start"])
234
- # start = df["start"].to_list()
235
- # random.shuffle(start)
236
- # df["start"] = pd.Series(start)
237
- df["elapsed_time"] = pd.to_timedelta(df["elapsed_time"])
238
260
 
239
261
  if len(df):
262
+ # If the search yields only activities without time information, the dtype isn't derived correctly.
263
+ df["start"] = pd.to_datetime(df["start"])
264
+ # start = df["start"].to_list()
265
+ # random.shuffle(start)
266
+ # df["start"] = pd.Series(start)
267
+ df["elapsed_time"] = pd.to_timedelta(df["elapsed_time"])
268
+
240
269
  for old, new in [
241
270
  ("elapsed_time", "average_speed_elapsed_kmh"),
242
271
  ("moving_time", "average_speed_moving_kmh"),
@@ -12,6 +12,7 @@ from flask import render_template
12
12
  from flask import request
13
13
  from flask import Response
14
14
  from flask import url_for
15
+ from flask.typing import ResponseReturnValue
15
16
  from PIL import Image
16
17
  from PIL import ImageOps
17
18
 
@@ -123,7 +124,7 @@ def make_photo_blueprint(
123
124
 
124
125
  @blueprint.route("/new", methods=["GET", "POST"])
125
126
  @needs_authentication(authenticator)
126
- def new() -> Response:
127
+ def new() -> ResponseReturnValue:
127
128
  if request.method == "POST":
128
129
  # check if the post request has the file part
129
130
  if "file" not in request.files:
@@ -132,66 +133,74 @@ def make_photo_blueprint(
132
133
  )
133
134
  return redirect(url_for(".new"))
134
135
 
135
- file = request.files["file"]
136
- # If the user does not select a file, the browser submits an
137
- # empty file without a filename.
138
- if file.filename == "":
139
- flasher.flash_message("No selected file.", FlashTypes.WARNING)
140
- return redirect(url_for(".new"))
141
- if not file:
142
- flasher.flash_message("Empty file uploaded.", FlashTypes.WARNING)
143
- return redirect(url_for(".new"))
136
+ new_photos: list[Photo] = []
137
+ for file in request.files.getlist("file"):
138
+ # If the user does not select a file, the browser submits an
139
+ # empty file without a filename.
140
+ if file.filename == "":
141
+ flasher.flash_message("No selected file.", FlashTypes.WARNING)
142
+ return redirect(url_for(".new"))
143
+ if not file:
144
+ flasher.flash_message("Empty file uploaded.", FlashTypes.WARNING)
145
+ return redirect(url_for(".new"))
146
+
147
+ filename = str(uuid.uuid4()) + pathlib.Path(file.filename).suffix
148
+ path = PHOTOS_DIR() / "original" / filename
149
+ path.parent.mkdir(exist_ok=True)
150
+ file.save(path)
151
+ metadata = get_metadata_from_image(path)
152
+
153
+ if "time" not in metadata:
154
+ flasher.flash_message(
155
+ f"Your image '{file.filename}' doesn't have the EXIF attribute 'EXIF DateTimeOriginal' and hence cannot be dated.",
156
+ FlashTypes.DANGER,
157
+ )
158
+ continue
159
+ time: datetime.datetime = metadata["time"]
160
+
161
+ activity = DB.session.scalar(
162
+ sqlalchemy.select(Activity)
163
+ .where(
164
+ Activity.start.is_not(None),
165
+ Activity.elapsed_time.is_not(None),
166
+ Activity.start <= time,
167
+ )
168
+ .order_by(Activity.start.desc())
169
+ .limit(1)
170
+ )
171
+ if activity is None or activity.start + activity.elapsed_time < time:
172
+ flasher.flash_message(
173
+ f"Your image '{file.filename}' is from {time} but no activity could be found. Please first upload an activity or fix the time in the photo.",
174
+ FlashTypes.DANGER,
175
+ )
176
+ continue
177
+
178
+ if "latitude" not in metadata:
179
+ time_series = activity.time_series
180
+ print(time_series)
181
+ row = time_series.loc[time_series["time"] >= time].iloc[0]
182
+ metadata["latitude"] = row["latitude"]
183
+ metadata["longitude"] = row["longitude"]
184
+
185
+ photo = Photo(
186
+ filename=filename,
187
+ time=time,
188
+ latitude=metadata["latitude"],
189
+ longitude=metadata["longitude"],
190
+ activity=activity,
191
+ )
144
192
 
145
- filename = str(uuid.uuid4()) + pathlib.Path(file.filename).suffix
146
- path = PHOTOS_DIR() / "original" / filename
147
- path.parent.mkdir(exist_ok=True)
148
- file.save(path)
149
- metadata = get_metadata_from_image(path)
193
+ DB.session.add(photo)
194
+ DB.session.commit()
195
+ new_photos.append(photo)
150
196
 
151
- if "time" not in metadata:
197
+ if new_photos:
152
198
  flasher.flash_message(
153
- "Your image doesn't have the EXIF attribute 'EXIF DateTimeOriginal' and hence cannot be dated.",
154
- FlashTypes.DANGER,
199
+ f"Added {len(new_photos)} new photos.", FlashTypes.SUCCESS
155
200
  )
201
+ return redirect(f"/activity/{new_photos[-1].activity.id}")
202
+ else:
156
203
  return redirect(url_for(".new"))
157
- time: datetime.datetime = metadata["time"]
158
-
159
- activity = DB.session.scalar(
160
- sqlalchemy.select(Activity)
161
- .where(
162
- Activity.start.is_not(None),
163
- Activity.elapsed_time.is_not(None),
164
- Activity.start <= time,
165
- )
166
- .order_by(Activity.start.desc())
167
- .limit(1)
168
- )
169
- if activity is None or activity.start + activity.elapsed_time < time:
170
- flasher.flash_message(
171
- f"Your image is from {time} but no activity could be found. Please first upload an activity or fix the time in the photo",
172
- FlashTypes.DANGER,
173
- )
174
- print(activity)
175
-
176
- if "latitude" not in metadata:
177
- time_series = activity.time_series
178
- print(time_series)
179
- row = time_series.loc[time_series["time"] >= time].iloc[0]
180
- metadata["latitude"] = row["latitude"]
181
- metadata["longitude"] = row["longitude"]
182
-
183
- photo = Photo(
184
- filename=filename,
185
- time=time,
186
- latitude=metadata["latitude"],
187
- longitude=metadata["longitude"],
188
- activity=activity,
189
- )
190
-
191
- DB.session.add(photo)
192
- DB.session.commit()
193
-
194
- return redirect(f"/activity/{activity.id}")
195
204
  else:
196
205
  return render_template("photo/new.html.j2")
197
206
 
@@ -447,6 +447,23 @@ def make_settings_blueprint(
447
447
  else:
448
448
  return render_template("settings/tags-edit.html.j2", tag=tag)
449
449
 
450
+ @blueprint.route("/tile-source", methods=["GET", "POST"])
451
+ @needs_authentication(authenticator)
452
+ def tile_source() -> str:
453
+ if request.method == "POST":
454
+ config_accessor().map_tile_url = request.form["map_tile_url"]
455
+ config_accessor().map_tile_attribution = request.form[
456
+ "map_tile_attribution"
457
+ ]
458
+ config_accessor.save()
459
+ flasher.flash_message("Tile source updated.", FlashTypes.SUCCESS)
460
+ return render_template(
461
+ "settings/tile-source.html.j2",
462
+ map_tile_url=config_accessor().map_tile_url,
463
+ map_tile_attribution=config_accessor().map_tile_attribution,
464
+ test_url=config_accessor().map_tile_url.format(zoom=14, x=8514, y=5504),
465
+ )
466
+
450
467
  return blueprint
451
468
 
452
469
 
@@ -49,13 +49,13 @@
49
49
  <h3>{{ equipment }}</h3>
50
50
  <div class="row mb-3">
51
51
  <div class="col-md-4">
52
- {{ vega_direct(data.total_distances_plot_id, data.total_distances_plot) }}
52
+ {{ vega_direct(data.total_distances_plot) }}
53
53
  </div>
54
54
  <div class="col-md-4">
55
- {{ vega_direct(data.yearly_distance_plot_id, data.yearly_distance_plot) }}
55
+ {{ vega_direct(data.yearly_distance_plot) }}
56
56
  </div>
57
57
  <div class="col-md-4">
58
- {{ vega_direct(data.usages_plot_id, data.usages_plot) }}
58
+ {{ vega_direct(data.usages_plot) }}
59
59
  </div>
60
60
  </div>
61
61
  {% endfor %}
@@ -44,9 +44,8 @@
44
44
  {% endfor %}
45
45
  </ul>
46
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>
47
+ <p class="card-text"><small class="text-body-secondary"></small>{{ activity.emoji_string }} on {{
48
+ activity.start|dt }}</small></p>
50
49
  </div>
51
50
  </div>
52
51
  </div>
@@ -46,14 +46,7 @@
46
46
  <h5 class="card-title">{{ elem.activity.name }}</h5>
47
47
  </a>
48
48
  <p class="card-text">
49
- {{ elem.activity.kind.name }} with
50
- 📏 {{ (elem.activity.distance_km)|round(1) }} km
51
- {% if elem.activity.elapsed_time %}
52
- ⏱️ {{ elem.activity.elapsed_time|td }}
53
- {% endif %}
54
- {% if elem.activity.elevation_gain %}
55
- ⛰️ {{ (elem.activity.elevation_gain)|round|int }} m
56
- {% endif %}
49
+ {{ elem.activity.emoji_string }}
57
50
  </p>
58
51
  {% if elem.activity.start %}
59
52
  <p class="card-text"><small class="text-body-secondary">{{ elem.activity.start|dt }}</small></p>
@@ -6,7 +6,7 @@
6
6
  <form method="POST" enctype="multipart/form-data">
7
7
  <div class="mb-3">
8
8
  <label for="file" class="form-label">Photo file</label>
9
- <input type="file" name="file" id="file" class="form-control">
9
+ <input type="file" name="file" id="file" class="form-control" multiple>
10
10
  </div>
11
11
  <button type="submit" class="btn btn-primary">Upload</button>
12
12
  </form>
@@ -56,6 +56,15 @@
56
56
  </div>
57
57
  </div>
58
58
  </div>
59
+ <div class="col">
60
+ <div class="card">
61
+ <div class="card-body">
62
+ <h5 class="card-title">Map tile source</h5>
63
+ <p class="card-text">Change the source of the map tiles.</p>
64
+ <a href="{{ url_for('.tile_source') }}" class="btn btn-primary">Change tile source</a>
65
+ </div>
66
+ </div>
67
+ </div>
59
68
  <div class="col">
60
69
  <div class="card">
61
70
  <div class="card-body">
@@ -0,0 +1,33 @@
1
+ {% extends "page.html.j2" %}
2
+
3
+ {% block container %}
4
+
5
+ <h1 class="mb-3">Tile Source</h1>
6
+
7
+ <p>You can change the tile source to be whatever you like. Be aware that different sources have different licensing
8
+ constraints. It is on you to make sure that you are allowed to use the tiles from the source that you enter. See <a
9
+ href="https://wiki.openstreetmap.org/wiki/Raster_tile_providers" target="_blank">this list of raster tile
10
+ providers</a> for inspiration.</p>
11
+
12
+
13
+ <form action="" method="POST" class="mb-3">
14
+ <div class="mb-3">
15
+ <label for="map_tile_url" class="form-label">Map tile URL</label>
16
+ <input type="text" class="form-control" id="map_tile_url" name="map_tile_url" value="{{ map_tile_url }}" />
17
+ </div>
18
+ <div class="mb-3">
19
+ <label for="map_tile_attribution" class="form-label">Map tile attribution</label>
20
+ <input type="text" class="form-control" id="map_tile_attribution" name="map_tile_attribution"
21
+ value="{{ map_tile_attribution|e }}" />
22
+ </div>
23
+
24
+ <button type="submit" class="btn btn-primary">Save</button>
25
+ </form>
26
+
27
+ <h2>Test image</h2>
28
+
29
+ <p>This is a tile using your current tile source:</p>
30
+
31
+ <p><img src="{{ test_url }}"></p>
32
+
33
+ {% endblock %}
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "geo-activity-playground"
3
- version = "1.1.0"
3
+ version = "1.2.0"
4
4
  description = "Analysis of geo data activities like rides, runs or hikes."
5
5
  authors = ["Martin Ueding <mu@martin-ueding.de>"]
6
6
  license = "MIT"