From 86cb01527923ccaef3fb92371a9591d7cba5b048 Mon Sep 17 00:00:00 2001
From: Sam
Date: Sun, 25 Aug 2019 18:54:33 +0200
Subject: [PATCH] API - get gpx and chart data for an activity segment - #14
---
docs/_sources/api/activities.rst.txt | 4 +-
docs/api/activities.html | 123 ++++++++++++++++
docs/http-routingtable.html | 10 ++
docs/objects.inv | Bin 750 -> 782 bytes
docs/searchindex.js | 2 +-
docsrc/source/api/activities.rst | 4 +-
.../fittrackee_api/activities/activities.py | 138 +++++++++++++++++-
.../fittrackee_api/activities/utils_gpx.py | 48 +++++-
.../tests/test_activities_api_1_post.py | 73 +++++++++
9 files changed, 394 insertions(+), 8 deletions(-)
diff --git a/docs/_sources/api/activities.rst.txt b/docs/_sources/api/activities.rst.txt
index 51b82b2b..14853645 100644
--- a/docs/_sources/api/activities.rst.txt
+++ b/docs/_sources/api/activities.rst.txt
@@ -11,4 +11,6 @@ Activities
activities.delete_activity,
activities.get_map,
activities.get_activity_gpx,
- activities.get_activity_chart_data
+ activities.get_activity_chart_data,
+ activities.get_segment_gpx,
+ activities.get_segment_chart_data
diff --git a/docs/api/activities.html b/docs/api/activities.html
index 824a9ecf..a60cf51d 100644
--- a/docs/api/activities.html
+++ b/docs/api/activities.html
@@ -958,6 +958,129 @@
+
+-
+
GET
/api/activities/
(int: activity_id)/gpx/segment/
(int: segment_id)
+Get gpx file for an activity segment displayed on map with Leaflet
+Example request:
+GET /api/activities/3/gpx/segment/0 HTTP/1.1
+Content-Type: application/json
+
+
+Example response:
+HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+ "data": {
+ "gpx": "gpx file content"
+ },
+ "message": "",
+ "status": "success"
+}
+
+
+
+- Parameters
+
+auth_user_id (integer) – authenticate user id (from JSON Web Token)
+activity_id (integer) – activity id
+segment_id (integer) – segment id
+
+
+- Request Headers
+-
+
+- Status Codes
+
+
|
diff --git a/docs/objects.inv b/docs/objects.inv
index 8799981b1471b7521da34d8627d50d594403526c..14af34ef395a4fb1ee7474ee332d8b8912178653 100644
GIT binary patch
delta 669
zcmV;O0%HB{1)geSfudkq5Qgvk3QN6g4=(C;Z&9U4IaG?8^t|%I1gru^W~j3N
zzWxMbvs-Akm&l%Z-^cb~&n9O*&sl-|H%ATwsS*2Q1xUVSZJ27
zL3%Mp29%Xf{uJMd(^TV~U4uHWhmKh1ji`8+(o`zps2H{K2p~pG4mttmBRaoU
zhk%|JI7(P+SAP>^(Wo@Xo34Vk9A*_F#T##6>v_C<1(8F^amQw?iyBvmlTh&iL2gG)
z4u|P^SH%Y!2axe4G&<*zPzYHjKXEP`8NJwfhh9ibtTq}sopfPz&sdMw-p~z>d!Cci
zW085PKDKEa=gZ0H61vvLa2>O3@28Xh_8Q1r_`njz?tfM=Uu?@~w8GGpA3SukpU#$b
z((<|OA_fmH`d?_k@>q(3(AB0!9;SKbA3$R9kAgg?k?PXCV8}&h47@AhJ$9I&vphc$
zl^Jz+pI!cTN51eWkRNuE1=l~42iKOom~l2;hD1Bv5b~loGN@Bnx&5}0d@ecpsfU^R
zG4Co+y?-`TPC={uW~M~Vvo~P+b1b+%X2p+gmQ~QrMQqp^8ZGuwD}K_$EU9&%c;xsh
zS@8=%$<$$+##DQ$p5q=nN3vFwEBoj#)F-UxyC_H1o$ZbWV6v!}4jXf&w)tmPL55O{
z=LUva2vl7$XJyMf^&KQbA;W#%6uMg#h7xj8rxsO#CA}_F2}@suTPU5M?@9Itr@x$0
D`?gCG
delta 636
zcmV-?0)zdI2JQureSfW$J#X7E5QcaC3Ibi+ffc%X3kn3tP#{Rs*`URXL{t_9>Qu!4
zzWkIZQg-FWi$UJK??WAVq)XO|l2s`F2ox}o2C?7QfaE(_X1+CeYQN|Vr8+?)3oXhu
zNH2#=6qEWlrre1R_kMmp2>#W9IkbRq0qv40oEj8epf)de(|=}sW}%*8)m+*!le^Di
zWz{f+2hNb)r9c|-wk%)wANN_;fbs=TtS@)^=YJ1STj}J_@tr(O1>D%-)O!PT#HMUz
zExMehQyE9csFNoEIbv4m1ei
zzJe%$3%ucDoPUd2SBz6oivdAxM@C6F-?@k?nP)cog`iSoIq~%XG1AYj=C8p5p;KM~ai=E8o$dX-GKFPsvC9
zI=e3#fT^lkI$X?ewaY)V8VXc$Jhm`2QlfqpOU6&4)90WVN)>yIFymIeOeVb
W(%UkXu}mXeLz(>CC&gd+v>*eMFEfY$
diff --git a/docs/searchindex.js b/docs/searchindex.js
index 0590b191..3d126f7c 100644
--- a/docs/searchindex.js
+++ b/docs/searchindex.js
@@ -1 +1 @@
-Search.setIndex({docnames:["api/activities","api/auth","api/index","api/records","api/sports","api/stats","api/users","changelog","features","index","installation","troubleshooting/administrator","troubleshooting/index","troubleshooting/user"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,sphinx:56},filenames:["api/activities.rst","api/auth.rst","api/index.rst","api/records.rst","api/sports.rst","api/stats.rst","api/users.rst","changelog.md","features.rst","index.rst","installation.rst","troubleshooting/administrator.rst","troubleshooting/index.rst","troubleshooting/user.rst"],objects:{"":{"/api/activities":[0,1,1,"post--api-activities"],"/api/activities/(int:activity_id)":[0,3,1,"patch--api-activities-(int-activity_id)"],"/api/activities/(int:activity_id)/chart_data":[0,0,1,"get--api-activities-(int-activity_id)-chart_data"],"/api/activities/(int:activity_id)/gpx":[0,0,1,"get--api-activities-(int-activity_id)-gpx"],"/api/activities/map/(map_id)":[0,0,1,"get--api-activities-map-(map_id)"],"/api/activities/no_gpx":[0,1,1,"post--api-activities-no_gpx"],"/api/auth/login":[1,1,1,"post--api-auth-login"],"/api/auth/logout":[1,0,1,"get--api-auth-logout"],"/api/auth/picture":[1,1,1,"post--api-auth-picture"],"/api/auth/profile":[1,0,1,"get--api-auth-profile"],"/api/auth/profile/edit":[1,1,1,"post--api-auth-profile-edit"],"/api/auth/register":[1,1,1,"post--api-auth-register"],"/api/ping":[6,0,1,"get--api-ping"],"/api/records":[3,0,1,"get--api-records"],"/api/sports":[4,0,1,"get--api-sports"],"/api/sports/(int:sport_id)":[4,0,1,"get--api-sports-(int-sport_id)"],"/api/stats/(int:user_id)/by_sport":[5,0,1,"get--api-stats-(int-user_id)-by_sport"],"/api/stats/(int:user_id)/by_time":[5,0,1,"get--api-stats-(int-user_id)-by_time"],"/api/users":[6,0,1,"get--api-users"],"/api/users/(user_id)":[6,0,1,"get--api-users-(user_id)"],"/api/users/(user_id)/picture":[6,0,1,"get--api-users-(user_id)-picture"]}},objnames:{"0":["http","get","HTTP get"],"1":["http","post","HTTP post"],"2":["http","delete","HTTP delete"],"3":["http","patch","HTTP patch"]},objtypes:{"0":"http:get","1":"http:post","2":"http:delete","3":"http:patch"},terms:{"default":[0,5],"export":9,"float":0,"int":[0,4,5],"null":[0,1,6],"return":[0,3],"static":10,"true":6,"try":[0,1],NOT:[0,1,4],Not:[0,1,4,5,6],That:1,The:10,Use:7,_can_be_delet:4,accord:9,account:8,acit:0,activ:[2,5,7,9],activity_d:[0,3],activity_id:[0,3],adapt:10,add:[7,8,9],admin:[1,6,8,10],administr:[0,1,8,9,12],again:[0,1,3,4,5,6],all:[3,4,5,6,10],allow:[0,1,9],alpinequest:9,alreadi:1,also:[9,10],android:9,api:[0,1,3,4,5,6,8,9,10,11],app:9,applic:[0,1,3,4,5,6,9,10],arch:10,archiv:10,ascent:0,auth:[0,1,3,4,5,6],auth_token:1,auth_user_id:[0,3,4,5,6],authent:[0,2,3,4,5,6,9],author:[0,1,3,4,5,6],avail:3,ave_spe:0,ave_speed_from:0,ave_speed_to:0,averag:[0,3,8],backup:10,bad:[0,1],bearer:[0,1,3,4,5,6],befor:10,beta:10,bike:[0,4,8],bio:[1,6],biographi:1,birth:1,birth_dat:[1,6],bound:0,build:10,by_sport:5,by_tim:5,calcul:7,calendar:[7,8],can:[8,9,10],chang:[9,10],charact:[1,12],chart:[0,8,10],chart_data:0,check:[6,11],client:[10,11],clone:10,code:[0,1,3,4,5,6],column:12,com:[1,6,10],config:[10,11],confirm:1,contact:[0,1],content:[0,1,3,4,5,6],coordin:10,copi:10,correctli:[7,11],coverag:9,creat:[0,1,8],created_at:[1,6],creation:8,creation_d:0,credenti:1,current:7,custom:[10,11],cycl:[4,8],dark:10,darkski:8,dashboard:[7,9],data:[0,1,3,4,5,6,9,10,12],databas:10,date:[0,1,5,8],debian:10,delet:[0,1,8],depend:7,desc:0,descent:0,describ:10,detail:[6,7,9],develop:9,directori:10,disabl:[1,8,10],displai:[0,7,8,9,10],distanc:[0,3,7,8],distance_from:0,distance_to:0,document:9,doe:[0,5,6],don:1,download:10,durat:[0,3,7,8],duration_from:0,duration_to:0,dure:1,edit:[1,8],elev:[0,8,10],email:[1,6,10],encount:10,end:[0,5],endpoint:[2,6,12],enter:8,environn:11,error:[0,1,7],europ:[1,6],even:8,exampl:[0,1,3,4,5,6,9,10,11],exist:[0,1,5,6,9,11],exodu:9,expir:[0,1,3,4,5,6],extens:[0,1],fa33f4d996844a5c73ecd1ae24456ab8:0,fals:[0,1,4,6],farest:[3,8],featur:9,fetch:10,file:[0,1,7,8,9,10,11],filter:[7,8],first:1,first_nam:[1,6],fittracke:10,fittrackee_api:10,fix:9,flask:10,flaticon:10,follow:[3,10],forbidden:[0,1],forecast:10,form:[0,1],format:[0,1,5],former:10,forrunn:9,found:[0,1,4,5,6],frame:5,freepik:10,fri:0,from:[0,3,4,5,6,9,10],gener:10,get:[0,1,3,4,5,6],gif:1,git:10,github:10,gmt:[0,1,3,6],gpl:9,gpx:[0,7,8,9,10],gpxpy:10,have:0,header:[0,1,3,4,5,6],health:6,hike:[4,8],his:8,http:[0,1,3,4,5,6,10,11],icon:10,imag:[0,1,6,10],img:4,improv:9,incorrect:7,info:1,inform:9,initi:[10,11],instal:9,instanc:10,integ:[0,3,4,5,6],intern:[0,1],invalid:[0,1,3,4,5,6],issu:[9,10],jan:0,javascript:10,jpeg:6,jpg:1,json:[0,1,3,4,5,6,12],jul:[0,1,3,6],keep:9,kei:[8,10],label:4,last:[1,10],last_nam:[1,6],latitud:0,leaflet:[0,10],least:0,line:12,linux:10,list:9,local:9,localhost:[10,11],locat:[1,6],log:[0,1,3,4,5,6,9,10],login:[1,10],logout:1,longest:[3,8],longitud:0,made:[10,11],mai:10,make:10,makefil:[10,11],mandatori:[0,10],map:[0,8,9,10],map_id:0,match:1,max:0,max_alt:0,max_spe:0,max_speed_from:0,max_speed_to:0,maxim:0,maximum:[3,8],mean:11,messag:[0,1,6],min_alt:0,minim:[0,9],mobil:9,modification_d:0,mon:0,mondai:5,montain:8,month:[5,7,8],more:9,morn:0,mountain:4,move:[0,7],mpwoadmin:10,multipart:[0,1],must:[1,8],name:1,nb_activ:[1,5,6],nb_sport:[1,6],necessari:10,need:10,network:11,next_act:0,no_gpx:0,note:[0,7,8,9,10],now:[8,10],number:0,oauth:[0,1,3,4,5,6],object:[0,1],one:0,onli:[0,8,9],open:[9,10],order:0,other:10,out:1,outdoor:9,own:9,owner:8,packag:10,page:0,pagin:0,paramet:[0,1,3,4,5,6],pari:[1,6],pars:[10,12],part:[0,1],password:[1,10],password_conf:1,past:10,patch:0,paus:[0,7],payload:[0,1],per:0,per_pag:0,permiss:0,pg_dump:10,pictur:[1,6],ping:6,pleas:[0,1,3,4,5,6],png:[0,1,4],pong:6,possibl:9,post:[0,1],postgresql:10,prerequisit:9,previous_act:0,privai:9,product:[9,10],profil:1,proprietari:9,provid:[0,1,3,4,5,6,8],pull:10,python:[9,10],queri:[0,5],react:10,react_app_api_url:11,readi:[9,10],rebuild:11,rechart:[0,10],record:[0,2,7,8,9],record_typ:[0,3],redux:10,regist:[1,10],registr:[1,8,10],reinstal:10,relat:10,releas:[7,10],repo:10,report:9,repositori:10,request:[0,1,3,4,5,6,11],requir:1,respons:[0,1,3,4,5,6],restart:10,run:[4,8,10],runner:9,sam:[1,6],samr1:10,sat:6,search:7,second:0,see:[8,9,10,11],segment:[0,7],select:[0,1],serv:10,server:[0,1,9,10],sever:9,signatur:[0,1,3,4,5,6],singl:6,sky:10,some:[0,7,10],sorri:1,sort:0,speed:[0,3,8,10],sport:[0,2,5,8,9,10],sport_id:[0,3,4,5],standard:8,start:[0,5,10],stat:[5,7],staticmap:10,statist:[2,9],statu:[0,1,3,4,5,6],step:10,still:9,stop:10,store:9,street:9,string:[0,1,5],success:[0,1,3,4,5,6],successfulli:1,sun:[0,1,3,6],sundai:[0,5],support:[7,8],system:10,tab:11,tar:10,test:[9,10],them:9,thi:[0,7,9,10],thunderforest:10,time:[0,1,5,8],timezon:[1,6,7],titl:0,todo:[10,13],token:[0,1,3,4,5,6],tooltip:7,total:7,total_dist:[1,5,6],total_dur:[1,5,6],track:9,tracker:9,transport:[4,8],troubleshoot:9,type:[0,1,3,4,5,6],unauthor:[0,1,3,4,5,6],undefin:11,under:9,unexpect:12,updat:[0,1,7,10],upgrad:9,upload:[7,8,10],user:[0,1,2,3,4,5,7,8,9,10,12],user_id:[0,3,5,6],usernam:[1,6],using:[0,9],valid:[0,1,3,4,5,6],valu:[0,3,10],variabl:11,version:9,view:7,virtualenv:10,walk:[4,8],weather:[7,8,10],weather_end:0,weather_start:0,web:[0,1,3,4,5,6,9],week:5,weekm:5,were:7,wget:10,when:7,with_gpx:0,without:[0,5,8,9],workout:9,written:10,www:10,xzf:10,yarn:10,year:5,yet:[9,10],you:[0,9],your:9,zip:0,zone:1},titles:["Activities","Authentication","API documentation","Records","Sports","Statistics","Users","Change log","Features","FitTrackee","Installation","Administrator","Troubleshooting","User"],titleterms:{"new":7,activ:[0,8],administr:11,api:2,authent:1,bug:7,chang:7,charact:11,close:7,column:11,content:9,dashboard:8,data:11,detail:8,dev:10,document:2,environ:10,featur:[7,8],fittracke:9,fix:7,improv:7,instal:10,issu:7,json:11,line:11,list:8,log:7,minim:7,misc:7,pars:11,prerequisit:10,prod:10,record:3,sport:4,statist:[5,7,8],tabl:9,troubleshoot:12,unexpect:11,upgrad:10,user:[6,13],version:7,workout:8}})
\ No newline at end of file
+Search.setIndex({docnames:["api/activities","api/auth","api/index","api/records","api/sports","api/stats","api/users","changelog","features","index","installation","troubleshooting/administrator","troubleshooting/index","troubleshooting/user"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,sphinx:56},filenames:["api/activities.rst","api/auth.rst","api/index.rst","api/records.rst","api/sports.rst","api/stats.rst","api/users.rst","changelog.md","features.rst","index.rst","installation.rst","troubleshooting/administrator.rst","troubleshooting/index.rst","troubleshooting/user.rst"],objects:{"":{"/api/activities":[0,1,1,"post--api-activities"],"/api/activities/(int:activity_id)":[0,3,1,"patch--api-activities-(int-activity_id)"],"/api/activities/(int:activity_id)/chart_data":[0,0,1,"get--api-activities-(int-activity_id)-chart_data"],"/api/activities/(int:activity_id)/chart_data/segment/(int:segment_id)":[0,0,1,"get--api-activities-(int-activity_id)-chart_data-segment-(int-segment_id)"],"/api/activities/(int:activity_id)/gpx":[0,0,1,"get--api-activities-(int-activity_id)-gpx"],"/api/activities/(int:activity_id)/gpx/segment/(int:segment_id)":[0,0,1,"get--api-activities-(int-activity_id)-gpx-segment-(int-segment_id)"],"/api/activities/map/(map_id)":[0,0,1,"get--api-activities-map-(map_id)"],"/api/activities/no_gpx":[0,1,1,"post--api-activities-no_gpx"],"/api/auth/login":[1,1,1,"post--api-auth-login"],"/api/auth/logout":[1,0,1,"get--api-auth-logout"],"/api/auth/picture":[1,1,1,"post--api-auth-picture"],"/api/auth/profile":[1,0,1,"get--api-auth-profile"],"/api/auth/profile/edit":[1,1,1,"post--api-auth-profile-edit"],"/api/auth/register":[1,1,1,"post--api-auth-register"],"/api/ping":[6,0,1,"get--api-ping"],"/api/records":[3,0,1,"get--api-records"],"/api/sports":[4,0,1,"get--api-sports"],"/api/sports/(int:sport_id)":[4,0,1,"get--api-sports-(int-sport_id)"],"/api/stats/(int:user_id)/by_sport":[5,0,1,"get--api-stats-(int-user_id)-by_sport"],"/api/stats/(int:user_id)/by_time":[5,0,1,"get--api-stats-(int-user_id)-by_time"],"/api/users":[6,0,1,"get--api-users"],"/api/users/(user_id)":[6,0,1,"get--api-users-(user_id)"],"/api/users/(user_id)/picture":[6,0,1,"get--api-users-(user_id)-picture"]}},objnames:{"0":["http","get","HTTP get"],"1":["http","post","HTTP post"],"2":["http","delete","HTTP delete"],"3":["http","patch","HTTP patch"]},objtypes:{"0":"http:get","1":"http:post","2":"http:delete","3":"http:patch"},terms:{"default":[0,5],"export":9,"float":0,"int":[0,4,5],"null":[0,1,6],"return":[0,3],"static":10,"true":6,"try":[0,1],NOT:[0,1,4],Not:[0,1,4,5,6],That:1,The:10,Use:7,_can_be_delet:4,accord:9,account:8,acit:0,activ:[2,5,7,9],activity_d:[0,3],activity_id:[0,3],adapt:10,add:[7,8,9],admin:[1,6,8,10],administr:[0,1,8,9,12],again:[0,1,3,4,5,6],all:[3,4,5,6,10],allow:[0,1,9],alpinequest:9,alreadi:1,also:[9,10],android:9,api:[0,1,3,4,5,6,8,9,10,11],app:9,applic:[0,1,3,4,5,6,9,10],arch:10,archiv:10,ascent:0,auth:[0,1,3,4,5,6],auth_token:1,auth_user_id:[0,3,4,5,6],authent:[0,2,3,4,5,6,9],author:[0,1,3,4,5,6],avail:3,ave_spe:0,ave_speed_from:0,ave_speed_to:0,averag:[0,3,8],backup:10,bad:[0,1],bearer:[0,1,3,4,5,6],befor:10,beta:10,bike:[0,4,8],bio:[1,6],biographi:1,birth:1,birth_dat:[1,6],bound:0,build:10,by_sport:5,by_tim:5,calcul:7,calendar:[7,8],can:[8,9,10],chang:[9,10],charact:[1,12],chart:[0,8,10],chart_data:0,check:[6,11],client:[10,11],clone:10,code:[0,1,3,4,5,6],column:12,com:[1,6,10],config:[10,11],confirm:1,contact:[0,1],content:[0,1,3,4,5,6],coordin:10,copi:10,correctli:[7,11],coverag:9,creat:[0,1,8],created_at:[1,6],creation:8,creation_d:0,credenti:1,current:7,custom:[10,11],cycl:[4,8],dark:10,darkski:8,dashboard:[7,9],data:[0,1,3,4,5,6,9,10,12],databas:10,date:[0,1,5,8],debian:10,delet:[0,1,8],depend:7,desc:0,descent:0,describ:10,detail:[6,7,9],develop:9,directori:10,disabl:[1,8,10],displai:[0,7,8,9,10],distanc:[0,3,7,8],distance_from:0,distance_to:0,document:9,doe:[0,5,6],don:1,download:10,durat:[0,3,7,8],duration_from:0,duration_to:0,dure:1,edit:[1,8],elev:[0,8,10],email:[1,6,10],encount:10,end:[0,5],endpoint:[2,6,12],enter:8,environn:11,error:[0,1,7],europ:[1,6],even:8,exampl:[0,1,3,4,5,6,9,10,11],exist:[0,1,5,6,9,11],exodu:9,expir:[0,1,3,4,5,6],extens:[0,1],fa33f4d996844a5c73ecd1ae24456ab8:0,fals:[0,1,4,6],farest:[3,8],featur:9,fetch:10,file:[0,1,7,8,9,10,11],filter:[7,8],first:1,first_nam:[1,6],fittracke:10,fittrackee_api:10,fix:9,flask:10,flaticon:10,follow:[3,10],forbidden:[0,1],forecast:10,form:[0,1],format:[0,1,5],former:10,forrunn:9,found:[0,1,4,5,6],frame:5,freepik:10,fri:0,from:[0,3,4,5,6,9,10],gener:10,get:[0,1,3,4,5,6],gif:1,git:10,github:10,gmt:[0,1,3,6],gpl:9,gpx:[0,7,8,9,10],gpxpy:10,have:0,header:[0,1,3,4,5,6],health:6,hike:[4,8],his:8,http:[0,1,3,4,5,6,10,11],icon:10,imag:[0,1,6,10],img:4,improv:9,incorrect:7,info:1,inform:9,initi:[10,11],instal:9,instanc:10,integ:[0,3,4,5,6],intern:[0,1],invalid:[0,1,3,4,5,6],issu:[9,10],jan:0,javascript:10,jpeg:6,jpg:1,json:[0,1,3,4,5,6,12],jul:[0,1,3,6],keep:9,kei:[8,10],label:4,last:[1,10],last_nam:[1,6],latitud:0,leaflet:[0,10],least:0,line:12,linux:10,list:9,local:9,localhost:[10,11],locat:[1,6],log:[0,1,3,4,5,6,9,10],login:[1,10],logout:1,longest:[3,8],longitud:0,made:[10,11],mai:10,make:10,makefil:[10,11],mandatori:[0,10],map:[0,8,9,10],map_id:0,match:1,max:0,max_alt:0,max_spe:0,max_speed_from:0,max_speed_to:0,maxim:0,maximum:[3,8],mean:11,messag:[0,1,6],min_alt:0,minim:[0,9],mobil:9,modification_d:0,mon:0,mondai:5,montain:8,month:[5,7,8],more:9,morn:0,mountain:4,move:[0,7],mpwoadmin:10,multipart:[0,1],must:[1,8],name:1,nb_activ:[1,5,6],nb_sport:[1,6],necessari:10,need:10,network:11,next_act:0,no_gpx:0,note:[0,7,8,9,10],now:[8,10],number:0,oauth:[0,1,3,4,5,6],object:[0,1],one:0,onli:[0,8,9],open:[9,10],order:0,other:10,out:1,outdoor:9,own:9,owner:8,packag:10,page:0,pagin:0,paramet:[0,1,3,4,5,6],pari:[1,6],pars:[10,12],part:[0,1],password:[1,10],password_conf:1,past:10,patch:0,paus:[0,7],payload:[0,1],per:0,per_pag:0,permiss:0,pg_dump:10,pictur:[1,6],ping:6,pleas:[0,1,3,4,5,6],png:[0,1,4],pong:6,possibl:9,post:[0,1],postgresql:10,prerequisit:9,previous_act:0,privai:9,product:[9,10],profil:1,proprietari:9,provid:[0,1,3,4,5,6,8],pull:10,python:[9,10],queri:[0,5],react:10,react_app_api_url:11,readi:[9,10],rebuild:11,rechart:[0,10],record:[0,2,7,8,9],record_typ:[0,3],redux:10,regist:[1,10],registr:[1,8,10],reinstal:10,relat:10,releas:[7,10],repo:10,report:9,repositori:10,request:[0,1,3,4,5,6,11],requir:1,respons:[0,1,3,4,5,6],restart:10,run:[4,8,10],runner:9,sam:[1,6],samr1:10,sat:6,search:7,second:0,see:[8,9,10,11],segment:[0,7],segment_id:0,select:[0,1],serv:10,server:[0,1,9,10],sever:9,signatur:[0,1,3,4,5,6],singl:6,sky:10,some:[0,7,10],sorri:1,sort:0,speed:[0,3,8,10],sport:[0,2,5,8,9,10],sport_id:[0,3,4,5],standard:8,start:[0,5,10],stat:[5,7],staticmap:10,statist:[2,9],statu:[0,1,3,4,5,6],step:10,still:9,stop:10,store:9,street:9,string:[0,1,5],success:[0,1,3,4,5,6],successfulli:1,sun:[0,1,3,6],sundai:[0,5],support:[7,8],system:10,tab:11,tar:10,test:[9,10],them:9,thi:[0,7,9,10],thunderforest:10,time:[0,1,5,8],timezon:[1,6,7],titl:0,todo:[10,13],token:[0,1,3,4,5,6],tooltip:7,total:7,total_dist:[1,5,6],total_dur:[1,5,6],track:9,tracker:9,transport:[4,8],troubleshoot:9,type:[0,1,3,4,5,6],unauthor:[0,1,3,4,5,6],undefin:11,under:9,unexpect:12,updat:[0,1,7,10],upgrad:9,upload:[7,8,10],user:[0,1,2,3,4,5,7,8,9,10,12],user_id:[0,3,5,6],usernam:[1,6],using:[0,9],valid:[0,1,3,4,5,6],valu:[0,3,10],variabl:11,version:9,view:7,virtualenv:10,walk:[4,8],weather:[7,8,10],weather_end:0,weather_start:0,web:[0,1,3,4,5,6,9],week:5,weekm:5,were:7,wget:10,when:7,with_gpx:0,without:[0,5,8,9],workout:9,written:10,www:10,xzf:10,yarn:10,year:5,yet:[9,10],you:[0,9],your:9,zip:0,zone:1},titles:["Activities","Authentication","API documentation","Records","Sports","Statistics","Users","Change log","Features","FitTrackee","Installation","Administrator","Troubleshooting","User"],titleterms:{"new":7,activ:[0,8],administr:11,api:2,authent:1,bug:7,chang:7,charact:11,close:7,column:11,content:9,dashboard:8,data:11,detail:8,dev:10,document:2,environ:10,featur:[7,8],fittracke:9,fix:7,improv:7,instal:10,issu:7,json:11,line:11,list:8,log:7,minim:7,misc:7,pars:11,prerequisit:10,prod:10,record:3,sport:4,statist:[5,7,8],tabl:9,troubleshoot:12,unexpect:11,upgrad:10,user:[6,13],version:7,workout:8}})
\ No newline at end of file
diff --git a/docsrc/source/api/activities.rst b/docsrc/source/api/activities.rst
index 51b82b2b..14853645 100644
--- a/docsrc/source/api/activities.rst
+++ b/docsrc/source/api/activities.rst
@@ -11,4 +11,6 @@ Activities
activities.delete_activity,
activities.get_map,
activities.get_activity_gpx,
- activities.get_activity_chart_data
+ activities.get_activity_chart_data,
+ activities.get_segment_gpx,
+ activities.get_segment_chart_data
diff --git a/fittrackee_api/fittrackee_api/activities/activities.py b/fittrackee_api/fittrackee_api/activities/activities.py
index af72fa41..9272f54e 100644
--- a/fittrackee_api/fittrackee_api/activities/activities.py
+++ b/fittrackee_api/fittrackee_api/activities/activities.py
@@ -16,7 +16,9 @@ from .utils import (
get_datetime_with_tz, process_files
)
from .utils_format import convert_in_duration
-from .utils_gpx import get_chart_data
+from .utils_gpx import (
+ ActivityGPXException, extract_segment_from_gpx_file, get_chart_data
+)
activities_blueprint = Blueprint('activities', __name__)
@@ -345,7 +347,7 @@ def get_activity(auth_user_id, activity_id):
return jsonify(response_object), code
-def get_activity_data(auth_user_id, activity_id, data_type):
+def get_activity_data(auth_user_id, activity_id, data_type, segment_id=None):
"""Get data from an activity gpx file"""
activity = Activity.query.filter_by(id=activity_id).first()
content = ''
@@ -364,10 +366,21 @@ def get_activity_data(auth_user_id, activity_id, data_type):
try:
absolute_gpx_filepath = get_absolute_file_path(activity.gpx)
if data_type == 'chart':
- content = get_chart_data(absolute_gpx_filepath)
+ content = get_chart_data(absolute_gpx_filepath, segment_id)
else: # data_type == 'gpx'
with open(absolute_gpx_filepath, encoding='utf-8') as f:
content = f.read()
+ if segment_id is not None:
+ content = extract_segment_from_gpx_file(
+ content,
+ segment_id
+ )
+ except ActivityGPXException as e:
+ appLog.error(e.message)
+ response_object = {'status': e.status,
+ 'message': e.message}
+ code = 404 if e.status == 'not found' else 500
+ return jsonify(response_object), code
except Exception as e:
appLog.error(e)
response_object = {'status': 'error',
@@ -505,6 +518,125 @@ def get_activity_chart_data(auth_user_id, activity_id):
return get_activity_data(auth_user_id, activity_id, 'chart')
+@activities_blueprint.route(
+ '/activities//gpx/segment/',
+ methods=['GET']
+)
+@authenticate
+def get_segment_gpx(auth_user_id, activity_id, segment_id):
+ """
+ Get gpx file for an activity segment displayed on map with Leaflet
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ GET /api/activities/3/gpx/segment/0 HTTP/1.1
+ Content-Type: application/json
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/json
+
+ {
+ "data": {
+ "gpx": "gpx file content"
+ },
+ "message": "",
+ "status": "success"
+ }
+
+ :param integer auth_user_id: authenticate user id (from JSON Web Token)
+ :param integer activity_id: activity id
+ :param integer segment_id: segment id
+
+ :reqheader Authorization: OAuth 2.0 Bearer Token
+
+ :statuscode 200: success
+ :statuscode 400: no gpx file for this activity
+ :statuscode 401:
+ - Provide a valid auth token.
+ - Signature expired. Please log in again.
+ - Invalid token. Please log in again.
+ :statuscode 404: activity not found
+ :statuscode 500:
+
+ """
+ return get_activity_data(auth_user_id, activity_id, 'gpx', segment_id)
+
+
+@activities_blueprint.route(
+ '/activities//chart_data/segment/',
+ methods=['GET']
+)
+@authenticate
+def get_segment_chart_data(auth_user_id, activity_id, segment_id):
+ """
+ Get chart data from an activity gpx file, to display it with Recharts
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ GET /api/activities/3/chart/segment/0 HTTP/1.1
+ Content-Type: application/json
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/json
+
+ {
+ "data": {
+ "chart_data": [
+ {
+ "distance": 0,
+ "duration": 0,
+ "elevation": 279.4,
+ "latitude": 51.5078118,
+ "longitude": -0.1232004,
+ "speed": 8.63,
+ "time": "Fri, 14 Jul 2017 13:44:03 GMT"
+ },
+ {
+ "distance": 7.5,
+ "duration": 7380,
+ "elevation": 280,
+ "latitude": 51.5079733,
+ "longitude": -0.1234538,
+ "speed": 6.39,
+ "time": "Fri, 14 Jul 2017 15:47:03 GMT"
+ }
+ ]
+ },
+ "message": "",
+ "status": "success"
+ }
+
+ :param integer auth_user_id: authenticate user id (from JSON Web Token)
+ :param integer activity_id: activity id
+ :param integer segment_id: segment id
+
+ :reqheader Authorization: OAuth 2.0 Bearer Token
+
+ :statuscode 200: success
+ :statuscode 400: no gpx file for this activity
+ :statuscode 401:
+ - Provide a valid auth token.
+ - Signature expired. Please log in again.
+ - Invalid token. Please log in again.
+ :statuscode 404: activity not found
+ :statuscode 500:
+
+ """
+ return get_activity_data(auth_user_id, activity_id, 'chart', segment_id)
+
+
@activities_blueprint.route('/activities/map/', methods=['GET'])
def get_map(map_id):
"""
diff --git a/fittrackee_api/fittrackee_api/activities/utils_gpx.py b/fittrackee_api/fittrackee_api/activities/utils_gpx.py
index 9c67b7f6..d8c2f8b9 100644
--- a/fittrackee_api/fittrackee_api/activities/utils_gpx.py
+++ b/fittrackee_api/fittrackee_api/activities/utils_gpx.py
@@ -121,7 +121,22 @@ def get_gpx_info(gpx_file, update_map_data=True, update_weather_data=True):
return gpx_data, map_data, weather_data
-def get_chart_data(gpx_file):
+def get_gpx_segments(track_segments, segment_id=None):
+ if segment_id is not None:
+ if segment_id > (len(track_segments) - 1):
+ raise ActivityGPXException(
+ 'not found',
+ f'No segment with id \'{segment_id}\'',
+ None
+ )
+ segments = [track_segments[segment_id]]
+ else:
+ segments = track_segments
+
+ return segments
+
+
+def get_chart_data(gpx_file, segment_id=None):
gpx = open_gpx_file(gpx_file)
if gpx is None:
return None
@@ -131,7 +146,10 @@ def get_chart_data(gpx_file):
previous_point = None
previous_distance = 0
- for segment_idx, segment in enumerate(gpx.tracks[0].segments):
+ track_segments = gpx.tracks[0].segments
+ segments = get_gpx_segments(track_segments, segment_id)
+
+ for segment_idx, segment in enumerate(segments):
for point_idx, point in enumerate(segment.points):
if segment_idx == 0 and point_idx == 0:
first_point = point
@@ -161,3 +179,29 @@ def get_chart_data(gpx_file):
previous_distance = distance
return chart_data
+
+
+def extract_segment_from_gpx_file(content, segment_id):
+ gpx_content = gpxpy.parse(content)
+ if len(gpx_content.tracks) == 0:
+ return None
+
+ track_segment = get_gpx_segments(
+ gpx_content.tracks[0].segments,
+ segment_id
+ )
+
+ gpx = gpxpy.gpx.GPX()
+ gpx_track = gpxpy.gpx.GPXTrack()
+ gpx.tracks.append(gpx_track)
+ gpx_segment = gpxpy.gpx.GPXTrackSegment()
+ gpx_track.segments.append(gpx_segment)
+
+ for point_idx, point in enumerate(track_segment[0].points):
+ gpx_segment.points.append(
+ gpxpy.gpx.GPXTrackPoint(
+ point.latitude,
+ point.longitude,
+ elevation=point.elevation))
+
+ return gpx.to_xml()
diff --git a/fittrackee_api/fittrackee_api/tests/test_activities_api_1_post.py b/fittrackee_api/fittrackee_api/tests/test_activities_api_1_post.py
index 1e184029..d6652422 100644
--- a/fittrackee_api/fittrackee_api/tests/test_activities_api_1_post.py
+++ b/fittrackee_api/fittrackee_api/tests/test_activities_api_1_post.py
@@ -274,6 +274,21 @@ def activity_assertion(app, user_1, sport_1_cycling, gpx_file, with_segments):
assert '' in data['message']
assert len(data['data']['gpx']) != ''
+ response = client.get(
+ '/api/activities/1/gpx/segment/0',
+ headers=dict(
+ Authorization='Bearer ' + json.loads(
+ resp_login.data.decode()
+ )['auth_token']
+ )
+ )
+ data = json.loads(response.data.decode())
+
+ assert response.status_code == 200
+ assert 'success' in data['status']
+ assert '' in data['message']
+ assert len(data['data']['gpx']) != ''
+
response = client.get(
f'/api/activities/map/{map_id}',
headers=dict(
@@ -419,6 +434,36 @@ def test_get_chart_data_activty_with_gpx(
assert data['message'] == ''
assert data['data']['chart_data'] != ''
+ response = client.get(
+ '/api/activities/1/chart_data/segment/0',
+ headers=dict(
+ Authorization='Bearer ' + json.loads(
+ resp_login.data.decode()
+ )['auth_token']
+ )
+ )
+ data = json.loads(response.data.decode())
+
+ assert response.status_code == 200
+ assert 'success' in data['status']
+ assert data['message'] == ''
+ assert data['data']['chart_data'] != ''
+
+ response = client.get(
+ '/api/activities/1/chart_data/segment/999999',
+ headers=dict(
+ Authorization='Bearer ' + json.loads(
+ resp_login.data.decode()
+ )['auth_token']
+ )
+ )
+ data = json.loads(response.data.decode())
+
+ assert response.status_code == 404
+ assert 'not found' in data['status']
+ assert data['message'] == 'No segment with id \'999999\''
+ assert 'data' not in data
+
def test_get_chart_data_activty_with_gpx_different_user(
app, user_1, user_2, sport_1_cycling, gpx_file
@@ -467,6 +512,34 @@ def test_get_chart_data_activty_with_gpx_different_user(
assert 'error' in data['status']
assert 'You do not have permissions.' in data['message']
+ response = client.get(
+ '/api/activities/1/chart_data/segment/0',
+ headers=dict(
+ Authorization='Bearer ' + json.loads(
+ resp_login.data.decode()
+ )['auth_token']
+ )
+ )
+ data = json.loads(response.data.decode())
+
+ assert response.status_code == 403
+ assert 'error' in data['status']
+ assert 'You do not have permissions.' in data['message']
+
+ response = client.get(
+ '/api/activities/1/chart_data/segment/999999',
+ headers=dict(
+ Authorization='Bearer ' + json.loads(
+ resp_login.data.decode()
+ )['auth_token']
+ )
+ )
+ data = json.loads(response.data.decode())
+
+ assert response.status_code == 403
+ assert 'error' in data['status']
+ assert 'You do not have permissions.' in data['message']
+
def test_add_an_activity_with_gpx_without_name(
app, user_1, sport_1_cycling, gpx_file_wo_name
|