Changeset d1c4782 in OpenWorkouts-current


Ignore:
Timestamp:
Jan 21, 2019, 10:43:20 AM (5 years ago)
Author:
borja <borja@…>
Branches:
current, feature/docs, master
Children:
be40b02
Parents:
ceae158
Message:

Show a capture of the workout map, as an image, in the dashboard:

  • Added a view to render the tracking map of a workout full screen
  • Added a small shell script that uses chrome to grabs a screenshot of the full screen map view of a workout, then uses imagemagick convert to crop/resize it and finally saves it in a given location
  • Added a static/maps directory to store maps captures
  • Added static/maps to the boring/ignore file
  • Added a tool in utilities.py to call the shell script that captures the screenshot of the map
  • Added a method to the Workout model, that returns the static path to the workout map capture (valid to use with request.static_url()). If there is no capture yet, call the tool to make one
  • Added code to dashboard.pt to show the capture of the map
  • Added a new parameter to te ow maps js code, allowing us to hide/show the zoom controls of the map when building a new one
Files:
3 added
8 edited

Legend:

Unmodified
Added
Removed
  • .boring

    rceae158 rd1c4782  
    138138ow.egg-info/*
    139139ow/static/components
     140ow/static/maps
  • ow/models/workout.py

    rceae158 rd1c4782  
    1 
     1import os
    22from datetime import datetime, timedelta, timezone
    33from decimal import Decimal
     
    1212    copy_blob,
    1313    create_blob,
    14     mps_to_kmph
     14    mps_to_kmph,
     15    save_map_screenshot
    1516)
    1617
     
    419420    def has_fit(self):
    420421        return self.fit_file is not None
     422
     423    @property
     424    def map_screenshot(self):
     425        """
     426        Return the static path to the screenshot image of the map for
     427        this workout (works only for workouts with gps tracking)
     428        """
     429        if not self.has_gpx:
     430            return None
     431
     432        current_path = os.path.abspath(os.path.dirname(__file__))
     433        screenshot_path = os.path.join(
     434            current_path, '../static/maps',
     435            str(self.owner.uid), str(self.workout_id)) + '.png'
     436
     437        if not os.path.exists(screenshot_path):
     438            # screenshot does not exist, generate it
     439            save_map_screenshot(self)
     440
     441        # the value returned is relative to the static files served
     442        # by the app, so we can use request.static_url() with it
     443        static_path = os.path.join('static/maps', str(self.owner.uid),
     444                                   str(self.workout_id))
     445        return 'ow:' + static_path + '.png'
  • ow/static/css/main.css

    rceae158 rd1c4782  
    752752}
    753753
     754.workout-map img {
     755    width: 100%;
     756}
     757
    754758.owo-del a:hover {
    755759    color:red
  • ow/static/js/ow.js

    rceae158 rd1c4782  
    2525    var shadow = spec.shadow;
    2626    var elevation = spec.elevation;
     27    var zoom_control = spec.zoom_control;
    2728
    2829    // OpenStreetMap urls and references
    29     var openstreetmap_url = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
    30     var openstreetmap_attr = 'Map data &copy; <a href="http://www.osm.org">OpenStreetMap</a>'
     30    var openstreetmap_url = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
     31    var openstreetmap_attr = 'Map data &copy; <a href="http://www.osm.org">OpenStreetMap</a>';
    3132
    3233    // Some constants reused through the code
     
    3839    var create_map = function create_map(latitude, longitude, zoom) {
    3940        /* Create a Leaflet map, set center point and add tiles */
    40         map = L.map(map_id, {preferCanvas: true});
     41        map = L.map(map_id, {zoomControl: zoom_control});
    4142        map.setView([latitude, longitude], zoom);
    4243        var tile_layer = L.tileLayer(openstreetmap_url, {
  • ow/templates/dashboard.pt

    rceae158 rd1c4782  
    9090            <div class="workout-intro" tal:content="workout.notes"></div>
    9191
     92            <div class="workout-map" tal:condition="workout.has_gpx">
     93                <a href="" tal:attributes="href request.resource_url(workout)">
     94                    <img src="" tal:attributes="src request.static_url(workout.map_screenshot);
     95                              alt workout.title; title workout.title">
     96                </a>
     97            </div>
     98
    9299            <ul class="workout-options">
    93100              <li class="owo-edit"><a href="" i18n:translate="" tal:attributes="href request.resource_url(workout, 'edit')"><span>edit</span></a></li>
  • ow/templates/workout.pt

    rceae158 rd1c4782  
    160160         end_icon: '${request.static_url('ow:static/components/leaflet-gpx/pin-icon-end.png')}',
    161161         shadow: '${request.static_url('ow:static/components/leaflet-gpx/pin-shadow.png')}',
    162          elevation: true
     162         elevation: true,
     163         zoom_control: true
    163164     });
    164165     workout_map.render();
  • ow/utilities.py

    rceae158 rd1c4782  
    11import re
     2import os
     3import logging
     4import subprocess
    25from datetime import datetime
    36from decimal import Decimal
     
    710from xml.dom import minidom
    811from ZODB.blob import Blob
     12
     13log = logging.getLogger(__name__)
    914
    1015
     
    184189        open_blob.write(data)
    185190    return blob
     191
     192
     193def save_map_screenshot(workout):
     194    if workout.has_gpx:
     195        current_path = os.path.abspath(os.path.dirname(__file__))
     196        tool_path = os.path.join(current_path, '../bin/screenshot_map')
     197
     198        screenshots_path = os.path.join(
     199            current_path, 'static/maps', str(workout.owner.uid))
     200        if not os.path.exists(screenshots_path):
     201            os.makedirs(screenshots_path)
     202
     203        screenshot_path = os.path.join(
     204            screenshots_path, str(workout.workout_id))
     205        screenshot_path += '.png'
     206
     207        subprocess.run(
     208            [tool_path, str(workout.owner.uid), str(workout.workout_id),
     209             screenshot_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     210
     211        return True
     212
     213    return False
  • ow/views/workout.py

    rceae158 rd1c4782  
    214214        content_disposition='attachment; filename="%s"' % gpx_slug,
    215215        body_file=context.tracking_file.open())
     216
     217
     218@view_config(
     219    context=Workout,
     220    name='map',
     221    renderer='ow:templates/workout-map.pt')
     222def workout_map(context, request):
     223    """
     224    Render a page that has only a map with tracking info
     225    """
     226    start_point = {}
     227    if context.has_gpx:
     228        with context.tracking_file.open() as gpx_file:
     229            gpx_contents = gpx_file.read()
     230            gpx_contents = gpx_contents.decode('utf-8')
     231            gpx = gpxpy.parse(gpx_contents)
     232            if gpx.tracks:
     233                track = gpx.tracks[0]
     234                center_point = track.get_center()
     235                start_point = {'latitude': center_point.latitude,
     236                               'longitude': center_point.longitude,
     237                               'elevation': center_point.elevation}
     238    return {'start_point': start_point}
Note: See TracChangeset for help on using the changeset viewer.