Merge pull request #211 from SamR1/fix-staticmap-generation
Fix staticmap generation
This commit is contained in:
commit
6a84902656
@ -25,6 +25,7 @@ export SENDER_EMAIL=
|
||||
|
||||
# Workouts
|
||||
# export TILE_SERVER_URL=
|
||||
# export STATICMAP_SUBDOMAINS=
|
||||
# export MAP_ATTRIBUTION=
|
||||
# export DEFAULT_STATICMAP=False
|
||||
# export WEATHER_API_KEY=
|
||||
|
@ -175,6 +175,16 @@ deployment method.
|
||||
:default: `https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png`
|
||||
|
||||
|
||||
.. envvar:: STATICMAP_SUBDOMAINS 🆕
|
||||
|
||||
.. versionadded:: 0.6.10
|
||||
|
||||
| Some tile servers require a subdomain, see `Map tile server <installation.html#map-tile-server>`__.
|
||||
| For instance: "a,b,c" for OSM France.
|
||||
|
||||
:default: empty string
|
||||
|
||||
|
||||
.. envvar:: MAP_ATTRIBUTION
|
||||
|
||||
.. versionadded:: 0.4.0
|
||||
@ -184,11 +194,17 @@ deployment method.
|
||||
:default: `© <a href="http://www.openstreetmap.org/copyright" target="_blank" rel="noopener noreferrer">OpenStreetMap</a> contributors`
|
||||
|
||||
|
||||
.. envvar:: DEFAULT_STATICMAP 🆕
|
||||
.. envvar:: DEFAULT_STATICMAP
|
||||
|
||||
.. versionadded:: 0.4.9
|
||||
|
||||
If `True`, it keeps using default tile server to generate static maps.
|
||||
| If `True`, it keeps using default tile server to generate static maps (Komoot.de tile server).
|
||||
| Otherwise, it uses the tile server set in `TILE_SERVER_URL <installation.html#envvar-TILE_SERVER_URL>`__.
|
||||
|
||||
.. versionchanged:: 0.6.10
|
||||
|
||||
| This variable is now case-insensitive.
|
||||
| If `False`, depending on tile server, `subdomains <installation.html#envvar-STATICMAP_SUBDOMAINS>`__ may be mandatory.
|
||||
|
||||
:default: False
|
||||
|
||||
@ -256,6 +272,20 @@ To keep using **ThunderForest Outdoors**, the configuration is:
|
||||
.. note::
|
||||
| Check the terms of service of tile provider for map attribution
|
||||
|
||||
|
||||
.. versionchanged:: 0.6.10
|
||||
|
||||
Since the tile server can be used for static map generation, some servers require a subdomain.
|
||||
|
||||
For instance, to set OSM France tile server, the expected values are:
|
||||
|
||||
- ``TILE_SERVER_URL=https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png``
|
||||
- ``MAP_ATTRIBUTION=fond de carte par <a href="http://www.openstreetmap.fr/mentions-legales/" target="_blank" rel="nofollow noopener">OpenStreetMap France</a>, sous <a href="http://creativecommons.org/licenses/by-sa/2.0/fr/" target="_blank" rel="nofollow noopener">licence CC BY-SA</a>``
|
||||
- ``STATICMAP_SUBDOMAINS=a,b,c``
|
||||
|
||||
The subdomain will be chosen randomly.
|
||||
|
||||
|
||||
Installation
|
||||
~~~~~~~~~~~~
|
||||
|
||||
|
@ -135,7 +135,7 @@
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-DATABASE_URL">DATABASE_URL</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-DEFAULT_STATICMAP">DEFAULT_STATICMAP 🆕</a>
|
||||
<li><a href="installation.html#envvar-DEFAULT_STATICMAP">DEFAULT_STATICMAP</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-EMAIL_URL">EMAIL_URL</a>
|
||||
</li>
|
||||
@ -150,6 +150,8 @@
|
||||
<li><a href="installation.html#envvar-REDIS_URL">REDIS_URL</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-SENDER_EMAIL">SENDER_EMAIL</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-STATICMAP_SUBDOMAINS">STATICMAP_SUBDOMAINS 🆕</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-TILE_SERVER_URL">TILE_SERVER_URL</a>
|
||||
</li>
|
||||
|
@ -420,6 +420,23 @@ see <a class="reference external" href="https://docs.sqlalchemy.org/en/13/core/p
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt class="sig sig-object std" id="envvar-STATICMAP_SUBDOMAINS">
|
||||
<span class="sig-name descname"><span class="pre">STATICMAP_SUBDOMAINS</span> <span class="pre">🆕</span></span><a class="headerlink" href="#envvar-STATICMAP_SUBDOMAINS" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 0.6.10.</span></p>
|
||||
</div>
|
||||
<div class="line-block">
|
||||
<div class="line">Some tile servers require a subdomain, see <a class="reference external" href="installation.html#map-tile-server">Map tile server</a>.</div>
|
||||
<div class="line">For instance: “a,b,c” for OSM France.</div>
|
||||
</div>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Default<span class="colon">:</span></dt>
|
||||
<dd class="field-odd"><p>empty string</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt class="sig sig-object std" id="envvar-MAP_ATTRIBUTION">
|
||||
<span class="sig-name descname"><span class="pre">MAP_ATTRIBUTION</span></span><a class="headerlink" href="#envvar-MAP_ATTRIBUTION" title="Permalink to this definition">¶</a></dt>
|
||||
@ -436,11 +453,21 @@ see <a class="reference external" href="https://docs.sqlalchemy.org/en/13/core/p
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt class="sig sig-object std" id="envvar-DEFAULT_STATICMAP">
|
||||
<span class="sig-name descname"><span class="pre">DEFAULT_STATICMAP</span> <span class="pre">🆕</span></span><a class="headerlink" href="#envvar-DEFAULT_STATICMAP" title="Permalink to this definition">¶</a></dt>
|
||||
<span class="sig-name descname"><span class="pre">DEFAULT_STATICMAP</span></span><a class="headerlink" href="#envvar-DEFAULT_STATICMAP" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 0.4.9.</span></p>
|
||||
</div>
|
||||
<p>If <cite>True</cite>, it keeps using default tile server to generate static maps.</p>
|
||||
<div class="line-block">
|
||||
<div class="line">If <cite>True</cite>, it keeps using default tile server to generate static maps (Komoot.de tile server).</div>
|
||||
<div class="line">Otherwise, it uses the tile server set in <a class="reference external" href="installation.html#envvar-TILE_SERVER_URL">TILE_SERVER_URL</a>.</div>
|
||||
</div>
|
||||
<div class="versionchanged">
|
||||
<p><span class="versionmodified changed">Changed in version 0.6.10.</span></p>
|
||||
</div>
|
||||
<div class="line-block">
|
||||
<div class="line">This variable is now case-insensitive.</div>
|
||||
<div class="line">If <cite>False</cite>, depending on tile server, <a class="reference external" href="installation.html#envvar-STATICMAP_SUBDOMAINS">subdomains</a> may be mandatory.</div>
|
||||
</div>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Default<span class="colon">:</span></dt>
|
||||
<dd class="field-odd"><p>False</p>
|
||||
@ -527,6 +554,17 @@ The tile server can be changed by updating <code class="docutils literal notrans
|
||||
<div class="line">Check the terms of service of tile provider for map attribution</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="versionchanged">
|
||||
<p><span class="versionmodified changed">Changed in version 0.6.10.</span></p>
|
||||
</div>
|
||||
<p>Since the tile server can be used for static map generation, some servers require a subdomain.</p>
|
||||
<p>For instance, to set OSM France tile server, the expected values are:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">TILE_SERVER_URL=https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">MAP_ATTRIBUTION=fond</span> <span class="pre">de</span> <span class="pre">carte</span> <span class="pre">par</span> <span class="pre"><a</span> <span class="pre">href="http://www.openstreetmap.fr/mentions-legales/"</span> <span class="pre">target="_blank"</span> <span class="pre">rel="nofollow</span> <span class="pre">noopener">OpenStreetMap</span> <span class="pre">France</a>,</span> <span class="pre">sous&nbsp;<a</span> <span class="pre">href="http://creativecommons.org/licenses/by-sa/2.0/fr/"</span> <span class="pre">target="_blank"</span> <span class="pre">rel="nofollow</span> <span class="pre">noopener">licence</span> <span class="pre">CC</span> <span class="pre">BY-SA</a></span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">STATICMAP_SUBDOMAINS=a,b,c</span></code></p></li>
|
||||
</ul>
|
||||
<p>The subdomain will be chosen randomly.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="id1">
|
||||
|
BIN
docs/objects.inv
BIN
docs/objects.inv
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -175,6 +175,16 @@ deployment method.
|
||||
:default: `https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png`
|
||||
|
||||
|
||||
.. envvar:: STATICMAP_SUBDOMAINS 🆕
|
||||
|
||||
.. versionadded:: 0.6.10
|
||||
|
||||
| Some tile servers require a subdomain, see `Map tile server <installation.html#map-tile-server>`__.
|
||||
| For instance: "a,b,c" for OSM France.
|
||||
|
||||
:default: empty string
|
||||
|
||||
|
||||
.. envvar:: MAP_ATTRIBUTION
|
||||
|
||||
.. versionadded:: 0.4.0
|
||||
@ -184,11 +194,17 @@ deployment method.
|
||||
:default: `© <a href="http://www.openstreetmap.org/copyright" target="_blank" rel="noopener noreferrer">OpenStreetMap</a> contributors`
|
||||
|
||||
|
||||
.. envvar:: DEFAULT_STATICMAP 🆕
|
||||
.. envvar:: DEFAULT_STATICMAP
|
||||
|
||||
.. versionadded:: 0.4.9
|
||||
|
||||
If `True`, it keeps using default tile server to generate static maps.
|
||||
| If `True`, it keeps using default tile server to generate static maps (Komoot.de tile server).
|
||||
| Otherwise, it uses the tile server set in `TILE_SERVER_URL <installation.html#envvar-TILE_SERVER_URL>`__.
|
||||
|
||||
.. versionchanged:: 0.6.10
|
||||
|
||||
| This variable is now case-insensitive.
|
||||
| If `False`, depending on tile server, `subdomains <installation.html#envvar-STATICMAP_SUBDOMAINS>`__ may be mandatory.
|
||||
|
||||
:default: False
|
||||
|
||||
@ -256,6 +272,20 @@ To keep using **ThunderForest Outdoors**, the configuration is:
|
||||
.. note::
|
||||
| Check the terms of service of tile provider for map attribution
|
||||
|
||||
|
||||
.. versionchanged:: 0.6.10
|
||||
|
||||
Since the tile server can be used for static map generation, some servers require a subdomain.
|
||||
|
||||
For instance, to set OSM France tile server, the expected values are:
|
||||
|
||||
- ``TILE_SERVER_URL=https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png``
|
||||
- ``MAP_ATTRIBUTION=fond de carte par <a href="http://www.openstreetmap.fr/mentions-legales/" target="_blank" rel="nofollow noopener">OpenStreetMap France</a>, sous <a href="http://creativecommons.org/licenses/by-sa/2.0/fr/" target="_blank" rel="nofollow noopener">licence CC BY-SA</a>``
|
||||
- ``STATICMAP_SUBDOMAINS=a,b,c``
|
||||
|
||||
The subdomain will be chosen randomly.
|
||||
|
||||
|
||||
Installation
|
||||
~~~~~~~~~~~~
|
||||
|
||||
|
@ -43,8 +43,9 @@ class BaseConfig:
|
||||
' contributors',
|
||||
),
|
||||
'DEFAULT_STATICMAP': (
|
||||
os.environ.get('DEFAULT_STATICMAP', 'False') == 'True'
|
||||
os.environ.get('DEFAULT_STATICMAP', 'false').lower() == 'true'
|
||||
),
|
||||
'STATICMAP_SUBDOMAINS': os.environ.get('STATICMAP_SUBDOMAINS', ''),
|
||||
}
|
||||
TRANSLATIONS_FOLDER = os.path.join(
|
||||
current_app.root_path, 'emails/translations'
|
||||
|
2
fittrackee/dist/index.html
vendored
2
fittrackee/dist/index.html
vendored
@ -1 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="/favicon.ico"><![endif]--><link rel="stylesheet" href="/static/css/fork-awesome.min.css"/><link rel="stylesheet" href="/static/css/leaflet.css"/><title>FitTrackee</title><script defer="defer" src="/static/js/chunk-vendors.7123d468.js"></script><script defer="defer" src="/static/js/app.51b2bdb0.js"></script><link href="/static/css/app.32d0ced1.css" rel="stylesheet"><link rel="icon" type="image/png" sizes="32x32" href="/img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/img/icons/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><meta name="theme-color" content="#4DBA87"><meta name="apple-mobile-web-app-capable" content="no"><meta name="apple-mobile-web-app-status-bar-style" content="default"><meta name="apple-mobile-web-app-title" content="fittrackee_client"><link rel="apple-touch-icon" href="/img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color="#4DBA87"><meta name="msapplication-TileImage" content="/img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#000000"></head><body><noscript><strong>We're sorry but FitTrackee doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="/favicon.ico"><![endif]--><link rel="stylesheet" href="/static/css/fork-awesome.min.css"/><link rel="stylesheet" href="/static/css/leaflet.css"/><title>FitTrackee</title><script defer="defer" src="/static/js/chunk-vendors.7123d468.js"></script><script defer="defer" src="/static/js/app.685ff4cc.js"></script><link href="/static/css/app.32d0ced1.css" rel="stylesheet"><link rel="icon" type="image/png" sizes="32x32" href="/img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/img/icons/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><meta name="theme-color" content="#4DBA87"><meta name="apple-mobile-web-app-capable" content="no"><meta name="apple-mobile-web-app-status-bar-style" content="default"><meta name="apple-mobile-web-app-title" content="fittrackee_client"><link rel="apple-touch-icon" href="/img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color="#4DBA87"><meta name="msapplication-TileImage" content="/img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#000000"></head><body><noscript><strong>We're sorry but FitTrackee doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
2
fittrackee/dist/service-worker.js
vendored
2
fittrackee/dist/service-worker.js
vendored
File diff suppressed because one or more lines are too long
2
fittrackee/dist/service-worker.js.map
vendored
2
fittrackee/dist/service-worker.js.map
vendored
File diff suppressed because one or more lines are too long
2
fittrackee/dist/static/js/app.51b2bdb0.js
vendored
2
fittrackee/dist/static/js/app.51b2bdb0.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
fittrackee/dist/static/js/app.685ff4cc.js
vendored
Normal file
2
fittrackee/dist/static/js/app.685ff4cc.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/js/app.685ff4cc.js.map
vendored
Normal file
1
fittrackee/dist/static/js/app.685ff4cc.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,2 +1,2 @@
|
||||
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[193],{9161:function(e,s,t){t.r(s),t.d(s,{default:function(){return A}});t(6699);var a=t(6252),r=t(2262),l=t(3577),o=t(3324),n=t(9996);const c={class:"chart-menu"},i={class:"chart-arrow"},u={class:"time-frames custom-checkboxes-group"},d={class:"time-frames-checkboxes custom-checkboxes"},p=["id","name","checked","onInput"],m={class:"chart-arrow"};var v=(0,a.aZ)({__name:"StatsMenu",emits:["arrowClick","timeFrameUpdate"],setup(e,{emit:s}){const t=(0,r.iH)("month"),o=["week","month","year"];function n(e){t.value=e,s("timeFrameUpdate",e)}return(e,r)=>((0,a.wg)(),(0,a.iD)("div",c,[(0,a._)("div",i,[(0,a._)("i",{class:"fa fa-chevron-left","aria-hidden":"true",onClick:r[0]||(r[0]=e=>s("arrowClick",!0))})]),(0,a._)("div",u,[(0,a._)("div",d,[((0,a.wg)(),(0,a.iD)(a.HY,null,(0,a.Ko)(o,(s=>(0,a._)("div",{class:"time-frame custom-checkbox",key:s},[(0,a._)("label",null,[(0,a._)("input",{type:"radio",id:s,name:s,checked:t.value===s,onInput:e=>n(s)},null,40,p),(0,a._)("span",null,(0,l.zw)(e.$t(`statistics.TIME_FRAMES.${s}`)),1)])]))),64))])]),(0,a._)("div",m,[(0,a._)("i",{class:"fa fa-chevron-right","aria-hidden":"true",onClick:r[1]||(r[1]=e=>s("arrowClick",!1))})])]))}}),k=t(3744);const _=(0,k.Z)(v,[["__scopeId","data-v-22d55de2"]]);var S=_,w=t(631);const f={class:"sports-menu"},h=["id","name","checked","onInput"],U={class:"sport-label"};var b=(0,a.aZ)({__name:"StatsSportsMenu",props:{userSports:null,selectedSportIds:{default:()=>[]}},emits:["selectedSportIdsUpdate"],setup(e,{emit:s}){const t=e,{t:n}=(0,o.QT)(),c=(0,a.f3)("sportColors"),{selectedSportIds:i}=(0,r.BK)(t),u=(0,a.Fl)((()=>(0,w.xH)(t.userSports,n)));function d(e){s("selectedSportIdsUpdate",e)}return(e,s)=>{const t=(0,a.up)("SportImage");return(0,a.wg)(),(0,a.iD)("div",f,[((0,a.wg)(!0),(0,a.iD)(a.HY,null,(0,a.Ko)((0,r.SU)(u),(e=>((0,a.wg)(),(0,a.iD)("label",{type:"checkbox",key:e.id,style:(0,l.j5)({color:e.color?e.color:(0,r.SU)(c)[e.label]})},[(0,a._)("input",{type:"checkbox",id:e.id,name:e.label,checked:(0,r.SU)(i).includes(e.id),onInput:s=>d(e.id)},null,40,h),(0,a.Wm)(t,{"sport-label":e.label,color:e.color},null,8,["sport-label","color"]),(0,a._)("span",U,(0,l.zw)(e.translatedLabel),1)],4)))),128))])}}});const I=b;var g=I,T=t(9318);const y={key:0,id:"user-statistics"};var C=(0,a.aZ)({__name:"index",props:{sports:null,user:null},setup(e){const s=e,{t:t}=(0,o.QT)(),{sports:l,user:c}=(0,r.BK)(s),i=(0,r.iH)("month"),u=(0,r.iH)(v(i.value)),d=(0,a.Fl)((()=>(0,w.xH)(s.sports,t))),p=(0,r.iH)(_(s.sports));function m(e){i.value=e,u.value=v(i.value)}function v(e){return(0,T.aZ)(new Date,e,s.user.weekm)}function k(e){u.value=(0,T.FN)(u.value,e,s.user.weekm)}function _(e){return e.map((e=>e.id))}function f(e){p.value.includes(e)?p.value=p.value.filter((s=>s!==e)):p.value.push(e)}return(0,a.YP)((()=>s.sports),(e=>{p.value=_(e)})),(e,s)=>(0,r.SU)(d)?((0,a.wg)(),(0,a.iD)("div",y,[(0,a.Wm)(S,{onTimeFrameUpdate:m,onArrowClick:k}),(0,a.Wm)(n.Z,{sports:(0,r.SU)(l),user:(0,r.SU)(c),chartParams:u.value,"displayed-sport-ids":p.value,fullStats:!0},null,8,["sports","user","chartParams","displayed-sport-ids"]),(0,a.Wm)(g,{"selected-sport-ids":p.value,"user-sports":(0,r.SU)(l),onSelectedSportIdsUpdate:f},null,8,["selected-sport-ids","user-sports"])])):(0,a.kq)("",!0)}});const F=(0,k.Z)(C,[["__scopeId","data-v-d693c7da"]]);var Z=F,x=t(5630),D=t(8602),H=t(9917);const E={id:"statistics",class:"view"},R={key:0,class:"container"};var W=(0,a.aZ)({__name:"StatisticsView",setup(e){const s=(0,H.o)(),t=(0,a.Fl)((()=>s.getters[D.YN.GETTERS.AUTH_USER_PROFILE])),o=(0,a.Fl)((()=>s.getters[D.O8.GETTERS.SPORTS].filter((e=>t.value.sports_list.includes(e.id)))));return(e,s)=>{const n=(0,a.up)("Card");return(0,a.wg)(),(0,a.iD)("div",E,[(0,r.SU)(t).username?((0,a.wg)(),(0,a.iD)("div",R,[(0,a.Wm)(n,null,{title:(0,a.w5)((()=>[(0,a.Uk)((0,l.zw)(e.$t("statistics.STATISTICS")),1)])),content:(0,a.w5)((()=>[(0,a.Wm)(Z,{class:(0,l.C_)({"stats-disabled":0===(0,r.SU)(t).nb_workouts}),user:(0,r.SU)(t),sports:(0,r.SU)(o)},null,8,["class","user","sports"])])),_:1}),0===(0,r.SU)(t).nb_workouts?((0,a.wg)(),(0,a.j4)(x.Z,{key:0})):(0,a.kq)("",!0)])):(0,a.kq)("",!0)])}}});const P=(0,k.Z)(W,[["__scopeId","data-v-2e341d4e"]]);var A=P}}]);
|
||||
//# sourceMappingURL=statistics.145d19e3.js.map
|
||||
//# sourceMappingURL=statistics.c817d0d3.js.map
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
fittrackee/tests/fixtures/fixtures_app.py
vendored
2
fittrackee/tests/fixtures/fixtures_app.py
vendored
@ -81,6 +81,8 @@ def app(monkeypatch: pytest.MonkeyPatch) -> Generator:
|
||||
monkeypatch.setenv('WEATHER_API_KEY', '')
|
||||
if os.getenv('TILE_SERVER_URL'):
|
||||
monkeypatch.delenv('TILE_SERVER_URL')
|
||||
if os.getenv('STATICMAP_SUBDOMAINS'):
|
||||
monkeypatch.delenv('STATICMAP_SUBDOMAINS')
|
||||
if os.getenv('MAP_ATTRIBUTION'):
|
||||
monkeypatch.delenv('MAP_ATTRIBUTION')
|
||||
if os.getenv('DEFAULT_STATICMAP'):
|
||||
|
@ -1,5 +1,5 @@
|
||||
import json
|
||||
from typing import Any, Dict, Optional, Tuple
|
||||
from typing import Dict, Optional, Tuple
|
||||
|
||||
from flask import Flask
|
||||
from flask.testing import FlaskClient
|
||||
@ -115,10 +115,20 @@ class ApiTestCaseMixin(RandomMixin):
|
||||
|
||||
|
||||
class CallArgsMixin:
|
||||
"""call args are returned differently between Python 3.7 and 3.7+"""
|
||||
|
||||
@staticmethod
|
||||
def get_args(call_args: Any) -> Any:
|
||||
def get_args(call_args: Tuple) -> Tuple:
|
||||
if len(call_args) == 2:
|
||||
args, _ = call_args
|
||||
else:
|
||||
_, args, _ = call_args
|
||||
return args
|
||||
|
||||
@staticmethod
|
||||
def get_kwargs(call_args: Tuple) -> Dict:
|
||||
if len(call_args) == 2:
|
||||
_, kwargs = call_args
|
||||
else:
|
||||
_, _, kwargs = call_args
|
||||
return kwargs
|
||||
|
63
fittrackee/tests/workouts/test_utils/test_maps.py
Normal file
63
fittrackee/tests/workouts/test_utils/test_maps.py
Normal file
@ -0,0 +1,63 @@
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from fittrackee.workouts.utils.maps import get_static_map_tile_server_url
|
||||
|
||||
|
||||
class TestGetStaticMapTileServerUrl:
|
||||
@pytest.mark.parametrize(
|
||||
'input_tile_server_url,'
|
||||
'input_tile_server_subdomains,'
|
||||
'expected_tile_server_url',
|
||||
[
|
||||
(
|
||||
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
'',
|
||||
'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
),
|
||||
(
|
||||
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
'a',
|
||||
'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
),
|
||||
(
|
||||
'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
'',
|
||||
'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
),
|
||||
(
|
||||
'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
'a',
|
||||
'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_it_returns_tile_server_url(
|
||||
self,
|
||||
input_tile_server_url: str,
|
||||
input_tile_server_subdomains: str,
|
||||
expected_tile_server_url: str,
|
||||
) -> None:
|
||||
tile_config = {
|
||||
'URL': input_tile_server_url,
|
||||
'STATICMAP_SUBDOMAINS': input_tile_server_subdomains,
|
||||
}
|
||||
|
||||
assert (
|
||||
get_static_map_tile_server_url(tile_config)
|
||||
== expected_tile_server_url
|
||||
)
|
||||
|
||||
def test_it_returns_tile_server_url_with_random_subdomain(self) -> None:
|
||||
"""in case multiple subdomains are provided"""
|
||||
tile_config = {
|
||||
'URL': 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
'STATICMAP_SUBDOMAINS': 'a,b,c',
|
||||
}
|
||||
|
||||
with patch('random.choice', return_value='b'):
|
||||
assert (
|
||||
get_static_map_tile_server_url(tile_config)
|
||||
== 'https://b.tile.openstreetmap.org/{z}/{x}/{y}.png'
|
||||
)
|
@ -9,6 +9,7 @@ from unittest.mock import Mock
|
||||
import pytest
|
||||
from flask import Flask
|
||||
|
||||
from fittrackee import VERSION
|
||||
from fittrackee.users.models import User
|
||||
from fittrackee.workouts.models import Sport, Workout
|
||||
|
||||
@ -442,7 +443,7 @@ class TestPostWorkoutWithGpx(ApiTestCaseMixin, CallArgsMixin):
|
||||
assert len(data['data']['workouts']) == 1
|
||||
assert data['data']['workouts'][0]['notes'] == input_notes
|
||||
|
||||
def test_it_calls_configured_tile_server_for_static_map(
|
||||
def test_it_calls_configured_tile_server_for_static_map_when_default_static_map_to_false( # noqa
|
||||
self,
|
||||
app: Flask,
|
||||
user_1: User,
|
||||
@ -473,7 +474,36 @@ class TestPostWorkoutWithGpx(ApiTestCaseMixin, CallArgsMixin):
|
||||
in call_args[0]
|
||||
)
|
||||
|
||||
def test_it_calls_default_tile_server_for_static_map(
|
||||
def test_it_calls_static_map_with_fittrackee_user_agent_when_default_static_map_to_false( # noqa
|
||||
self,
|
||||
app: Flask,
|
||||
user_1: User,
|
||||
sport_1_cycling: Sport,
|
||||
gpx_file: str,
|
||||
static_map_get_mock: Mock,
|
||||
) -> None:
|
||||
client, auth_token = self.get_test_client_and_auth_token(
|
||||
app, user_1.email
|
||||
)
|
||||
client.post(
|
||||
'/api/workouts',
|
||||
data=dict(
|
||||
file=(BytesIO(str.encode(gpx_file)), 'example.gpx'),
|
||||
data='{"sport_id": 1}',
|
||||
),
|
||||
headers=dict(
|
||||
content_type='multipart/form-data',
|
||||
Authorization=f'Bearer {auth_token}',
|
||||
),
|
||||
)
|
||||
|
||||
call_kwargs = self.get_kwargs(static_map_get_mock.call_args)
|
||||
|
||||
assert call_kwargs['headers'] == {
|
||||
'User-Agent': f'FitTrackee v{VERSION}'
|
||||
}
|
||||
|
||||
def test_it_calls_default_tile_server_for_static_map_when_default_static_map_to_true( # noqa
|
||||
self,
|
||||
app_default_static_map: Flask,
|
||||
user_1: User,
|
||||
@ -504,6 +534,35 @@ class TestPostWorkoutWithGpx(ApiTestCaseMixin, CallArgsMixin):
|
||||
not in call_args[0]
|
||||
)
|
||||
|
||||
def test_it_calls_static_map_with_fittrackee_user_agent_when_default_static_map_to_true( # noqa
|
||||
self,
|
||||
app_default_static_map: Flask,
|
||||
user_1: User,
|
||||
sport_1_cycling: Sport,
|
||||
gpx_file: str,
|
||||
static_map_get_mock: Mock,
|
||||
) -> None:
|
||||
client, auth_token = self.get_test_client_and_auth_token(
|
||||
app_default_static_map, user_1.email
|
||||
)
|
||||
client.post(
|
||||
'/api/workouts',
|
||||
data=dict(
|
||||
file=(BytesIO(str.encode(gpx_file)), 'example.gpx'),
|
||||
data='{"sport_id": 1}',
|
||||
),
|
||||
headers=dict(
|
||||
content_type='multipart/form-data',
|
||||
Authorization=f'Bearer {auth_token}',
|
||||
),
|
||||
)
|
||||
|
||||
call_kwargs = self.get_kwargs(static_map_get_mock.call_args)
|
||||
|
||||
assert call_kwargs['headers'] == {
|
||||
'User-Agent': f'FitTrackee v{VERSION}'
|
||||
}
|
||||
|
||||
def test_it_returns_500_if_gpx_file_has_not_tracks(
|
||||
self,
|
||||
app: Flask,
|
||||
@ -527,7 +586,7 @@ class TestPostWorkoutWithGpx(ApiTestCaseMixin, CallArgsMixin):
|
||||
),
|
||||
)
|
||||
|
||||
data = self.assert_500(response, 'Error during gpx processing.')
|
||||
data = self.assert_500(response, 'error during gpx processing')
|
||||
assert 'data' not in data
|
||||
|
||||
def test_it_returns_500_if_gpx_has_invalid_xml(
|
||||
@ -556,7 +615,7 @@ class TestPostWorkoutWithGpx(ApiTestCaseMixin, CallArgsMixin):
|
||||
),
|
||||
)
|
||||
|
||||
data = self.assert_500(response, 'Error during gpx file parsing.')
|
||||
data = self.assert_500(response, 'error during gpx file parsing')
|
||||
assert 'data' not in data
|
||||
|
||||
def test_it_returns_400_if_workout_gpx_has_invalid_extension(
|
||||
@ -895,7 +954,7 @@ class TestPostWorkoutWithZipArchive(ApiTestCaseMixin):
|
||||
),
|
||||
)
|
||||
|
||||
data = self.assert_500(response, 'Error during gpx processing.')
|
||||
data = self.assert_500(response, 'error during gpx processing')
|
||||
assert 'data' not in data
|
||||
|
||||
def test_it_imports_only_max_number_of_files(
|
||||
|
@ -1,20 +1,32 @@
|
||||
import hashlib
|
||||
from typing import List
|
||||
import random
|
||||
from typing import Dict, List
|
||||
|
||||
from flask import current_app
|
||||
from staticmap import Line, StaticMap
|
||||
|
||||
from fittrackee import VERSION
|
||||
from fittrackee.files import get_absolute_file_path
|
||||
|
||||
|
||||
def get_static_map_tile_server_url(tile_server_config: Dict) -> str:
|
||||
if tile_server_config['STATICMAP_SUBDOMAINS']:
|
||||
subdomains = tile_server_config['STATICMAP_SUBDOMAINS'].split(',')
|
||||
subdomain = f'{random.choice(subdomains)}.' # nosec
|
||||
else:
|
||||
subdomain = ''
|
||||
return tile_server_config['URL'].replace('{s}.', subdomain)
|
||||
|
||||
|
||||
def generate_map(map_filepath: str, map_data: List) -> None:
|
||||
"""
|
||||
Generate and save map image from map data
|
||||
"""
|
||||
m = StaticMap(400, 225, 10)
|
||||
m.headers = {'User-Agent': f'FitTrackee v{VERSION}'}
|
||||
if not current_app.config['TILE_SERVER']['DEFAULT_STATICMAP']:
|
||||
m.url_template = current_app.config['TILE_SERVER']['URL'].replace(
|
||||
'{s}.', ''
|
||||
m.url_template = get_static_map_tile_server_url(
|
||||
current_app.config['TILE_SERVER']
|
||||
)
|
||||
line = Line(map_data, '#3388FF', 4)
|
||||
m.add_line(line)
|
||||
|
@ -307,9 +307,9 @@ def process_one_gpx_file(
|
||||
absolute_map_filepath = get_absolute_file_path(map_filepath)
|
||||
generate_map(absolute_map_filepath, map_data)
|
||||
except (gpxpy.gpx.GPXXMLSyntaxException, TypeError) as e:
|
||||
raise WorkoutException('error', 'Error during gpx file parsing.', e)
|
||||
raise WorkoutException('error', 'error during gpx file parsing', e)
|
||||
except Exception as e:
|
||||
raise WorkoutException('error', 'Error during gpx processing.', e)
|
||||
raise WorkoutException('error', 'error during gpx processing', e)
|
||||
|
||||
try:
|
||||
new_workout = create_workout(
|
||||
|
@ -2,6 +2,8 @@
|
||||
"ERROR": {
|
||||
"UNKNOWN": "Error. Please try again or contact the administrator.",
|
||||
"email: valid email must be provided": "Email: valid email must be provided.",
|
||||
"error during gpx processing": "Error during gpx processing.",
|
||||
"error during gpx file parsing": "Error during gpx file parsing.",
|
||||
"error on getting configuration": "Error on getting configuration.",
|
||||
"error when updating configuration": "Error when updating configuration",
|
||||
"error, please try again or contact the administrator": "Error, please try again or contact the administrator.",
|
||||
|
@ -2,6 +2,8 @@
|
||||
"ERROR": {
|
||||
"UNKNOWN": "Erreur. Veuillez réessayer ou contacter l'administrateur.",
|
||||
"email: valid email must be provided": "Courriel : une adresse électronique valide doit être fournie.",
|
||||
"error during gpx processing": "Erreur lors du traitement du fichier gpx.",
|
||||
"error during gpx file parsing": "Erreur lors de l'analyse du fichier.",
|
||||
"error on getting configuration": "Erreur lors de la récupération de la configuration.",
|
||||
"error when updating configuration": "Erreur lors de la mise à jour de la configuration",
|
||||
"error, please try again or contact the administrator": "Erreur, veuillez réessayer ou contacter l'administrateur.",
|
||||
|
Loading…
Reference in New Issue
Block a user