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:
@@ -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
|
||||||
|
|||||||
Vendored
+1
-1
@@ -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>
|
||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -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
|
||||||
Vendored
+1
-1
@@ -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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-2
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
-2
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+2
-2
@@ -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
|
||||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -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
|
||||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+2
-2
File diff suppressed because one or more lines are too long
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
|
||||||
|
|||||||
Reference in New Issue
Block a user