Merge pull request #245 from jat255/add_date_formats
Add ability to customize format used to display dates throughout the app
This commit is contained in:
commit
c4bb41caf8
20
Makefile
20
Makefile
@ -42,6 +42,9 @@ clean-install: clean
|
|||||||
rm -rf dist/
|
rm -rf dist/
|
||||||
|
|
||||||
## Docker commands for evaluation purposes
|
## Docker commands for evaluation purposes
|
||||||
|
docker-bandit:
|
||||||
|
docker-compose -f docker-compose-dev.yml exec fittrackee $(DOCKER_BANDIT) -r fittrackee -c pyproject.toml
|
||||||
|
|
||||||
docker-build:
|
docker-build:
|
||||||
docker-compose -f docker-compose-dev.yml build fittrackee
|
docker-compose -f docker-compose-dev.yml build fittrackee
|
||||||
|
|
||||||
@ -50,11 +53,15 @@ docker-build-all: docker-build docker-build-client
|
|||||||
docker-build-client:
|
docker-build-client:
|
||||||
docker-compose -f docker-compose-dev.yml build fittrackee_client
|
docker-compose -f docker-compose-dev.yml build fittrackee_client
|
||||||
|
|
||||||
|
docker-check-all: docker-bandit docker-lint-all docker-type-check docker-test-client docker-test-python
|
||||||
|
|
||||||
docker-init: docker-run docker-init-db docker-restart docker-run-workers
|
docker-init: docker-run docker-init-db docker-restart docker-run-workers
|
||||||
|
|
||||||
docker-init-db:
|
docker-init-db:
|
||||||
docker-compose -f docker-compose-dev.yml exec fittrackee docker/init-database.sh
|
docker-compose -f docker-compose-dev.yml exec fittrackee docker/init-database.sh
|
||||||
|
|
||||||
|
docker-lint-all: docker-lint-client docker-lint-python
|
||||||
|
|
||||||
docker-lint-client:
|
docker-lint-client:
|
||||||
docker-compose -f docker-compose-dev.yml up -d fittrackee_client
|
docker-compose -f docker-compose-dev.yml up -d fittrackee_client
|
||||||
docker-compose -f docker-compose-dev.yml exec fittrackee_client yarn lint
|
docker-compose -f docker-compose-dev.yml exec fittrackee_client yarn lint
|
||||||
@ -65,12 +72,18 @@ docker-lint-python: docker-run
|
|||||||
docker-logs:
|
docker-logs:
|
||||||
docker-compose -f docker-compose-dev.yml logs --follow
|
docker-compose -f docker-compose-dev.yml logs --follow
|
||||||
|
|
||||||
|
docker-migrate-db:
|
||||||
|
docker-compose -f docker-compose-dev.yml exec fittrackee $(DOCKER_FLASK) db migrate --directory $(DOCKER_MIGRATIONS)
|
||||||
|
|
||||||
docker-rebuild:
|
docker-rebuild:
|
||||||
docker-compose -f docker-compose-dev.yml build --no-cache
|
docker-compose -f docker-compose-dev.yml build --no-cache
|
||||||
|
|
||||||
docker-restart:
|
docker-restart:
|
||||||
docker-compose -f docker-compose-dev.yml restart fittrackee
|
docker-compose -f docker-compose-dev.yml restart fittrackee
|
||||||
|
|
||||||
|
docker-revision:
|
||||||
|
docker-compose -f docker-compose-dev.yml exec fittrackee $(DOCKER_FLASK) db revision --directory $(DOCKER_MIGRATIONS) --message $(MIGRATION_MESSAGE)
|
||||||
|
|
||||||
docker-run-all: docker-run docker-run-workers
|
docker-run-all: docker-run docker-run-workers
|
||||||
|
|
||||||
docker-run:
|
docker-run:
|
||||||
@ -104,9 +117,16 @@ docker-test-e2e: docker-run
|
|||||||
docker-test-python: docker-run
|
docker-test-python: docker-run
|
||||||
docker-compose -f docker-compose-dev.yml exec fittrackee docker/test-python.sh $(PYTEST_ARGS)
|
docker-compose -f docker-compose-dev.yml exec fittrackee docker/test-python.sh $(PYTEST_ARGS)
|
||||||
|
|
||||||
|
docker-type-check:
|
||||||
|
echo 'Running mypy in docker...'
|
||||||
|
docker-compose -f docker-compose-dev.yml exec fittrackee $(DOCKER_MYPY) fittrackee
|
||||||
|
|
||||||
docker-up:
|
docker-up:
|
||||||
docker-compose -f docker-compose-dev.yml up fittrackee
|
docker-compose -f docker-compose-dev.yml up fittrackee
|
||||||
|
|
||||||
|
docker-upgrade-db:
|
||||||
|
docker-compose -f docker-compose-dev.yml exec fittrackee $(DOCKER_FTCLI) db upgrade
|
||||||
|
|
||||||
downgrade-db:
|
downgrade-db:
|
||||||
$(FLASK) db downgrade --directory $(MIGRATIONS)
|
$(FLASK) db downgrade --directory $(MIGRATIONS)
|
||||||
|
|
||||||
|
@ -27,6 +27,14 @@ BANDIT = $(VENV)/bin/bandit
|
|||||||
PYBABEL = $(VENV)/bin/pybabel
|
PYBABEL = $(VENV)/bin/pybabel
|
||||||
FTCLI = $(VENV)/bin/ftcli
|
FTCLI = $(VENV)/bin/ftcli
|
||||||
|
|
||||||
|
# Docker env
|
||||||
|
export DOCKER_APP_DIR = /usr/src/app
|
||||||
|
export DOCKER_MIGRATIONS = $(DOCKER_APP_DIR)/fittrackee/migrations
|
||||||
|
export DOCKER_FLASK = /usr/local/bin/flask
|
||||||
|
export DOCKER_FTCLI = /usr/local/bin/ftcli
|
||||||
|
export DOCKER_BANDIT = /usr/local/bin/bandit
|
||||||
|
export DOCKER_MYPY = /usr/local/bin/mypy
|
||||||
|
|
||||||
# Node env
|
# Node env
|
||||||
NODE_MODULES = $(PWD)/fittrackee_client/node_modules
|
NODE_MODULES = $(PWD)/fittrackee_client/node_modules
|
||||||
NPM ?= yarn
|
NPM ?= yarn
|
||||||
|
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.e9c5b3a5.js"></script><script defer="defer" src="/static/js/app.f492102f.js"></script><link href="/static/css/app.eee1934d.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.a306e708.js"></script><script defer="defer" src="/static/js/app.2c35ea55.js"></script><link href="/static/css/app.a67ca8d9.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
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([[328],{6e3:function(t,e,i){i.r(e),i.d(e,{default:function(){return _}});var a=i(6252),n=i(2262),s=i(8273),c=i(5801),r=i(9917);const S=t=>((0,a.dD)("data-v-64629971"),t=t(),(0,a.Cn)(),t),l={id:"admin",class:"view"},p={key:0,class:"container"},u=S((()=>(0,a._)("div",{id:"bottom"},null,-1)));var T=(0,a.aZ)({__name:"AdminView",setup(t){const e=(0,r.o)(),i=(0,a.Fl)((()=>e.getters[c.SY.GETTERS.APP_CONFIG])),S=(0,a.Fl)((()=>e.getters[c.SY.GETTERS.APP_STATS])),T=(0,a.Fl)((()=>e.getters[c.YN.GETTERS.IS_ADMIN])),d=(0,a.Fl)((()=>e.getters[c.YN.GETTERS.USER_LOADING]));return(0,a.wF)((()=>e.dispatch(c.SY.ACTIONS.GET_APPLICATION_STATS))),(t,e)=>{const c=(0,a.up)("router-view");return(0,a.wg)(),(0,a.iD)("div",l,[(0,n.SU)(d)?(0,a.kq)("",!0):((0,a.wg)(),(0,a.iD)("div",p,[(0,n.SU)(T)?((0,a.wg)(),(0,a.j4)(c,{key:0,appConfig:(0,n.SU)(i),appStatistics:(0,n.SU)(S)},null,8,["appConfig","appStatistics"])):((0,a.wg)(),(0,a.j4)(s.Z,{key:1})),u]))])}}}),d=i(3744);const o=(0,d.Z)(T,[["__scopeId","data-v-64629971"]]);var _=o}}]);
|
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[328],{6e3:function(t,e,i){i.r(e),i.d(e,{default:function(){return _}});var a=i(6252),n=i(2262),s=i(8273),c=i(5801),r=i(9917);const S=t=>((0,a.dD)("data-v-64629971"),t=t(),(0,a.Cn)(),t),l={id:"admin",class:"view"},p={key:0,class:"container"},u=S((()=>(0,a._)("div",{id:"bottom"},null,-1)));var T=(0,a.aZ)({__name:"AdminView",setup(t){const e=(0,r.o)(),i=(0,a.Fl)((()=>e.getters[c.SY.GETTERS.APP_CONFIG])),S=(0,a.Fl)((()=>e.getters[c.SY.GETTERS.APP_STATS])),T=(0,a.Fl)((()=>e.getters[c.YN.GETTERS.IS_ADMIN])),d=(0,a.Fl)((()=>e.getters[c.YN.GETTERS.USER_LOADING]));return(0,a.wF)((()=>e.dispatch(c.SY.ACTIONS.GET_APPLICATION_STATS))),(t,e)=>{const c=(0,a.up)("router-view");return(0,a.wg)(),(0,a.iD)("div",l,[(0,n.SU)(d)?(0,a.kq)("",!0):((0,a.wg)(),(0,a.iD)("div",p,[(0,n.SU)(T)?((0,a.wg)(),(0,a.j4)(c,{key:0,appConfig:(0,n.SU)(i),appStatistics:(0,n.SU)(S)},null,8,["appConfig","appStatistics"])):((0,a.wg)(),(0,a.j4)(s.Z,{key:1})),u]))])}}}),d=i(3744);const o=(0,d.Z)(T,[["__scopeId","data-v-64629971"]]);var _=o}}]);
|
||||||
//# sourceMappingURL=admin.ab9e5f5f.js.map
|
//# sourceMappingURL=admin.3b0b84c0.js.map
|
@ -1 +1 @@
|
|||||||
{"version":3,"file":"static/js/admin.ab9e5f5f.js","mappings":"mOAGA,MAAMA,EAAeC,KAAMC,EAAAA,EAAAA,IAAa,mBAAmBD,EAAEA,KAAIE,EAAAA,EAAAA,MAAcF,GACzEG,EAAa,CACjBC,GAAI,QACJC,MAAO,QAEHC,EAAa,CACjBC,IAAK,EACLF,MAAO,aAEHG,EAA2BT,GAAa,KAAmBU,EAAAA,EAAAA,GAAoB,MAAO,CAAEL,GAAI,UAAY,MAAO,KAUrH,OAA4BM,EAAAA,EAAAA,IAAiB,CAC3CC,OAAQ,YACRC,MAAMC,GAEN,MAAMC,GAAQC,EAAAA,EAAAA,KAERC,GAAqCC,EAAAA,EAAAA,KACzC,IAAMH,EAAMI,QAAQC,EAAAA,GAAAA,QAAAA,cAEhBC,GAA6CH,EAAAA,EAAAA,KACjD,IAAMH,EAAMI,QAAQC,EAAAA,GAAAA,QAAAA,aAEhBE,GAAuCJ,EAAAA,EAAAA,KAC3C,IAAMH,EAAMI,QAAQI,EAAAA,GAAAA,QAAAA,YAEhBC,GAAoCN,EAAAA,EAAAA,KACxC,IAAMH,EAAMI,QAAQI,EAAAA,GAAAA,QAAAA,gBAKxB,OAFEE,EAAAA,EAAAA,KAAc,IAAMV,EAAMW,SAASN,EAAAA,GAAAA,QAAAA,yBAE9B,CAACO,EAAUC,KAChB,MAAMC,GAAyBC,EAAAA,EAAAA,IAAkB,eAEjD,OAAQC,EAAAA,EAAAA,OAAcC,EAAAA,EAAAA,IAAoB,MAAO5B,EAAY,EACzD6B,EAAAA,EAAAA,IAAOT,IAWLU,EAAAA,EAAAA,IAAoB,IAAI,KAVvBH,EAAAA,EAAAA,OAAcC,EAAAA,EAAAA,IAAoB,MAAOzB,EAAY,EACnD0B,EAAAA,EAAAA,IAAOX,KACHS,EAAAA,EAAAA,OAAcI,EAAAA,EAAAA,IAAaN,EAAwB,CAClDrB,IAAK,EACLS,WAAWgB,EAAAA,EAAAA,IAAOhB,GAClBI,eAAeY,EAAAA,EAAAA,IAAOZ,IACrB,KAAM,EAAG,CAAC,YAAa,qBACzBU,EAAAA,EAAAA,OAAcI,EAAAA,EAAAA,IAAaC,EAAAA,EAAU,CAAE5B,IAAK,KACjDC,MAVR,CAeD,I,UCvDD,MAAM4B,GAA2B,OAAgB,EAAQ,CAAC,CAAC,YAAY,qBAEvE,O","sources":["webpack://fittrackee_client/./src/views/AdminView.vue?67de","webpack://fittrackee_client/./src/views/AdminView.vue"],"sourcesContent":["import { defineComponent as _defineComponent } from 'vue'\nimport { unref as _unref, resolveComponent as _resolveComponent, openBlock as _openBlock, createBlock as _createBlock, createCommentVNode as _createCommentVNode, createElementVNode as _createElementVNode, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from \"vue\"\n\nconst _withScopeId = n => (_pushScopeId(\"data-v-64629971\"),n=n(),_popScopeId(),n)\nconst _hoisted_1 = {\n id: \"admin\",\n class: \"view\"\n}\nconst _hoisted_2 = {\n key: 0,\n class: \"container\"\n}\nconst _hoisted_3 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode(\"div\", { id: \"bottom\" }, null, -1))\n\nimport { computed, ComputedRef, onBeforeMount } from 'vue'\n\n import NotFound from '@/components/Common/NotFound.vue'\n import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'\n import { TAppConfig, IAppStatistics } from '@/types/application'\n import { useStore } from '@/use/useStore'\n\n \nexport default /*#__PURE__*/_defineComponent({\n __name: 'AdminView',\n setup(__props) {\n\n const store = useStore()\n\n const appConfig: ComputedRef<TAppConfig> = computed(\n () => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]\n )\n const appStatistics: ComputedRef<IAppStatistics> = computed(\n () => store.getters[ROOT_STORE.GETTERS.APP_STATS]\n )\n const isAuthUserAmin: ComputedRef<boolean> = computed(\n () => store.getters[AUTH_USER_STORE.GETTERS.IS_ADMIN]\n )\n const userLoading: ComputedRef<boolean> = computed(\n () => store.getters[AUTH_USER_STORE.GETTERS.USER_LOADING]\n )\n\n onBeforeMount(() => store.dispatch(ROOT_STORE.ACTIONS.GET_APPLICATION_STATS))\n\nreturn (_ctx: any,_cache: any) => {\n const _component_router_view = _resolveComponent(\"router-view\")!\n\n return (_openBlock(), _createElementBlock(\"div\", _hoisted_1, [\n (!_unref(userLoading))\n ? (_openBlock(), _createElementBlock(\"div\", _hoisted_2, [\n (_unref(isAuthUserAmin))\n ? (_openBlock(), _createBlock(_component_router_view, {\n key: 0,\n appConfig: _unref(appConfig),\n appStatistics: _unref(appStatistics)\n }, null, 8, [\"appConfig\", \"appStatistics\"]))\n : (_openBlock(), _createBlock(NotFound, { key: 1 })),\n _hoisted_3\n ]))\n : _createCommentVNode(\"\", true)\n ]))\n}\n}\n\n})","import script from \"./AdminView.vue?vue&type=script&setup=true&lang=ts\"\nexport * from \"./AdminView.vue?vue&type=script&setup=true&lang=ts\"\n\nimport \"./AdminView.vue?vue&type=style&index=0&id=64629971&lang=scss&scoped=true\"\n\nimport exportComponent from \"/mnt/data-lnx/Devs/00_Perso/FitTrackee/fittrackee_client/node_modules/vue-loader/dist/exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['__scopeId',\"data-v-64629971\"]])\n\nexport default __exports__"],"names":["_withScopeId","n","_pushScopeId","_popScopeId","_hoisted_1","id","class","_hoisted_2","key","_hoisted_3","_createElementVNode","_defineComponent","__name","setup","__props","store","useStore","appConfig","computed","getters","ROOT_STORE","appStatistics","isAuthUserAmin","AUTH_USER_STORE","userLoading","onBeforeMount","dispatch","_ctx","_cache","_component_router_view","_resolveComponent","_openBlock","_createElementBlock","_unref","_createCommentVNode","_createBlock","NotFound","__exports__"],"sourceRoot":""}
|
{"version":3,"file":"static/js/admin.3b0b84c0.js","mappings":"mOAGA,MAAMA,EAAeC,KAAMC,EAAAA,EAAAA,IAAa,mBAAmBD,EAAEA,KAAIE,EAAAA,EAAAA,MAAcF,GACzEG,EAAa,CACjBC,GAAI,QACJC,MAAO,QAEHC,EAAa,CACjBC,IAAK,EACLF,MAAO,aAEHG,EAA2BT,GAAa,KAAmBU,EAAAA,EAAAA,GAAoB,MAAO,CAAEL,GAAI,UAAY,MAAO,KAUrH,OAA4BM,EAAAA,EAAAA,IAAiB,CAC3CC,OAAQ,YACRC,MAAMC,GAEN,MAAMC,GAAQC,EAAAA,EAAAA,KAERC,GAAqCC,EAAAA,EAAAA,KACzC,IAAMH,EAAMI,QAAQC,EAAAA,GAAAA,QAAAA,cAEhBC,GAA6CH,EAAAA,EAAAA,KACjD,IAAMH,EAAMI,QAAQC,EAAAA,GAAAA,QAAAA,aAEhBE,GAAuCJ,EAAAA,EAAAA,KAC3C,IAAMH,EAAMI,QAAQI,EAAAA,GAAAA,QAAAA,YAEhBC,GAAoCN,EAAAA,EAAAA,KACxC,IAAMH,EAAMI,QAAQI,EAAAA,GAAAA,QAAAA,gBAKxB,OAFEE,EAAAA,EAAAA,KAAc,IAAMV,EAAMW,SAASN,EAAAA,GAAAA,QAAAA,yBAE9B,CAACO,EAAUC,KAChB,MAAMC,GAAyBC,EAAAA,EAAAA,IAAkB,eAEjD,OAAQC,EAAAA,EAAAA,OAAcC,EAAAA,EAAAA,IAAoB,MAAO5B,EAAY,EACzD6B,EAAAA,EAAAA,IAAOT,IAWLU,EAAAA,EAAAA,IAAoB,IAAI,KAVvBH,EAAAA,EAAAA,OAAcC,EAAAA,EAAAA,IAAoB,MAAOzB,EAAY,EACnD0B,EAAAA,EAAAA,IAAOX,KACHS,EAAAA,EAAAA,OAAcI,EAAAA,EAAAA,IAAaN,EAAwB,CAClDrB,IAAK,EACLS,WAAWgB,EAAAA,EAAAA,IAAOhB,GAClBI,eAAeY,EAAAA,EAAAA,IAAOZ,IACrB,KAAM,EAAG,CAAC,YAAa,qBACzBU,EAAAA,EAAAA,OAAcI,EAAAA,EAAAA,IAAaC,EAAAA,EAAU,CAAE5B,IAAK,KACjDC,MAVR,CAeD,I,UCvDD,MAAM4B,GAA2B,OAAgB,EAAQ,CAAC,CAAC,YAAY,qBAEvE,O","sources":["webpack://fittrackee_client/./src/views/AdminView.vue?67de","webpack://fittrackee_client/./src/views/AdminView.vue"],"sourcesContent":["import { defineComponent as _defineComponent } from 'vue'\nimport { unref as _unref, resolveComponent as _resolveComponent, openBlock as _openBlock, createBlock as _createBlock, createCommentVNode as _createCommentVNode, createElementVNode as _createElementVNode, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from \"vue\"\n\nconst _withScopeId = n => (_pushScopeId(\"data-v-64629971\"),n=n(),_popScopeId(),n)\nconst _hoisted_1 = {\n id: \"admin\",\n class: \"view\"\n}\nconst _hoisted_2 = {\n key: 0,\n class: \"container\"\n}\nconst _hoisted_3 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode(\"div\", { id: \"bottom\" }, null, -1))\n\nimport { computed, ComputedRef, onBeforeMount } from 'vue'\n\n import NotFound from '@/components/Common/NotFound.vue'\n import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'\n import { TAppConfig, IAppStatistics } from '@/types/application'\n import { useStore } from '@/use/useStore'\n\n \nexport default /*#__PURE__*/_defineComponent({\n __name: 'AdminView',\n setup(__props) {\n\n const store = useStore()\n\n const appConfig: ComputedRef<TAppConfig> = computed(\n () => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]\n )\n const appStatistics: ComputedRef<IAppStatistics> = computed(\n () => store.getters[ROOT_STORE.GETTERS.APP_STATS]\n )\n const isAuthUserAmin: ComputedRef<boolean> = computed(\n () => store.getters[AUTH_USER_STORE.GETTERS.IS_ADMIN]\n )\n const userLoading: ComputedRef<boolean> = computed(\n () => store.getters[AUTH_USER_STORE.GETTERS.USER_LOADING]\n )\n\n onBeforeMount(() => store.dispatch(ROOT_STORE.ACTIONS.GET_APPLICATION_STATS))\n\nreturn (_ctx: any,_cache: any) => {\n const _component_router_view = _resolveComponent(\"router-view\")!\n\n return (_openBlock(), _createElementBlock(\"div\", _hoisted_1, [\n (!_unref(userLoading))\n ? (_openBlock(), _createElementBlock(\"div\", _hoisted_2, [\n (_unref(isAuthUserAmin))\n ? (_openBlock(), _createBlock(_component_router_view, {\n key: 0,\n appConfig: _unref(appConfig),\n appStatistics: _unref(appStatistics)\n }, null, 8, [\"appConfig\", \"appStatistics\"]))\n : (_openBlock(), _createBlock(NotFound, { key: 1 })),\n _hoisted_3\n ]))\n : _createCommentVNode(\"\", true)\n ]))\n}\n}\n\n})","import script from \"./AdminView.vue?vue&type=script&setup=true&lang=ts\"\nexport * from \"./AdminView.vue?vue&type=script&setup=true&lang=ts\"\n\nimport \"./AdminView.vue?vue&type=style&index=0&id=64629971&lang=scss&scoped=true\"\n\nimport exportComponent from \"/mnt/data-lnx/Devs/00_Perso/FitTrackee/fittrackee_client/node_modules/vue-loader/dist/exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['__scopeId',\"data-v-64629971\"]])\n\nexport default __exports__"],"names":["_withScopeId","n","_pushScopeId","_popScopeId","_hoisted_1","id","class","_hoisted_2","key","_hoisted_3","_createElementVNode","_defineComponent","__name","setup","__props","store","useStore","appConfig","computed","getters","ROOT_STORE","appStatistics","isAuthUserAmin","AUTH_USER_STORE","userLoading","onBeforeMount","dispatch","_ctx","_cache","_component_router_view","_resolveComponent","_openBlock","_createElementBlock","_unref","_createCommentVNode","_createBlock","NotFound","__exports__"],"sourceRoot":""}
|
2
fittrackee/dist/static/js/app.2c35ea55.js
vendored
Normal file
2
fittrackee/dist/static/js/app.2c35ea55.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/js/app.2c35ea55.js.map
vendored
Normal file
1
fittrackee/dist/static/js/app.2c35ea55.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
fittrackee/dist/static/js/app.f492102f.js
vendored
2
fittrackee/dist/static/js/app.f492102f.js
vendored
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
File diff suppressed because one or more lines are too long
@ -1,2 +1,2 @@
|
|||||||
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[845],{4264:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});r(7658);var n=r(6252),a=r(2262),s=r(3577),u=r(2201),o=r(7167),i=r(5801),c=r(9917);const l={key:0,id:"account-confirmation",class:"center-card with-margin"},E={class:"error-message"};var _=(0,n.aZ)({__name:"AccountConfirmationView",setup(e){const t=(0,u.yj)(),r=(0,u.tv)(),_=(0,c.o)(),d=(0,n.Fl)((()=>_.getters[i.SY.GETTERS.ERROR_MESSAGES])),S=(0,n.Fl)((()=>t.query.token));function m(){S.value?_.dispatch(i.YN.ACTIONS.CONFIRM_ACCOUNT,{token:S.value}):r.push("/")}return(0,n.wF)((()=>m())),(0,n.Ah)((()=>_.commit(i.SY.MUTATIONS.EMPTY_ERROR_MESSAGES))),(e,t)=>{const r=(0,n.up)("router-link");return(0,a.SU)(d)?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(o.Z),(0,n._)("p",E,[(0,n._)("span",null,(0,s.zw)(e.$t("error.SOMETHING_WRONG"))+".",1),(0,n.Wm)(r,{class:"links",to:"/account-confirmation/resend"},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.$t("buttons.ACCOUNT-CONFIRMATION-RESEND"))+"? ",1)])),_:1})])])):(0,n.kq)("",!0)}}}),d=r(3744);const S=(0,d.Z)(_,[["__scopeId","data-v-785df978"]]);var m=S},8160:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});r(7658);var n=r(6252),a=r(2262),s=r(3577),u=r(2201),o=r(7167),i=r(5801),c=r(9917);const l={key:0,id:"email-update",class:"center-card with-margin"},E={class:"error-message"};var _=(0,n.aZ)({__name:"EmailUpdateView",setup(e){const t=(0,u.yj)(),r=(0,u.tv)(),_=(0,c.o)(),d=(0,n.Fl)((()=>_.getters[i.YN.GETTERS.AUTH_USER_PROFILE])),S=(0,n.Fl)((()=>_.getters[i.YN.GETTERS.IS_AUTHENTICATED])),m=(0,n.Fl)((()=>_.getters[i.SY.GETTERS.ERROR_MESSAGES])),p=(0,n.Fl)((()=>t.query.token));function R(){p.value?_.dispatch(i.YN.ACTIONS.CONFIRM_EMAIL,{token:p.value,refreshUser:S.value}):r.push("/")}return(0,n.wF)((()=>R())),(0,n.Ah)((()=>_.commit(i.SY.MUTATIONS.EMPTY_ERROR_MESSAGES))),(0,n.YP)((()=>m.value),(e=>{d.value.username&&e&&r.push("/")})),(e,t)=>{const r=(0,n.up)("router-link"),u=(0,n.up)("i18n-t");return(0,a.SU)(m)&&!(0,a.SU)(d).username?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(o.Z),(0,n._)("p",E,[(0,n._)("span",null,(0,s.zw)(e.$t("error.SOMETHING_WRONG"))+".",1),(0,n._)("span",null,[(0,n.Wm)(u,{keypath:"user.PROFILE.ERRORED_EMAIL_UPDATE"},{default:(0,n.w5)((()=>[(0,n.Wm)(r,{to:"/login"},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.$t("user.LOG_IN")),1)])),_:1})])),_:1})])])])):(0,n.kq)("",!0)}}}),d=r(3744);const S=(0,d.Z)(_,[["__scopeId","data-v-8c2ec9ce"]]);var m=S},6266:function(e,t,r){r.r(t),r.d(t,{default:function(){return d}});var n=r(6252),a=r(2262),s=r(5801),u=r(9917);const o=e=>((0,n.dD)("data-v-05463732"),e=e(),(0,n.Cn)(),e),i={key:0,id:"profile",class:"container view"},c=o((()=>(0,n._)("div",{id:"bottom"},null,-1)));var l=(0,n.aZ)({__name:"ProfileView",setup(e){const t=(0,u.o)(),r=(0,n.Fl)((()=>t.getters[s.YN.GETTERS.AUTH_USER_PROFILE]));return(e,t)=>{const s=(0,n.up)("router-view");return(0,a.SU)(r).username?((0,n.wg)(),(0,n.iD)("div",i,[(0,n.Wm)(s,{user:(0,a.SU)(r)},null,8,["user"]),c])):(0,n.kq)("",!0)}}}),E=r(3744);const _=(0,E.Z)(l,[["__scopeId","data-v-05463732"]]);var d=_},9453:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});var n=r(6252),a=r(2262),s=r(2201),u=r(2179),o=r(7408),i=r(5801),c=r(9917);const l={key:0,id:"user",class:"view"},E={class:"box"};var _=(0,n.aZ)({__name:"UserView",props:{fromAdmin:{type:Boolean}},setup(e){const t=e,{fromAdmin:r}=(0,a.BK)(t),_=(0,s.yj)(),d=(0,c.o)(),S=(0,n.Fl)((()=>d.getters[i.RT.GETTERS.USER]));return(0,n.wF)((()=>{_.params.username&&"string"===typeof _.params.username&&d.dispatch(i.RT.ACTIONS.GET_USER,_.params.username)})),(0,n.Jd)((()=>{d.dispatch(i.RT.ACTIONS.EMPTY_USER)})),(e,t)=>(0,a.SU)(S).username?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(u.Z,{user:(0,a.SU)(S)},null,8,["user"]),(0,n._)("div",E,[(0,n.Wm)(o.Z,{user:(0,a.SU)(S),"from-admin":(0,a.SU)(r)},null,8,["user","from-admin"])])])):(0,n.kq)("",!0)}}),d=r(3744);const S=(0,d.Z)(_,[["__scopeId","data-v-af7007f4"]]);var m=S}}]);
|
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[845],{4264:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});r(7658);var n=r(6252),a=r(2262),s=r(3577),u=r(2201),o=r(7167),i=r(5801),c=r(9917);const l={key:0,id:"account-confirmation",class:"center-card with-margin"},E={class:"error-message"};var _=(0,n.aZ)({__name:"AccountConfirmationView",setup(e){const t=(0,u.yj)(),r=(0,u.tv)(),_=(0,c.o)(),d=(0,n.Fl)((()=>_.getters[i.SY.GETTERS.ERROR_MESSAGES])),S=(0,n.Fl)((()=>t.query.token));function m(){S.value?_.dispatch(i.YN.ACTIONS.CONFIRM_ACCOUNT,{token:S.value}):r.push("/")}return(0,n.wF)((()=>m())),(0,n.Ah)((()=>_.commit(i.SY.MUTATIONS.EMPTY_ERROR_MESSAGES))),(e,t)=>{const r=(0,n.up)("router-link");return(0,a.SU)(d)?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(o.Z),(0,n._)("p",E,[(0,n._)("span",null,(0,s.zw)(e.$t("error.SOMETHING_WRONG"))+".",1),(0,n.Wm)(r,{class:"links",to:"/account-confirmation/resend"},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.$t("buttons.ACCOUNT-CONFIRMATION-RESEND"))+"? ",1)])),_:1})])])):(0,n.kq)("",!0)}}}),d=r(3744);const S=(0,d.Z)(_,[["__scopeId","data-v-785df978"]]);var m=S},8160:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});r(7658);var n=r(6252),a=r(2262),s=r(3577),u=r(2201),o=r(7167),i=r(5801),c=r(9917);const l={key:0,id:"email-update",class:"center-card with-margin"},E={class:"error-message"};var _=(0,n.aZ)({__name:"EmailUpdateView",setup(e){const t=(0,u.yj)(),r=(0,u.tv)(),_=(0,c.o)(),d=(0,n.Fl)((()=>_.getters[i.YN.GETTERS.AUTH_USER_PROFILE])),S=(0,n.Fl)((()=>_.getters[i.YN.GETTERS.IS_AUTHENTICATED])),m=(0,n.Fl)((()=>_.getters[i.SY.GETTERS.ERROR_MESSAGES])),p=(0,n.Fl)((()=>t.query.token));function R(){p.value?_.dispatch(i.YN.ACTIONS.CONFIRM_EMAIL,{token:p.value,refreshUser:S.value}):r.push("/")}return(0,n.wF)((()=>R())),(0,n.Ah)((()=>_.commit(i.SY.MUTATIONS.EMPTY_ERROR_MESSAGES))),(0,n.YP)((()=>m.value),(e=>{d.value.username&&e&&r.push("/")})),(e,t)=>{const r=(0,n.up)("router-link"),u=(0,n.up)("i18n-t");return(0,a.SU)(m)&&!(0,a.SU)(d).username?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(o.Z),(0,n._)("p",E,[(0,n._)("span",null,(0,s.zw)(e.$t("error.SOMETHING_WRONG"))+".",1),(0,n._)("span",null,[(0,n.Wm)(u,{keypath:"user.PROFILE.ERRORED_EMAIL_UPDATE"},{default:(0,n.w5)((()=>[(0,n.Wm)(r,{to:"/login"},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.$t("user.LOG_IN")),1)])),_:1})])),_:1})])])])):(0,n.kq)("",!0)}}}),d=r(3744);const S=(0,d.Z)(_,[["__scopeId","data-v-8c2ec9ce"]]);var m=S},6266:function(e,t,r){r.r(t),r.d(t,{default:function(){return d}});var n=r(6252),a=r(2262),s=r(5801),u=r(9917);const o=e=>((0,n.dD)("data-v-05463732"),e=e(),(0,n.Cn)(),e),i={key:0,id:"profile",class:"container view"},c=o((()=>(0,n._)("div",{id:"bottom"},null,-1)));var l=(0,n.aZ)({__name:"ProfileView",setup(e){const t=(0,u.o)(),r=(0,n.Fl)((()=>t.getters[s.YN.GETTERS.AUTH_USER_PROFILE]));return(e,t)=>{const s=(0,n.up)("router-view");return(0,a.SU)(r).username?((0,n.wg)(),(0,n.iD)("div",i,[(0,n.Wm)(s,{user:(0,a.SU)(r)},null,8,["user"]),c])):(0,n.kq)("",!0)}}}),E=r(3744);const _=(0,E.Z)(l,[["__scopeId","data-v-05463732"]]);var d=_},9453:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});var n=r(6252),a=r(2262),s=r(2201),u=r(2179),o=r(1585),i=r(5801),c=r(9917);const l={key:0,id:"user",class:"view"},E={class:"box"};var _=(0,n.aZ)({__name:"UserView",props:{fromAdmin:{type:Boolean}},setup(e){const t=e,{fromAdmin:r}=(0,a.BK)(t),_=(0,s.yj)(),d=(0,c.o)(),S=(0,n.Fl)((()=>d.getters[i.RT.GETTERS.USER]));return(0,n.wF)((()=>{_.params.username&&"string"===typeof _.params.username&&d.dispatch(i.RT.ACTIONS.GET_USER,_.params.username)})),(0,n.Jd)((()=>{d.dispatch(i.RT.ACTIONS.EMPTY_USER)})),(e,t)=>(0,a.SU)(S).username?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(u.Z,{user:(0,a.SU)(S)},null,8,["user"]),(0,n._)("div",E,[(0,n.Wm)(o.Z,{user:(0,a.SU)(S),"from-admin":(0,a.SU)(r)},null,8,["user","from-admin"])])])):(0,n.kq)("",!0)}}),d=r(3744);const S=(0,d.Z)(_,[["__scopeId","data-v-af7007f4"]]);var m=S}}]);
|
||||||
//# sourceMappingURL=profile.dd30724d.js.map
|
//# sourceMappingURL=profile.23749cd8.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
@ -1,2 +1,2 @@
|
|||||||
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[193],{7885:function(e,s,t){t.r(s),t.d(s,{default:function(){return A}});var a=t(6252),r=t(2262),l=t(3577),o=(t(7658),t(9150)),n=t(4998);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-30799d13"]]);var Z=F,x=t(5630),D=t(5801),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}}]);
|
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[193],{7885:function(e,s,t){t.r(s),t.d(s,{default:function(){return A}});var a=t(6252),r=t(2262),l=t(3577),o=(t(7658),t(9150)),n=t(4998);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-30799d13"]]);var Z=F,x=t(5630),D=t(5801),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.9cd652fd.js.map
|
//# sourceMappingURL=statistics.eaf4afd3.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
1
fittrackee/dist/static/js/workouts.f4402b84.js.map
vendored
Normal file
1
fittrackee/dist/static/js/workouts.f4402b84.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,31 @@
|
|||||||
|
"""Add date_format for date display to user preferences in DB
|
||||||
|
|
||||||
|
Revision ID: bf13b8f5589d
|
||||||
|
Revises: 84d840ce853b
|
||||||
|
Create Date: 2022-10-25 18:53:59.378423
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'bf13b8f5589d'
|
||||||
|
down_revision = '5b936821326d'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.add_column(
|
||||||
|
'users', sa.Column('date_format', sa.String(length=50), nullable=True)
|
||||||
|
)
|
||||||
|
op.execute("UPDATE users SET date_format = 'MM/dd/yyyy'")
|
||||||
|
op.alter_column('users', 'date_format', nullable=False)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('users', 'date_format')
|
||||||
|
# ### end Alembic commands ###
|
@ -235,6 +235,27 @@ class TestUserRegistration(ApiTestCaseMixin):
|
|||||||
assert data['status'] == 'success'
|
assert data['status'] == 'success'
|
||||||
assert 'auth_token' not in data
|
assert 'auth_token' not in data
|
||||||
|
|
||||||
|
def test_it_creates_user_with_default_date_format(
|
||||||
|
self, app: Flask
|
||||||
|
) -> None:
|
||||||
|
client = app.test_client()
|
||||||
|
username = self.random_string()
|
||||||
|
|
||||||
|
client.post(
|
||||||
|
'/api/auth/register',
|
||||||
|
data=json.dumps(
|
||||||
|
dict(
|
||||||
|
username=username,
|
||||||
|
email=self.random_email(),
|
||||||
|
password=self.random_string(),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
content_type='application/json',
|
||||||
|
)
|
||||||
|
|
||||||
|
new_user = User.query.filter_by(username=username).first()
|
||||||
|
assert new_user.date_format == 'MM/dd/yyyy'
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'input_language,expected_language',
|
'input_language,expected_language',
|
||||||
[('en', 'en'), ('fr', 'fr'), ('invalid', 'en'), (None, 'en')],
|
[('en', 'en'), ('fr', 'fr'), ('invalid', 'en'), (None, 'en')],
|
||||||
@ -1394,6 +1415,7 @@ class TestUserPreferencesUpdate(ApiTestCaseMixin):
|
|||||||
language=input_language,
|
language=input_language,
|
||||||
imperial_units=True,
|
imperial_units=True,
|
||||||
display_ascent=False,
|
display_ascent=False,
|
||||||
|
date_format='yyyy-MM-dd',
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
headers=dict(Authorization=f'Bearer {auth_token}'),
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
||||||
@ -1407,6 +1429,7 @@ class TestUserPreferencesUpdate(ApiTestCaseMixin):
|
|||||||
assert data['data']['imperial_units'] is True
|
assert data['data']['imperial_units'] is True
|
||||||
assert data['data']['language'] == expected_language
|
assert data['data']['language'] == expected_language
|
||||||
assert data['data']['timezone'] == 'America/New_York'
|
assert data['data']['timezone'] == 'America/New_York'
|
||||||
|
assert data['data']['date_format'] == 'yyyy-MM-dd'
|
||||||
assert data['data']['weekm'] is True
|
assert data['data']['weekm'] is True
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
@ -173,6 +173,7 @@ def register_user() -> Union[Tuple[Dict, int], HttpResponse]:
|
|||||||
if not user:
|
if not user:
|
||||||
new_user = User(username=username, email=email, password=password)
|
new_user = User(username=username, email=email, password=password)
|
||||||
new_user.timezone = 'Europe/Paris'
|
new_user.timezone = 'Europe/Paris'
|
||||||
|
new_user.date_format = 'MM/dd/yyyy'
|
||||||
new_user.confirmation_token = secrets.token_urlsafe(30)
|
new_user.confirmation_token = secrets.token_urlsafe(30)
|
||||||
new_user.language = language
|
new_user.language = language
|
||||||
db.session.add(new_user)
|
db.session.add(new_user)
|
||||||
@ -780,6 +781,7 @@ def edit_user_preferences(auth_user: User) -> Union[Dict, HttpResponse]:
|
|||||||
"bio": null,
|
"bio": null,
|
||||||
"birth_date": null,
|
"birth_date": null,
|
||||||
"created_at": "Sun, 14 Jul 2019 14:09:58 GMT",
|
"created_at": "Sun, 14 Jul 2019 14:09:58 GMT",
|
||||||
|
"date_format": "MM/dd/yyyy",
|
||||||
"display_ascent": true,
|
"display_ascent": true,
|
||||||
"email": "sam@example.com",
|
"email": "sam@example.com",
|
||||||
"first_name": null,
|
"first_name": null,
|
||||||
@ -854,6 +856,7 @@ def edit_user_preferences(auth_user: User) -> Union[Dict, HttpResponse]:
|
|||||||
}
|
}
|
||||||
|
|
||||||
:<json boolean display_ascent: display highest ascent records and total
|
:<json boolean display_ascent: display highest ascent records and total
|
||||||
|
:<json string date_format: the format used to display dates in the app
|
||||||
:<json boolean imperial_units: display distance in imperial units
|
:<json boolean imperial_units: display distance in imperial units
|
||||||
:<json string language: language preferences
|
:<json string language: language preferences
|
||||||
:<json string timezone: user time zone
|
:<json string timezone: user time zone
|
||||||
@ -874,6 +877,7 @@ def edit_user_preferences(auth_user: User) -> Union[Dict, HttpResponse]:
|
|||||||
# get post data
|
# get post data
|
||||||
post_data = request.get_json()
|
post_data = request.get_json()
|
||||||
user_mandatory_data = {
|
user_mandatory_data = {
|
||||||
|
'date_format',
|
||||||
'display_ascent',
|
'display_ascent',
|
||||||
'imperial_units',
|
'imperial_units',
|
||||||
'language',
|
'language',
|
||||||
@ -883,6 +887,7 @@ def edit_user_preferences(auth_user: User) -> Union[Dict, HttpResponse]:
|
|||||||
if not post_data or not post_data.keys() >= user_mandatory_data:
|
if not post_data or not post_data.keys() >= user_mandatory_data:
|
||||||
return InvalidPayloadErrorResponse()
|
return InvalidPayloadErrorResponse()
|
||||||
|
|
||||||
|
date_format = post_data.get('date_format')
|
||||||
display_ascent = post_data.get('display_ascent')
|
display_ascent = post_data.get('display_ascent')
|
||||||
imperial_units = post_data.get('imperial_units')
|
imperial_units = post_data.get('imperial_units')
|
||||||
language = get_language(post_data.get('language'))
|
language = get_language(post_data.get('language'))
|
||||||
@ -890,6 +895,7 @@ def edit_user_preferences(auth_user: User) -> Union[Dict, HttpResponse]:
|
|||||||
weekm = post_data.get('weekm')
|
weekm = post_data.get('weekm')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
auth_user.date_format = date_format
|
||||||
auth_user.display_ascent = display_ascent
|
auth_user.display_ascent = display_ascent
|
||||||
auth_user.imperial_units = imperial_units
|
auth_user.imperial_units = imperial_units
|
||||||
auth_user.language = language
|
auth_user.language = language
|
||||||
|
@ -33,6 +33,7 @@ class User(BaseModel):
|
|||||||
bio = db.Column(db.String(200), nullable=True)
|
bio = db.Column(db.String(200), nullable=True)
|
||||||
picture = db.Column(db.String(255), nullable=True)
|
picture = db.Column(db.String(255), nullable=True)
|
||||||
timezone = db.Column(db.String(50), nullable=True)
|
timezone = db.Column(db.String(50), nullable=True)
|
||||||
|
date_format = db.Column(db.String(50), nullable=True)
|
||||||
# does the week start Monday?
|
# does the week start Monday?
|
||||||
weekm = db.Column(db.Boolean, default=False, nullable=False)
|
weekm = db.Column(db.Boolean, default=False, nullable=False)
|
||||||
workouts = db.relationship(
|
workouts = db.relationship(
|
||||||
@ -190,6 +191,7 @@ class User(BaseModel):
|
|||||||
serialized_user = {
|
serialized_user = {
|
||||||
**serialized_user,
|
**serialized_user,
|
||||||
**{
|
**{
|
||||||
|
'date_format': self.date_format,
|
||||||
'display_ascent': self.display_ascent,
|
'display_ascent': self.display_ascent,
|
||||||
'imperial_units': self.imperial_units,
|
'imperial_units': self.imperial_units,
|
||||||
'language': self.language,
|
'language': self.language,
|
||||||
|
@ -62,9 +62,10 @@
|
|||||||
{{ $t('user.PROFILE.REGISTRATION_DATE') }}
|
{{ $t('user.PROFILE.REGISTRATION_DATE') }}
|
||||||
</span>
|
</span>
|
||||||
{{
|
{{
|
||||||
format(
|
formatDate(
|
||||||
getDateWithTZ(user.created_at, authUser.timezone),
|
user.created_at,
|
||||||
'dd/MM/yyyy HH:mm'
|
authUser.timezone,
|
||||||
|
authUser.date_format
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</td>
|
</td>
|
||||||
@ -130,7 +131,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { format } from 'date-fns'
|
|
||||||
import {
|
import {
|
||||||
ComputedRef,
|
ComputedRef,
|
||||||
Ref,
|
Ref,
|
||||||
@ -152,7 +152,7 @@
|
|||||||
import { IAuthUserProfile, IUserProfile } from '@/types/user'
|
import { IAuthUserProfile, IUserProfile } from '@/types/user'
|
||||||
import { useStore } from '@/use/useStore'
|
import { useStore } from '@/use/useStore'
|
||||||
import { getQuery, sortList } from '@/utils/api'
|
import { getQuery, sortList } from '@/utils/api'
|
||||||
import { getDateWithTZ } from '@/utils/dates'
|
import { formatDate } from '@/utils/dates'
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
@ -86,7 +86,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
span {
|
span {
|
||||||
padding: 2px 5px;
|
padding: 2px;
|
||||||
}
|
}
|
||||||
.record-type {
|
.record-type {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
@ -94,7 +94,12 @@
|
|||||||
.record-value {
|
.record-value {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
padding-right: $default-padding * 2;
|
padding-right: $default-padding;
|
||||||
|
}
|
||||||
|
.record-date {
|
||||||
|
white-space: nowrap;
|
||||||
|
min-width: 30%;
|
||||||
|
text-align: right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,8 @@
|
|||||||
translateSports(props.sports, t),
|
translateSports(props.sports, t),
|
||||||
props.user.timezone,
|
props.user.timezone,
|
||||||
props.user.imperial_units,
|
props.user.imperial_units,
|
||||||
props.user.display_ascent
|
props.user.display_ascent,
|
||||||
|
props.user.date_format
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
</script>
|
</script>
|
||||||
|
@ -130,6 +130,8 @@
|
|||||||
import { TAppConfig } from '@/types/application'
|
import { TAppConfig } from '@/types/application'
|
||||||
import { IAuthUserProfile, IUserProfile } from '@/types/user'
|
import { IAuthUserProfile, IUserProfile } from '@/types/user'
|
||||||
import { useStore } from '@/use/useStore'
|
import { useStore } from '@/use/useStore'
|
||||||
|
import { formatDate, getDateFormat } from '@/utils/dates'
|
||||||
|
import { localeFromLanguage } from '@/utils/locales'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
user: IUserProfile
|
user: IUserProfile
|
||||||
@ -142,17 +144,28 @@
|
|||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
const { user, fromAdmin } = toRefs(props)
|
const { user, fromAdmin } = toRefs(props)
|
||||||
|
const language: ComputedRef<string> = computed(
|
||||||
|
() => store.getters[ROOT_STORE.GETTERS.LANGUAGE]
|
||||||
|
)
|
||||||
const authUser: ComputedRef<IAuthUserProfile> = computed(
|
const authUser: ComputedRef<IAuthUserProfile> = computed(
|
||||||
() => store.getters[AUTH_USER_STORE.GETTERS.AUTH_USER_PROFILE]
|
() => store.getters[AUTH_USER_STORE.GETTERS.AUTH_USER_PROFILE]
|
||||||
)
|
)
|
||||||
const registrationDate = computed(() =>
|
const registrationDate = computed(() =>
|
||||||
props.user.created_at
|
props.user.created_at
|
||||||
? format(new Date(props.user.created_at), 'dd/MM/yyyy HH:mm')
|
? formatDate(
|
||||||
|
props.user.created_at,
|
||||||
|
authUser.value.timezone,
|
||||||
|
authUser.value.date_format
|
||||||
|
)
|
||||||
: ''
|
: ''
|
||||||
)
|
)
|
||||||
const birthDate = computed(() =>
|
const birthDate = computed(() =>
|
||||||
props.user.birth_date
|
props.user.birth_date
|
||||||
? format(new Date(props.user.birth_date), 'dd/MM/yyyy')
|
? format(
|
||||||
|
new Date(props.user.birth_date),
|
||||||
|
`${getDateFormat(authUser.value.date_format, language.value)}`,
|
||||||
|
{ locale: localeFromLanguage[language.value] }
|
||||||
|
)
|
||||||
: ''
|
: ''
|
||||||
)
|
)
|
||||||
const isSuccess = computed(
|
const isSuccess = computed(
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
<div id="user-preferences" class="description-list">
|
<div id="user-preferences" class="description-list">
|
||||||
<dl>
|
<dl>
|
||||||
<dt>{{ $t('user.PROFILE.LANGUAGE') }}:</dt>
|
<dt>{{ $t('user.PROFILE.LANGUAGE') }}:</dt>
|
||||||
<dd>{{ language }}</dd>
|
<dd>{{ userLanguage }}</dd>
|
||||||
<dt>{{ $t('user.PROFILE.TIMEZONE') }}:</dt>
|
<dt>{{ $t('user.PROFILE.TIMEZONE') }}:</dt>
|
||||||
<dd>{{ timezone }}</dd>
|
<dd>{{ timezone }}</dd>
|
||||||
|
<dt>{{ $t('user.PROFILE.DATE_FORMAT') }}:</dt>
|
||||||
|
<dd>{{ getDateFormat(date_format, appLanguage) }}</dd>
|
||||||
<dt>{{ $t('user.PROFILE.FIRST_DAY_OF_WEEK') }}:</dt>
|
<dt>{{ $t('user.PROFILE.FIRST_DAY_OF_WEEK') }}:</dt>
|
||||||
<dd>{{ $t(`user.PROFILE.${fistDayOfWeek}`) }}</dd>
|
<dd>{{ $t(`user.PROFILE.${fistDayOfWeek}`) }}</dd>
|
||||||
<dt>{{ $t('user.PROFILE.UNITS.LABEL') }}:</dt>
|
<dt>{{ $t('user.PROFILE.UNITS.LABEL') }}:</dt>
|
||||||
@ -28,9 +30,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed, ComputedRef } from 'vue'
|
||||||
|
|
||||||
|
import { ROOT_STORE } from '@/store/constants'
|
||||||
import { IAuthUserProfile } from '@/types/user'
|
import { IAuthUserProfile } from '@/types/user'
|
||||||
|
import { useStore } from '@/use/useStore'
|
||||||
|
import { getDateFormat } from '@/utils/dates'
|
||||||
import { languageLabels } from '@/utils/locales'
|
import { languageLabels } from '@/utils/locales'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -38,7 +43,12 @@
|
|||||||
}
|
}
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const language = computed(() =>
|
const store = useStore()
|
||||||
|
|
||||||
|
const appLanguage: ComputedRef<string> = computed(
|
||||||
|
() => store.getters[ROOT_STORE.GETTERS.LANGUAGE]
|
||||||
|
)
|
||||||
|
const userLanguage = computed(() =>
|
||||||
props.user.language
|
props.user.language
|
||||||
? languageLabels[props.user.language]
|
? languageLabels[props.user.language]
|
||||||
: languageLabels['en']
|
: languageLabels['en']
|
||||||
@ -47,6 +57,9 @@
|
|||||||
const timezone = computed(() =>
|
const timezone = computed(() =>
|
||||||
props.user.timezone ? props.user.timezone : 'Europe/Paris'
|
props.user.timezone ? props.user.timezone : 'Europe/Paris'
|
||||||
)
|
)
|
||||||
|
const date_format = computed(() =>
|
||||||
|
props.user.date_format ? props.user.date_format : 'MM/dd/yyyy'
|
||||||
|
)
|
||||||
const display_ascent = computed(() =>
|
const display_ascent = computed(() =>
|
||||||
props.user.display_ascent ? 'DISPLAYED' : 'HIDDEN'
|
props.user.display_ascent ? 'DISPLAYED' : 'HIDDEN'
|
||||||
)
|
)
|
||||||
|
@ -65,11 +65,12 @@
|
|||||||
import { ComputedRef, computed, reactive, onMounted, onUnmounted } from 'vue'
|
import { ComputedRef, computed, reactive, onMounted, onUnmounted } from 'vue'
|
||||||
|
|
||||||
import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'
|
import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'
|
||||||
import { IUserProfile, IUserPayload } from '@/types/user'
|
import { IUserProfile, IUserPayload, IAuthUserProfile } from '@/types/user'
|
||||||
import { useStore } from '@/use/useStore'
|
import { useStore } from '@/use/useStore'
|
||||||
|
import { formatDate } from '@/utils/dates'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
user: IUserProfile
|
user: IAuthUserProfile
|
||||||
}
|
}
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
@ -84,7 +85,11 @@
|
|||||||
})
|
})
|
||||||
const registrationDate = computed(() =>
|
const registrationDate = computed(() =>
|
||||||
props.user.created_at
|
props.user.created_at
|
||||||
? format(new Date(props.user.created_at), 'dd/MM/yyyy HH:mm')
|
? formatDate(
|
||||||
|
props.user.created_at,
|
||||||
|
props.user.timezone,
|
||||||
|
props.user.date_format
|
||||||
|
)
|
||||||
: ''
|
: ''
|
||||||
)
|
)
|
||||||
const loading = computed(
|
const loading = computed(
|
||||||
|
@ -23,6 +23,22 @@
|
|||||||
@updateTimezone="updateTZ"
|
@updateTimezone="updateTZ"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
<label class="form-items">
|
||||||
|
{{ $t('user.PROFILE.DATE_FORMAT') }}
|
||||||
|
<select
|
||||||
|
id="date_format"
|
||||||
|
v-model="userForm.date_format"
|
||||||
|
:disabled="loading"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
v-for="dateFormat in dateFormatOptions"
|
||||||
|
:value="dateFormat.value"
|
||||||
|
:key="dateFormat.value"
|
||||||
|
>
|
||||||
|
{{ dateFormat.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
<div class="form-items form-checkboxes">
|
<div class="form-items form-checkboxes">
|
||||||
<span class="checkboxes-label">
|
<span class="checkboxes-label">
|
||||||
{{ $t('user.PROFILE.FIRST_DAY_OF_WEEK') }}
|
{{ $t('user.PROFILE.FIRST_DAY_OF_WEEK') }}
|
||||||
@ -106,6 +122,7 @@
|
|||||||
import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'
|
import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'
|
||||||
import { IUserPreferencesPayload, IAuthUserProfile } from '@/types/user'
|
import { IUserPreferencesPayload, IAuthUserProfile } from '@/types/user'
|
||||||
import { useStore } from '@/use/useStore'
|
import { useStore } from '@/use/useStore'
|
||||||
|
import { availableDateFormatOptions } from '@/utils/dates'
|
||||||
import { availableLanguages } from '@/utils/locales'
|
import { availableLanguages } from '@/utils/locales'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -120,6 +137,7 @@
|
|||||||
imperial_units: false,
|
imperial_units: false,
|
||||||
language: '',
|
language: '',
|
||||||
timezone: 'Europe/Paris',
|
timezone: 'Europe/Paris',
|
||||||
|
date_format: 'dd/MM/yyyy',
|
||||||
weekm: false,
|
weekm: false,
|
||||||
})
|
})
|
||||||
const weekStart = [
|
const weekStart = [
|
||||||
@ -158,6 +176,13 @@
|
|||||||
const errorMessages: ComputedRef<string | string[] | null> = computed(
|
const errorMessages: ComputedRef<string | string[] | null> = computed(
|
||||||
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
|
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
|
||||||
)
|
)
|
||||||
|
const dateFormatOptions = computed(() =>
|
||||||
|
availableDateFormatOptions(
|
||||||
|
new Date().toUTCString(),
|
||||||
|
props.user.timezone,
|
||||||
|
userForm.language
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.user) {
|
if (props.user) {
|
||||||
@ -170,6 +195,7 @@
|
|||||||
userForm.imperial_units = user.imperial_units ? user.imperial_units : false
|
userForm.imperial_units = user.imperial_units ? user.imperial_units : false
|
||||||
userForm.language = user.language ? user.language : 'en'
|
userForm.language = user.language ? user.language : 'en'
|
||||||
userForm.timezone = user.timezone ? user.timezone : 'Europe/Paris'
|
userForm.timezone = user.timezone ? user.timezone : 'Europe/Paris'
|
||||||
|
userForm.date_format = user.date_format ? user.date_format : 'dd/MM/yyyy'
|
||||||
userForm.weekm = user.weekm ? user.weekm : false
|
userForm.weekm = user.weekm ? user.weekm : false
|
||||||
}
|
}
|
||||||
function updateProfile() {
|
function updateProfile() {
|
||||||
|
@ -50,9 +50,10 @@
|
|||||||
<dt>{{ capitalize($t('oauth2.APP.ISSUE_AT')) }}:</dt>
|
<dt>{{ capitalize($t('oauth2.APP.ISSUE_AT')) }}:</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{{
|
{{
|
||||||
format(
|
formatDate(
|
||||||
getDateWithTZ(client.issued_at, authUser.timezone),
|
client.issued_at,
|
||||||
'dd/MM/yyyy HH:mm'
|
authUser.timezone,
|
||||||
|
authUser.date_format
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</dd>
|
</dd>
|
||||||
@ -105,7 +106,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { format } from 'date-fns'
|
|
||||||
import {
|
import {
|
||||||
ComputedRef,
|
ComputedRef,
|
||||||
Ref,
|
Ref,
|
||||||
@ -124,7 +124,7 @@
|
|||||||
import { IOAuth2Client } from '@/types/oauth'
|
import { IOAuth2Client } from '@/types/oauth'
|
||||||
import { IAuthUserProfile } from '@/types/user'
|
import { IAuthUserProfile } from '@/types/user'
|
||||||
import { useStore } from '@/use/useStore'
|
import { useStore } from '@/use/useStore'
|
||||||
import { getDateWithTZ } from '@/utils/dates'
|
import { formatDate } from '@/utils/dates'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
authUser: IAuthUserProfile
|
authUser: IAuthUserProfile
|
||||||
|
@ -9,9 +9,10 @@
|
|||||||
<span class="app-issued-at">
|
<span class="app-issued-at">
|
||||||
{{ $t('oauth2.APP.ISSUE_AT') }}
|
{{ $t('oauth2.APP.ISSUE_AT') }}
|
||||||
{{
|
{{
|
||||||
format(
|
formatDate(
|
||||||
getDateWithTZ(client.issued_at, authUser.timezone),
|
client.issued_at,
|
||||||
'dd/MM/yyyy HH:mm'
|
authUser.timezone,
|
||||||
|
authUser.date_format
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
@ -34,7 +35,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { format } from 'date-fns'
|
|
||||||
import { ComputedRef, computed, onBeforeMount, toRefs, watch } from 'vue'
|
import { ComputedRef, computed, onBeforeMount, toRefs, watch } from 'vue'
|
||||||
import { LocationQuery, useRoute } from 'vue-router'
|
import { LocationQuery, useRoute } from 'vue-router'
|
||||||
|
|
||||||
@ -45,7 +45,7 @@
|
|||||||
import { IAuthUserProfile } from '@/types/user'
|
import { IAuthUserProfile } from '@/types/user'
|
||||||
import { useStore } from '@/use/useStore'
|
import { useStore } from '@/use/useStore'
|
||||||
import { defaultPage, getNumberQueryValue } from '@/utils/api'
|
import { defaultPage, getNumberQueryValue } from '@/utils/api'
|
||||||
import { getDateWithTZ } from '@/utils/dates'
|
import { formatDate } from '@/utils/dates'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
authUser: IAuthUserProfile
|
authUser: IAuthUserProfile
|
||||||
|
@ -29,10 +29,7 @@
|
|||||||
class="workout-date"
|
class="workout-date"
|
||||||
v-if="workout.workout_date && user"
|
v-if="workout.workout_date && user"
|
||||||
:title="
|
:title="
|
||||||
format(
|
formatDate(workout.workout_date, user.timezone, user.date_format)
|
||||||
getDateWithTZ(workout.workout_date, user.timezone),
|
|
||||||
'dd/MM/yyyy HH:mm'
|
|
||||||
)
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{
|
{{
|
||||||
@ -141,7 +138,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Locale, format, formatDistance } from 'date-fns'
|
import { Locale, formatDistance } from 'date-fns'
|
||||||
import { ComputedRef, computed, toRefs, withDefaults } from 'vue'
|
import { ComputedRef, computed, toRefs, withDefaults } from 'vue'
|
||||||
|
|
||||||
import StaticMap from '@/components/Common/StaticMap.vue'
|
import StaticMap from '@/components/Common/StaticMap.vue'
|
||||||
@ -151,7 +148,7 @@
|
|||||||
import { IUserProfile } from '@/types/user'
|
import { IUserProfile } from '@/types/user'
|
||||||
import { IWorkout } from '@/types/workouts'
|
import { IWorkout } from '@/types/workouts'
|
||||||
import { useStore } from '@/use/useStore'
|
import { useStore } from '@/use/useStore'
|
||||||
import { getDateWithTZ } from '@/utils/dates'
|
import { formatDate } from '@/utils/dates'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
user: IUserProfile
|
user: IUserProfile
|
||||||
|
@ -131,7 +131,8 @@
|
|||||||
getDateWithTZ(
|
getDateWithTZ(
|
||||||
props.workoutData.workout.workout_date,
|
props.workoutData.workout.workout_date,
|
||||||
props.authUser.timezone
|
props.authUser.timezone
|
||||||
)
|
),
|
||||||
|
props.authUser.date_format
|
||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
ascent: segment ? segment.ascent : workout.ascent,
|
ascent: segment ? segment.ascent : workout.ascent,
|
||||||
|
@ -84,9 +84,10 @@
|
|||||||
{{ $t('workouts.DATE') }}
|
{{ $t('workouts.DATE') }}
|
||||||
</span>
|
</span>
|
||||||
{{
|
{{
|
||||||
format(
|
formatDate(
|
||||||
getDateWithTZ(workout.workout_date, user.timezone),
|
workout.workout_date,
|
||||||
'dd/MM/yyyy HH:mm'
|
user.timezone,
|
||||||
|
user.date_format
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</td>
|
</td>
|
||||||
@ -162,7 +163,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { format } from 'date-fns'
|
|
||||||
import {
|
import {
|
||||||
ComputedRef,
|
ComputedRef,
|
||||||
Ref,
|
Ref,
|
||||||
@ -186,7 +186,7 @@
|
|||||||
import { IWorkout, TWorkoutsPayload } from '@/types/workouts'
|
import { IWorkout, TWorkoutsPayload } from '@/types/workouts'
|
||||||
import { useStore } from '@/use/useStore'
|
import { useStore } from '@/use/useStore'
|
||||||
import { getQuery, sortList, workoutsPayloadKeys } from '@/utils/api'
|
import { getQuery, sortList, workoutsPayloadKeys } from '@/utils/api'
|
||||||
import { getDateWithTZ } from '@/utils/dates'
|
import { formatDate } from '@/utils/dates'
|
||||||
import { getSportColor, getSportLabel } from '@/utils/sports'
|
import { getSportColor, getSportLabel } from '@/utils/sports'
|
||||||
import { convertDistance } from '@/utils/units'
|
import { convertDistance } from '@/utils/units'
|
||||||
import { defaultOrder } from '@/utils/workouts'
|
import { defaultOrder } from '@/utils/workouts'
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
"BACK_TO_PROFILE": "Zurück zum Profil",
|
"BACK_TO_PROFILE": "Zurück zum Profil",
|
||||||
"BIO": "Biographie",
|
"BIO": "Biographie",
|
||||||
"BIRTH_DATE": "Geburtsdatum",
|
"BIRTH_DATE": "Geburtsdatum",
|
||||||
|
"DATE_FORMAT": "Datumsanzeigeformat",
|
||||||
"EDIT": "Profil bearbeiten",
|
"EDIT": "Profil bearbeiten",
|
||||||
"EDIT_PREFERENCES": "Einstellungen ändern",
|
"EDIT_PREFERENCES": "Einstellungen ändern",
|
||||||
"EDIT_SPORTS_PREFERENCES": "Einstellungen für Sportarten ändern",
|
"EDIT_SPORTS_PREFERENCES": "Einstellungen für Sportarten ändern",
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
"BACK_TO_PROFILE": "Back to profile",
|
"BACK_TO_PROFILE": "Back to profile",
|
||||||
"BIO": "Bio",
|
"BIO": "Bio",
|
||||||
"BIRTH_DATE": "Birth date",
|
"BIRTH_DATE": "Birth date",
|
||||||
|
"DATE_FORMAT": "Date display format",
|
||||||
"EDIT": "Edit profile",
|
"EDIT": "Edit profile",
|
||||||
"EDIT_PREFERENCES": "Edit preferences",
|
"EDIT_PREFERENCES": "Edit preferences",
|
||||||
"EDIT_SPORTS_PREFERENCES": "Edit sports preferences",
|
"EDIT_SPORTS_PREFERENCES": "Edit sports preferences",
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
"BACK_TO_PROFILE": "Revenir au profil",
|
"BACK_TO_PROFILE": "Revenir au profil",
|
||||||
"BIO": "Bio",
|
"BIO": "Bio",
|
||||||
"BIRTH_DATE": "Date de naissance",
|
"BIRTH_DATE": "Date de naissance",
|
||||||
|
"DATE_FORMAT": "Format d'affichage de la date",
|
||||||
"EDIT": "Modifier le profil",
|
"EDIT": "Modifier le profil",
|
||||||
"EDIT_PREFERENCES": "Modifier les préférences",
|
"EDIT_PREFERENCES": "Modifier les préférences",
|
||||||
"EDIT_SPORTS_PREFERENCES": "Modifier les préférences des sports",
|
"EDIT_SPORTS_PREFERENCES": "Modifier les préférences des sports",
|
||||||
|
@ -29,6 +29,7 @@ export interface IAuthUserProfile extends IUserProfile {
|
|||||||
imperial_units: boolean
|
imperial_units: boolean
|
||||||
language: string | null
|
language: string | null
|
||||||
timezone: string
|
timezone: string
|
||||||
|
date_format: string
|
||||||
weekm: boolean
|
weekm: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ export interface IUserPreferencesPayload {
|
|||||||
imperial_units: boolean
|
imperial_units: boolean
|
||||||
language: string
|
language: string
|
||||||
timezone: string
|
timezone: string
|
||||||
|
date_format: string
|
||||||
weekm: boolean
|
weekm: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,11 @@ import {
|
|||||||
} from 'date-fns'
|
} from 'date-fns'
|
||||||
import { utcToZonedTime } from 'date-fns-tz'
|
import { utcToZonedTime } from 'date-fns-tz'
|
||||||
|
|
||||||
|
import createI18n from '@/i18n'
|
||||||
|
import { localeFromLanguage } from '@/utils/locales'
|
||||||
|
|
||||||
|
const { locale } = createI18n.global
|
||||||
|
|
||||||
export const getStartDate = (
|
export const getStartDate = (
|
||||||
duration: string,
|
duration: string,
|
||||||
day: Date,
|
day: Date,
|
||||||
@ -70,11 +75,70 @@ export const formatWorkoutDate = (
|
|||||||
if (!dateFormat) {
|
if (!dateFormat) {
|
||||||
dateFormat = 'yyyy/MM/dd'
|
dateFormat = 'yyyy/MM/dd'
|
||||||
}
|
}
|
||||||
|
dateFormat = getDateFormat(dateFormat, locale.value)
|
||||||
if (!timeFormat) {
|
if (!timeFormat) {
|
||||||
timeFormat = 'HH:mm'
|
timeFormat = 'HH:mm'
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
workout_date: format(dateTime, dateFormat),
|
workout_date: format(dateTime, dateFormat, {
|
||||||
|
locale: localeFromLanguage[locale.value],
|
||||||
|
}),
|
||||||
workout_time: format(dateTime, timeFormat),
|
workout_time: format(dateTime, timeFormat),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const availableDateFormats = [
|
||||||
|
'MM/dd/yyyy',
|
||||||
|
'dd/MM/yyyy',
|
||||||
|
'yyyy-MM-dd',
|
||||||
|
'date_string',
|
||||||
|
]
|
||||||
|
const dateStringFormats: Record<string, string> = {
|
||||||
|
de: 'do MMM yyyy',
|
||||||
|
en: 'MMM. do, yyyy',
|
||||||
|
fr: 'd MMM yyyy',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getDateFormat = (dateFormat: string, language: string): string => {
|
||||||
|
return dateFormat === 'date_string' ? dateStringFormats[language] : dateFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
export const formatDate = (
|
||||||
|
dateString: string,
|
||||||
|
timezone: string,
|
||||||
|
dateFormat: string,
|
||||||
|
withTime = true,
|
||||||
|
language: string | null = null
|
||||||
|
): string => {
|
||||||
|
if (!language) {
|
||||||
|
language = locale.value
|
||||||
|
}
|
||||||
|
return format(
|
||||||
|
getDateWithTZ(dateString, timezone),
|
||||||
|
`${getDateFormat(dateFormat, language)}${withTime ? ' HH:mm' : ''}`,
|
||||||
|
{ locale: localeFromLanguage[language] }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const availableDateFormatOptions = (
|
||||||
|
inputDate: string,
|
||||||
|
timezone: string,
|
||||||
|
language: string | null = null
|
||||||
|
) => {
|
||||||
|
const l: string = language ? language : locale.value
|
||||||
|
const options: Record<string, string>[] = []
|
||||||
|
availableDateFormats.map((df) => {
|
||||||
|
const dateFormat = getDateFormat(df, l)
|
||||||
|
options.push({
|
||||||
|
label: `${dateFormat} - ${formatDate(
|
||||||
|
inputDate,
|
||||||
|
timezone,
|
||||||
|
dateFormat,
|
||||||
|
false,
|
||||||
|
l
|
||||||
|
)}`,
|
||||||
|
value: df,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
|
import createI18n from '@/i18n'
|
||||||
import { ITranslatedSport } from '@/types/sports'
|
import { ITranslatedSport } from '@/types/sports'
|
||||||
import { TUnit } from '@/types/units'
|
import { TUnit } from '@/types/units'
|
||||||
import { ICardRecord, IRecord, IRecordsBySports } from '@/types/workouts'
|
import { ICardRecord, IRecord, IRecordsBySports } from '@/types/workouts'
|
||||||
import { formatWorkoutDate, getDateWithTZ } from '@/utils/dates'
|
import { formatDate, getDateFormat } from '@/utils/dates'
|
||||||
import { convertDistance, units } from '@/utils/units'
|
import { convertDistance, units } from '@/utils/units'
|
||||||
|
|
||||||
|
const { locale } = createI18n.global
|
||||||
|
|
||||||
export const formatRecord = (
|
export const formatRecord = (
|
||||||
record: IRecord,
|
record: IRecord,
|
||||||
tz: string,
|
tz: string,
|
||||||
useImperialUnits: boolean
|
useImperialUnits: boolean,
|
||||||
|
date_format: string
|
||||||
): Record<string, string | number> => {
|
): Record<string, string | number> => {
|
||||||
const distanceUnitFrom: TUnit = 'km'
|
const distanceUnitFrom: TUnit = 'km'
|
||||||
const distanceUnitTo: TUnit = useImperialUnits
|
const distanceUnitTo: TUnit = useImperialUnits
|
||||||
@ -53,8 +57,7 @@ export const formatRecord = (
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
workout_date: formatWorkoutDate(getDateWithTZ(record.workout_date, tz))
|
workout_date: formatDate(record.workout_date, tz, date_format, false),
|
||||||
.workout_date,
|
|
||||||
workout_id: record.workout_id,
|
workout_id: record.workout_id,
|
||||||
id: record.id,
|
id: record.id,
|
||||||
record_type: record.record_type,
|
record_type: record.record_type,
|
||||||
@ -73,9 +76,11 @@ export const getRecordsBySports = (
|
|||||||
translatedSports: ITranslatedSport[],
|
translatedSports: ITranslatedSport[],
|
||||||
tz: string,
|
tz: string,
|
||||||
useImperialUnits: boolean,
|
useImperialUnits: boolean,
|
||||||
display_ascent: boolean
|
display_ascent: boolean,
|
||||||
): IRecordsBySports =>
|
date_format: string
|
||||||
records
|
): IRecordsBySports => {
|
||||||
|
date_format = getDateFormat(date_format, locale.value)
|
||||||
|
return records
|
||||||
.filter((r) => (display_ascent ? true : r.record_type !== 'HA'))
|
.filter((r) => (display_ascent ? true : r.record_type !== 'HA'))
|
||||||
.reduce((sportList: IRecordsBySports, record) => {
|
.reduce((sportList: IRecordsBySports, record) => {
|
||||||
const sport = translatedSports.find((s) => s.id === record.sport_id)
|
const sport = translatedSports.find((s) => s.id === record.sport_id)
|
||||||
@ -88,8 +93,9 @@ export const getRecordsBySports = (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sportList[sport.translatedLabel].records.push(
|
sportList[sport.translatedLabel].records.push(
|
||||||
formatRecord(record, tz, useImperialUnits)
|
formatRecord(record, tz, useImperialUnits, date_format)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return sportList
|
return sportList
|
||||||
}, {})
|
}, {})
|
||||||
|
}
|
||||||
|
@ -5,6 +5,9 @@ import {
|
|||||||
incrementDate,
|
incrementDate,
|
||||||
getStartDate,
|
getStartDate,
|
||||||
formatWorkoutDate,
|
formatWorkoutDate,
|
||||||
|
formatDate,
|
||||||
|
availableDateFormatOptions,
|
||||||
|
getDateFormat,
|
||||||
} from '@/utils/dates'
|
} from '@/utils/dates'
|
||||||
|
|
||||||
describe('startDate (week starting Sunday)', () => {
|
describe('startDate (week starting Sunday)', () => {
|
||||||
@ -240,3 +243,158 @@ describe('formatWorkoutDate', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('formatDate', () => {
|
||||||
|
const dateString = 'Tue, 01 Nov 2022 00:00:00 GMT'
|
||||||
|
|
||||||
|
const testsParams = [
|
||||||
|
{
|
||||||
|
description:
|
||||||
|
'format date for "Europe/Paris" timezone and "dd/MM/yyyy" format (with time)',
|
||||||
|
inputParams: {
|
||||||
|
timezone: 'Europe/Paris',
|
||||||
|
dateFormat: 'dd/MM/yyyy',
|
||||||
|
withTime: true,
|
||||||
|
},
|
||||||
|
expectedDate: '01/11/2022 01:00',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description:
|
||||||
|
'format date for "America/New_York" timezone and "MM/dd/yyyy" format (w/o time)',
|
||||||
|
inputParams: {
|
||||||
|
timezone: 'America/New_York',
|
||||||
|
dateFormat: 'MM/dd/yyyy',
|
||||||
|
withTime: false,
|
||||||
|
},
|
||||||
|
expectedDate: '10/31/2022',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
testsParams.map((testParams) => {
|
||||||
|
it(testParams.description, () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
formatDate(
|
||||||
|
dateString,
|
||||||
|
testParams.inputParams.timezone,
|
||||||
|
testParams.inputParams.dateFormat,
|
||||||
|
testParams.inputParams.withTime
|
||||||
|
),
|
||||||
|
testParams.expectedDate
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('formatDate (w/ default value)', () => {
|
||||||
|
it('format date for "Europe/Paris" timezone and "dd/MM/yyyy" format', () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
formatDate('Tue, 01 Nov 2022 00:00:00 GMT', 'Europe/Paris', 'yyyy-MM-dd'),
|
||||||
|
'2022-11-01 01:00'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('getDateFormat', () => {
|
||||||
|
const testsParams = [
|
||||||
|
{
|
||||||
|
inputParams: {
|
||||||
|
dateFormat: 'dd/MM/yyyy',
|
||||||
|
language: 'en',
|
||||||
|
},
|
||||||
|
expectedFormat: 'dd/MM/yyyy',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputParams: {
|
||||||
|
dateFormat: 'MM/dd/yyyy',
|
||||||
|
language: 'en',
|
||||||
|
},
|
||||||
|
expectedFormat: 'MM/dd/yyyy',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputParams: {
|
||||||
|
dateFormat: 'yyyy-MM-dd',
|
||||||
|
language: 'en',
|
||||||
|
},
|
||||||
|
expectedFormat: 'yyyy-MM-dd',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputParams: {
|
||||||
|
dateFormat: 'date_string',
|
||||||
|
language: 'en',
|
||||||
|
},
|
||||||
|
expectedFormat: 'MMM. do, yyyy',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputParams: {
|
||||||
|
dateFormat: 'date_string',
|
||||||
|
language: 'fr',
|
||||||
|
},
|
||||||
|
expectedFormat: 'd MMM yyyy',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputParams: {
|
||||||
|
dateFormat: 'date_string',
|
||||||
|
language: 'de',
|
||||||
|
},
|
||||||
|
expectedFormat: 'do MMM yyyy',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
testsParams.map((testParams) => {
|
||||||
|
it(`get date format for "${testParams.inputParams.language}" and "${testParams.inputParams.dateFormat}" `, () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
getDateFormat(
|
||||||
|
testParams.inputParams.dateFormat,
|
||||||
|
testParams.inputParams.language
|
||||||
|
),
|
||||||
|
testParams.expectedFormat
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('availableDateFormatOptions', () => {
|
||||||
|
const inputDate = `Sun, 9 Oct 2022 18:18:41 GMT`
|
||||||
|
const inputTimezone = `Europe/Paris`
|
||||||
|
|
||||||
|
const testsParams = [
|
||||||
|
{
|
||||||
|
inputLanguage: 'en',
|
||||||
|
expectedOptions: [
|
||||||
|
{ label: 'MM/dd/yyyy - 10/09/2022', value: 'MM/dd/yyyy' },
|
||||||
|
{ label: 'dd/MM/yyyy - 09/10/2022', value: 'dd/MM/yyyy' },
|
||||||
|
{ label: 'yyyy-MM-dd - 2022-10-09', value: 'yyyy-MM-dd' },
|
||||||
|
{ label: 'MMM. do, yyyy - Oct. 9th, 2022', value: 'date_string' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLanguage: 'fr',
|
||||||
|
expectedOptions: [
|
||||||
|
{ label: 'MM/dd/yyyy - 10/09/2022', value: 'MM/dd/yyyy' },
|
||||||
|
{ label: 'dd/MM/yyyy - 09/10/2022', value: 'dd/MM/yyyy' },
|
||||||
|
{ label: 'yyyy-MM-dd - 2022-10-09', value: 'yyyy-MM-dd' },
|
||||||
|
{ label: 'd MMM yyyy - 9 oct. 2022', value: 'date_string' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputLanguage: 'de',
|
||||||
|
expectedOptions: [
|
||||||
|
{ label: 'MM/dd/yyyy - 10/09/2022', value: 'MM/dd/yyyy' },
|
||||||
|
{ label: 'dd/MM/yyyy - 09/10/2022', value: 'dd/MM/yyyy' },
|
||||||
|
{ label: 'yyyy-MM-dd - 2022-10-09', value: 'yyyy-MM-dd' },
|
||||||
|
{ label: 'do MMM yyyy - 9. Okt. 2022', value: 'date_string' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
testsParams.map((testParams) => {
|
||||||
|
it(`returns available options for ${testParams.inputLanguage} locale`, () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
availableDateFormatOptions(
|
||||||
|
inputDate,
|
||||||
|
inputTimezone,
|
||||||
|
testParams.inputLanguage
|
||||||
|
),
|
||||||
|
testParams.expectedOptions
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
@ -19,6 +19,7 @@ describe('formatRecord', () => {
|
|||||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||||
},
|
},
|
||||||
timezone: 'Europe/Paris',
|
timezone: 'Europe/Paris',
|
||||||
|
date_format: 'yyyy/dd/MM'
|
||||||
},
|
},
|
||||||
expected: {
|
expected: {
|
||||||
id: 9,
|
id: 9,
|
||||||
@ -41,6 +42,7 @@ describe('formatRecord', () => {
|
|||||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||||
},
|
},
|
||||||
timezone: 'Europe/Paris',
|
timezone: 'Europe/Paris',
|
||||||
|
date_format: 'yyyy/MM/dd'
|
||||||
},
|
},
|
||||||
expected: {
|
expected: {
|
||||||
id: 10,
|
id: 10,
|
||||||
@ -63,6 +65,7 @@ describe('formatRecord', () => {
|
|||||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||||
},
|
},
|
||||||
timezone: 'Europe/Paris',
|
timezone: 'Europe/Paris',
|
||||||
|
date_format: 'yyyy/MM/dd'
|
||||||
},
|
},
|
||||||
expected: {
|
expected: {
|
||||||
id: 11,
|
id: 11,
|
||||||
@ -85,12 +88,13 @@ describe('formatRecord', () => {
|
|||||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||||
},
|
},
|
||||||
timezone: 'Europe/Paris',
|
timezone: 'Europe/Paris',
|
||||||
|
date_format: 'dd/MM/yyyy'
|
||||||
},
|
},
|
||||||
expected: {
|
expected: {
|
||||||
id: 12,
|
id: 12,
|
||||||
record_type: 'MS',
|
record_type: 'MS',
|
||||||
value: '18 km/h',
|
value: '18 km/h',
|
||||||
workout_date: '2019/07/08',
|
workout_date: '08/07/2019',
|
||||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -107,12 +111,13 @@ describe('formatRecord', () => {
|
|||||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||||
},
|
},
|
||||||
timezone: 'Europe/Paris',
|
timezone: 'Europe/Paris',
|
||||||
|
date_format: 'MMM. do, yyyy'
|
||||||
},
|
},
|
||||||
expected: {
|
expected: {
|
||||||
id: 13,
|
id: 13,
|
||||||
record_type: 'HA',
|
record_type: 'HA',
|
||||||
value: '100 m',
|
value: '100 m',
|
||||||
workout_date: '2019/07/07',
|
workout_date: 'Jul. 7th, 2019',
|
||||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -123,7 +128,8 @@ describe('formatRecord', () => {
|
|||||||
formatRecord(
|
formatRecord(
|
||||||
testParams.inputParams.record,
|
testParams.inputParams.record,
|
||||||
testParams.inputParams.timezone,
|
testParams.inputParams.timezone,
|
||||||
false
|
false,
|
||||||
|
testParams.inputParams.date_format
|
||||||
),
|
),
|
||||||
testParams.expected
|
testParams.expected
|
||||||
)
|
)
|
||||||
@ -146,6 +152,7 @@ describe('formatRecord after conversion', () => {
|
|||||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||||
},
|
},
|
||||||
timezone: 'Europe/Paris',
|
timezone: 'Europe/Paris',
|
||||||
|
date_format: 'yyyy/dd/MM'
|
||||||
},
|
},
|
||||||
expected: {
|
expected: {
|
||||||
id: 9,
|
id: 9,
|
||||||
@ -168,12 +175,13 @@ describe('formatRecord after conversion', () => {
|
|||||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||||
},
|
},
|
||||||
timezone: 'Europe/Paris',
|
timezone: 'Europe/Paris',
|
||||||
|
date_format: 'yyyy/dd/MM'
|
||||||
},
|
},
|
||||||
expected: {
|
expected: {
|
||||||
id: 10,
|
id: 10,
|
||||||
record_type: 'FD',
|
record_type: 'FD',
|
||||||
value: '11.185 mi',
|
value: '11.185 mi',
|
||||||
workout_date: '2019/07/08',
|
workout_date: '2019/08/07',
|
||||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -190,6 +198,7 @@ describe('formatRecord after conversion', () => {
|
|||||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||||
},
|
},
|
||||||
timezone: 'Europe/Paris',
|
timezone: 'Europe/Paris',
|
||||||
|
date_format: 'yyyy/dd/MM'
|
||||||
},
|
},
|
||||||
expected: {
|
expected: {
|
||||||
id: 11,
|
id: 11,
|
||||||
@ -212,12 +221,13 @@ describe('formatRecord after conversion', () => {
|
|||||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||||
},
|
},
|
||||||
timezone: 'Europe/Paris',
|
timezone: 'Europe/Paris',
|
||||||
|
date_format: 'yyyy/dd/MM'
|
||||||
},
|
},
|
||||||
expected: {
|
expected: {
|
||||||
id: 12,
|
id: 12,
|
||||||
record_type: 'MS',
|
record_type: 'MS',
|
||||||
value: '11.18 mi/h',
|
value: '11.18 mi/h',
|
||||||
workout_date: '2019/07/08',
|
workout_date: '2019/08/07',
|
||||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -234,6 +244,7 @@ describe('formatRecord after conversion', () => {
|
|||||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||||
},
|
},
|
||||||
timezone: 'Europe/Paris',
|
timezone: 'Europe/Paris',
|
||||||
|
date_format: 'yyyy/dd/MM'
|
||||||
},
|
},
|
||||||
expected: {
|
expected: {
|
||||||
id: 13,
|
id: 13,
|
||||||
@ -250,7 +261,8 @@ describe('formatRecord after conversion', () => {
|
|||||||
formatRecord(
|
formatRecord(
|
||||||
testParams.inputParams.record,
|
testParams.inputParams.record,
|
||||||
testParams.inputParams.timezone,
|
testParams.inputParams.timezone,
|
||||||
true
|
true,
|
||||||
|
testParams.inputParams.date_format
|
||||||
),
|
),
|
||||||
testParams.expected
|
testParams.expected
|
||||||
)
|
)
|
||||||
@ -272,7 +284,8 @@ describe('formatRecord (invalid record type)', () => {
|
|||||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||||
},
|
},
|
||||||
'Europe/Paris',
|
'Europe/Paris',
|
||||||
false
|
false,
|
||||||
|
'yyyy/dd/MM'
|
||||||
)
|
)
|
||||||
).to.throw(
|
).to.throw(
|
||||||
'Invalid record type, expected: "AS", "FD", "HA", "LD", "MD", got: "M"'
|
'Invalid record type, expected: "AS", "FD", "HA", "LD", "MD", got: "M"'
|
||||||
@ -287,6 +300,7 @@ describe('getRecordsBySports', () => {
|
|||||||
input: {
|
input: {
|
||||||
records: [],
|
records: [],
|
||||||
tz: 'Europe/Paris',
|
tz: 'Europe/Paris',
|
||||||
|
date_format: 'yyyy/dd/MM'
|
||||||
},
|
},
|
||||||
expected: {},
|
expected: {},
|
||||||
},
|
},
|
||||||
@ -305,6 +319,7 @@ describe('getRecordsBySports', () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
tz: 'Europe/Paris',
|
tz: 'Europe/Paris',
|
||||||
|
date_format: 'yyyy/dd/MM'
|
||||||
},
|
},
|
||||||
expected: {
|
expected: {
|
||||||
'Cycling (Sport)': {
|
'Cycling (Sport)': {
|
||||||
@ -355,6 +370,7 @@ describe('getRecordsBySports', () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
tz: 'Europe/Paris',
|
tz: 'Europe/Paris',
|
||||||
|
date_format: 'yyyy/dd/MM'
|
||||||
},
|
},
|
||||||
expected: {
|
expected: {
|
||||||
'Cycling (Sport)': {
|
'Cycling (Sport)': {
|
||||||
@ -385,7 +401,7 @@ describe('getRecordsBySports', () => {
|
|||||||
id: 10,
|
id: 10,
|
||||||
record_type: 'FD',
|
record_type: 'FD',
|
||||||
value: '18 km',
|
value: '18 km',
|
||||||
workout_date: '2019/07/08',
|
workout_date: '2019/08/07',
|
||||||
workout_id: 'n6JcLPQt3QtZWFfiSnYm4C',
|
workout_id: 'n6JcLPQt3QtZWFfiSnYm4C',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -401,7 +417,8 @@ describe('getRecordsBySports', () => {
|
|||||||
translatedSports,
|
translatedSports,
|
||||||
testParams.input.tz,
|
testParams.input.tz,
|
||||||
false,
|
false,
|
||||||
true
|
true,
|
||||||
|
testParams.input.date_format
|
||||||
),
|
),
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@ -418,6 +435,7 @@ describe('getRecordsBySports after conversion', () => {
|
|||||||
input: {
|
input: {
|
||||||
records: [],
|
records: [],
|
||||||
tz: 'Europe/Paris',
|
tz: 'Europe/Paris',
|
||||||
|
date_format: 'yyyy/dd/MM'
|
||||||
},
|
},
|
||||||
expected: {},
|
expected: {},
|
||||||
},
|
},
|
||||||
@ -436,6 +454,7 @@ describe('getRecordsBySports after conversion', () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
tz: 'Europe/Paris',
|
tz: 'Europe/Paris',
|
||||||
|
date_format: 'yyyy/dd/MM'
|
||||||
},
|
},
|
||||||
expected: {
|
expected: {
|
||||||
'Cycling (Sport)': {
|
'Cycling (Sport)': {
|
||||||
@ -486,6 +505,7 @@ describe('getRecordsBySports after conversion', () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
tz: 'Europe/Paris',
|
tz: 'Europe/Paris',
|
||||||
|
date_format: 'yyyy/dd/MM'
|
||||||
},
|
},
|
||||||
expected: {
|
expected: {
|
||||||
'Cycling (Sport)': {
|
'Cycling (Sport)': {
|
||||||
@ -516,7 +536,7 @@ describe('getRecordsBySports after conversion', () => {
|
|||||||
id: 10,
|
id: 10,
|
||||||
record_type: 'FD',
|
record_type: 'FD',
|
||||||
value: '11.185 mi',
|
value: '11.185 mi',
|
||||||
workout_date: '2019/07/08',
|
workout_date: '2019/08/07',
|
||||||
workout_id: 'n6JcLPQt3QtZWFfiSnYm4C',
|
workout_id: 'n6JcLPQt3QtZWFfiSnYm4C',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -532,7 +552,8 @@ describe('getRecordsBySports after conversion', () => {
|
|||||||
translatedSports,
|
translatedSports,
|
||||||
testParams.input.tz,
|
testParams.input.tz,
|
||||||
true,
|
true,
|
||||||
true
|
true,
|
||||||
|
testParams.input.date_format
|
||||||
),
|
),
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@ -549,6 +570,7 @@ describe('getRecordsBySports with HA record', () => {
|
|||||||
input: {
|
input: {
|
||||||
records: [],
|
records: [],
|
||||||
tz: 'Europe/Paris',
|
tz: 'Europe/Paris',
|
||||||
|
date_format: 'yyyy/dd/MM'
|
||||||
},
|
},
|
||||||
expected: {},
|
expected: {},
|
||||||
},
|
},
|
||||||
@ -576,6 +598,7 @@ describe('getRecordsBySports with HA record', () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
tz: 'Europe/Paris',
|
tz: 'Europe/Paris',
|
||||||
|
date_format: 'yyyy/dd/MM'
|
||||||
},
|
},
|
||||||
expected: {
|
expected: {
|
||||||
'Cycling (Sport)': {
|
'Cycling (Sport)': {
|
||||||
@ -602,7 +625,8 @@ describe('getRecordsBySports with HA record', () => {
|
|||||||
translatedSports,
|
translatedSports,
|
||||||
testParams.input.tz,
|
testParams.input.tz,
|
||||||
false,
|
false,
|
||||||
false
|
false,
|
||||||
|
testParams.input.date_format
|
||||||
),
|
),
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
Loading…
x
Reference in New Issue
Block a user