- Timestamp:
- Apr 22, 2019, 6:14:53 PM (5 years ago)
- Branches:
- current
- Children:
- 0dedfbe
- Parents:
- e52a502
- Location:
- ow
- Files:
-
- 1 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
ow/models/root.py
re52a502 r42baca4 43 43 'nickname': CatalogFieldIndex('nickname'), 44 44 'sport': CatalogFieldIndex('sport'), 45 'hashed': CatalogFieldIndex('hashed'), 45 46 } 46 47 return indexes … … 140 141 def sports_json(self): 141 142 return json.dumps(self.sports) 143 144 def get_workout_by_hash(self, hashed): 145 if hashed is not None: 146 # for some reason, when searching for None 147 # the catalog will return all workouts 148 res = self.query(Eq('hashed', hashed)) 149 if res: 150 return next(res) 151 return None -
ow/models/workout.py
re52a502 r42baca4 136 136 137 137 @property 138 def hashed(self): 139 """ 140 Return a unique hash that we use to look for duplicated workouts. 141 The hash contains: owner's uid, start time, duration and distance 142 """ 143 hashed = '' 144 if self.owner is not None: 145 hashed += str(self.owner.uid) 146 hashed += self.start.strftime('%Y%m%d%H%M%S') 147 hashed += str(self.duration.seconds) 148 hashed += str(self.distance) 149 return hashed 150 151 @property 138 152 def trimmed_notes(self): 139 153 """ -
ow/templates/add_workout.pt
re52a502 r42baca4 25 25 ${form.csrf_token()} 26 26 27 <fieldset> 28 <p> 29 <label for="title" i18n:translate="">Title</label> 30 ${form.errorlist('title')} 31 ${form.text('title')} 32 </p> 33 <p> 34 <label for="notes" i18n:translate="">Notes</label> 35 ${form.errorlist('notes')} 36 ${form.textarea('notes', rows=10, cols=50)} 37 </p> 38 <p> 39 <label for="tracking_file" i18n:translate=""> 40 Workout file (gpx, fit)</label> 41 ${form.errorlist('tracking_file')} 42 ${form.file('tracking_file')} 43 </p> 44 </fieldset> 27 <tal:is_duplicate tal:condition="duplicate is not None"> 28 <article class="workout-resume"> 45 29 46 <tal:with-localizer tal:define="localizer get_localizer(request)"> 47 ${form.submit("submit", localizer.translate(_('Save')), **{'class':"button button-normal"})} 48 </tal:with-localizer> 30 <h2 class="workout-title"> 31 <tal:warning i18n:translate="">THIS MAY BE A DUPLICATE OF:</tal:warning> 32 <a href="" tal:content="duplicate.title" 33 tal:attributes="href request.resource_url(duplicate)"></a> 34 </h2> 35 36 <ul class="workout-info"> 37 <li> 38 <tal:c tal:content="duplicate.sport"></tal:c> 39 </li> 40 <li> 41 <tal:c tal:content="duplicate.start_in_timezone(context.timezone)"></tal:c> 42 </li> 43 <li> 44 <!--! use the properly formatted duration instead of the timedelta object --> 45 <tal:c tal:content="duplicate._duration"></tal:c> 46 </li> 47 <li tal:condition="duplicate.distance"> 48 <tal:c tal:content="duplicate.rounded_distance"></tal:c> km 49 </li> 50 <li tal:condition="duplicate.uphill"> 51 +<tal:c tal:content="duplicate.uphill"></tal:c> m 52 </li> 53 </ul> 54 55 <div class="workout-map" tal:condition="duplicate.has_gpx"> 56 <a href="" tal:attributes="href request.resource_url(duplicate)"> 57 <tal:has-screenshot tal:condition="duplicate.map_screenshot is not None"> 58 <img src="" tal:attributes="src request.static_url(duplicate.map_screenshot); 59 alt duplicate.title; title duplicate.title"> 60 </tal:has-screenshot> 61 <tal:has-not-screenshot tal:condition="duplicate.map_screenshot is None"> 62 <img src="" tal:attributes="src request.static_url('ow:static/media/img/no_map.gif'); 63 alt duplicate.title; title duplicate.title; class 'js-needs-map'"> 64 </tal:has-not-screenshot> 65 </a> 66 </div> 67 68 </article> 69 70 <div> 71 </tal:is_duplicate> 72 73 <fieldset> 74 75 <p> 76 <label for="title" i18n:translate="">Title</label> 77 ${form.errorlist('title')} 78 ${form.text('title')} 79 </p> 80 81 <p> 82 <label for="notes" i18n:translate="">Notes</label> 83 ${form.errorlist('notes')} 84 ${form.textarea('notes', rows=10, cols=50)} 85 </p> 86 87 <p> 88 <label for="tracking_file" i18n:translate=""> 89 Workout file (gpx, fit)</label> 90 ${form.errorlist('tracking_file')} 91 ${form.file('tracking_file')} 92 </p> 93 94 <p tal:condition="duplicate is not None"> 95 <label for="allow_duplicates" i18n:translate="">Allow duplicated workouts</label> 96 <small i18n:translate=""> 97 Mark this checkbox if you want to add to override the mechanism not allowing duplicated workouts 98 </small> 99 <input type="checkbox" name="allow_duplicates"> 100 </p> 101 102 </fieldset> 103 104 <tal:with-localizer tal:define="localizer get_localizer(request)"> 105 ${form.submit("submit", localizer.translate(_('Save')), **{'class':"button button-normal"})} 106 </tal:with-localizer> 49 107 50 108 ${form.end()} -
ow/tests/models/test_root.py
re52a502 r42baca4 35 35 # a new OpenWorkouts instance has a catalog created automatically 36 36 assert isinstance(root.catalog, Catalog) 37 assert len(root.catalog) == 338 for key in ['email', 'nickname', 'sport' ]:37 assert len(root.catalog) == 4 38 for key in ['email', 'nickname', 'sport', 'hashed']: 39 39 assert key in root.catalog 40 40 41 41 def test_update_indexes(self, root): 42 42 indexes = sorted([i for i in root.catalog]) 43 assert indexes == ['email', ' nickname', 'sport']43 assert indexes == ['email', 'hashed', 'nickname', 'sport'] 44 44 # remove one index 45 45 del root.catalog['email'] 46 46 indexes = sorted([i for i in root.catalog]) 47 assert indexes == [' nickname', 'sport']47 assert indexes == ['hashed', 'nickname', 'sport'] 48 48 # now update indexes, the index will be back there 49 49 root._update_indexes() 50 50 indexes = sorted([i for i in root.catalog]) 51 assert indexes == ['email', ' nickname', 'sport']51 assert indexes == ['email', 'hashed', 'nickname', 'sport'] 52 52 53 53 def test_add_user_ok(self, root): -
ow/tests/test_catalog.py
re52a502 r42baca4 56 56 changes = update_indexes(catalog, indexes) 57 57 assert changes['added'] == ['newindex'] 58 assert changes['removed'] == ['email', 'nickname', 'sport' ]58 assert changes['removed'] == ['email', 'nickname', 'sport', 'hashed'] 59 59 60 60 def test_update_indexes_empty(self, root): … … 63 63 changes = update_indexes(catalog, indexes) 64 64 assert changes['added'] == [] 65 assert changes['removed'] == ['email', 'nickname', 'sport' ]65 assert changes['removed'] == ['email', 'nickname', 'sport', 'hashed'] 66 66 67 67 def test_install_catalog(self): -
ow/views/workout.py
re52a502 r42baca4 89 89 form = Form(request, schema=UploadedWorkoutSchema()) 90 90 91 duplicate = None 92 allow_duplicates = request.POST.get('allow_duplicates') == 'on' 93 91 94 if 'submit' in request.POST and form.validate(): 92 95 # Grab some information from the tracking file … … 98 101 # Add basic info gathered from the file 99 102 workout.load_from_file() 100 # Add the workout 101 context.add_workout(workout) 102 return HTTPFound(location=request.resource_url(workout)) 103 # Ensure this workout is not a duplicate of an existing workout. 104 # 105 # hashed is not "complete" for a workout that has not been added 106 # yet, as it does not have the owner set, so we have to "build it" 107 hashed = str(context.uid) + workout.hashed 108 duplicate = request.root.get_workout_by_hash(hashed) 109 110 if duplicate and not allow_duplicates: 111 form.errors['tracking_file'] = _( 112 'This workout looks like a duplicate of another workout, ' 113 'please enable workout duplicates below to save it' 114 ) 115 else: 116 # Add the workout 117 context.add_workout(workout) 118 return HTTPFound(location=request.resource_url(workout)) 103 119 104 120 return { 105 'form': FormRenderer(form) 121 'form': FormRenderer(form), 122 'duplicate': duplicate 106 123 } 107 124
Note: See TracChangeset
for help on using the changeset viewer.