Merge pull request #449 from SamR1/update-vue

Update vue and tooling
This commit is contained in:
Sam 2023-11-15 18:03:55 +01:00 committed by GitHub
commit 1ec6853106
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
410 changed files with 8148 additions and 12859 deletions

View File

@ -16,10 +16,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Use Node.js 17.x - name: Use Node.js 18.x
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: "17.x" node-version: "18.x"
- name: Install yarn and dependencies - name: Install yarn and dependencies
working-directory: ${{env.working-directory}} working-directory: ${{env.working-directory}}
run: | run: |
@ -28,6 +28,9 @@ jobs:
- name: Lint - name: Lint
working-directory: ${{env.working-directory}} working-directory: ${{env.working-directory}}
run: yarn lint run: yarn lint
- name: Type check
working-directory: ${{env.working-directory}}
run: yarn type-check
- name: Tests - name: Tests
working-directory: ${{env.working-directory}} working-directory: ${{env.working-directory}}
run: yarn test:unit run: yarn test:unit

View File

@ -24,9 +24,9 @@ bandit:
build-client: lint-client build-client: lint-client
cd fittrackee_client && $(NPM) build cd fittrackee_client && $(NPM) build
check-all: bandit lint-all type-check test-all check-all: bandit lint-all type-check-all test-all
check-client: lint-client test-client check-client: lint-client type-check-client test-client
check-python: bandit lint-python type-check test-python check-python: bandit lint-python type-check test-python
@ -98,7 +98,7 @@ docker-run-workers:
docker-serve-client: docker-serve-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 serve docker-compose -f docker-compose-dev.yml exec fittrackee_client yarn dev
docker-set-admin: docker-set-admin:
docker-compose -f docker-compose-dev.yml exec fittrackee docker/set-admin.sh $(USERNAME) docker-compose -f docker-compose-dev.yml exec fittrackee docker/set-admin.sh $(USERNAME)
@ -194,7 +194,7 @@ lint-client:
cd fittrackee_client && $(NPM) lint cd fittrackee_client && $(NPM) lint
lint-client-fix: lint-client-fix:
cd fittrackee_client && $(NPM) lint-fix cd fittrackee_client && $(NPM) format
lint-python: lint-python:
$(PYTEST) --isort --black -m "isort or black" fittrackee e2e --ignore=fittrackee/migrations $(PYTEST) --isort --black -m "isort or black" fittrackee e2e --ignore=fittrackee/migrations
@ -233,7 +233,7 @@ serve-dev:
serve-client: serve-client:
# for dev environments # for dev environments
cd fittrackee_client && PORT=3000 $(NPM) serve cd fittrackee_client && PORT=3000 $(NPM) dev
serve-python: serve-python:
# for dev environments # for dev environments
@ -263,12 +263,20 @@ test-python:
$(PYTEST) fittrackee --cov-config .coveragerc --cov=fittrackee --cov-report term-missing $(PYTEST_ARGS) $(PYTEST) fittrackee --cov-config .coveragerc --cov=fittrackee --cov-report term-missing $(PYTEST_ARGS)
test-client: test-client:
cd fittrackee_client && $(NPM) test:unit $(MOCHA_ARGS) cd fittrackee_client && $(NPM) test:unit run
test-client-watch:
cd fittrackee_client && $(NPM) test:unit watch
type-check: type-check:
echo 'Running mypy...' echo 'Running mypy...'
$(MYPY) fittrackee $(MYPY) fittrackee
type-check-all: type-check-client type-check
type-check-client:
cd fittrackee_client && $(NPM) type-check
upgrade-db: upgrade-db:
$(FTCLI) db upgrade $(FTCLI) db upgrade

View File

@ -36,7 +36,7 @@ services:
container_name: fittrackee_client container_name: fittrackee_client
environment: environment:
- NODE_ENV=development - NODE_ENV=development
- VUE_APP_API_URL=http://localhost:5000 - VITE_APP_API_URL=http://localhost:5000
build: build:
context: ./fittrackee_client context: ./fittrackee_client
volumes: volumes:

View File

@ -29,7 +29,7 @@ Prerequisites
- SMTP provider (if email sending is enabled) - SMTP provider (if email sending is enabled)
- API key from a `weather data provider <installation.html#weather-data>`__ - API key from a `weather data provider <installation.html#weather-data>`__
- `Poetry <https://poetry.eustace.io>`__ (for installation from sources only) - `Poetry <https://poetry.eustace.io>`__ (for installation from sources only)
- `Node <https://nodejs.org>`__ 16+ and `Yarn <https://yarnpkg.com>`__ (for development only) - `Node <https://nodejs.org>`__ 18+ and `Yarn <https://yarnpkg.com>`__ (for development only)
- Docker and Docker Compose (for development or evaluation purposes) - Docker and Docker Compose (for development or evaluation purposes)
.. note:: .. note::
@ -245,7 +245,9 @@ deployment method.
Provider for weather data (not mandatory), see `Weather data <installation.html#weather-data>`__. Provider for weather data (not mandatory), see `Weather data <installation.html#weather-data>`__.
.. envvar:: VUE_APP_API_URL .. envvar:: VITE_APP_API_URL
.. versionchanged:: 0.x.x ⚠️ replaces ``VUE_APP_API_URL``
**FitTrackee** API URL, only needed in dev environment. **FitTrackee** API URL, only needed in dev environment.
@ -818,7 +820,7 @@ Installation
.. versionadded:: 0.4.4 .. versionadded:: 0.4.4
For evaluation purposes, docker files are available, installing **FitTrackee** from **sources**. For **evaluation** purposes, docker files are available, installing **FitTrackee** from **sources**.
- To install **FitTrackee**: - To install **FitTrackee**:

View File

@ -1 +1,20 @@
<!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.6f625ccc.js"></script><script defer="defer" src="/static/js/app.6d1bd717.js"></script><link href="/static/css/app.a587cef2.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">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/static/css/fork-awesome.min.css"/>
<link rel="stylesheet" href="/static/css/leaflet.css"/>
<title>FitTrackee</title>
<script type="module" crossorigin src="/static/index-51012998.js"></script>
<link rel="modulepreload" crossorigin href="/static/charts-ed4ceed1.js">
<link rel="modulepreload" crossorigin href="/static/maps-c37c70d1.js">
<link rel="stylesheet" href="/static/css/maps-69420918.css">
<link rel="stylesheet" href="/static/css/index-827feab5.css">
</head>
<body>
<div id="app"></div>
</body>
</html>

View File

@ -1 +0,0 @@
{"name":"fittrackee_client","short_name":"fittrackee_client","theme_color":"#4DBA87","icons":[{"src":"./img/icons/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"./img/icons/android-chrome-512x512.png","sizes":"512x512","type":"image/png"},{"src":"./img/icons/android-chrome-maskable-192x192.png","sizes":"192x192","type":"image/png","purpose":"maskable"},{"src":"./img/icons/android-chrome-maskable-512x512.png","sizes":"512x512","type":"image/png","purpose":"maskable"}],"start_url":".","display":"standalone","background_color":"#000000"}

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

View File

@ -1 +0,0 @@
#admin .admin-card[data-v-64629971]{width:100%}#admin .admin-card[data-v-64629971] .card .admin-form{display:flex;flex-direction:column}#admin .admin-card[data-v-64629971] .card .admin-form label{display:flex;align-items:center;justify-content:space-between;margin:10px 0;flex-wrap:wrap}#admin .admin-card[data-v-64629971] .card .admin-form label input{width:50%;font-size:.9em;margin-right:50px}@media screen and (max-width:1000px){#admin .admin-card[data-v-64629971] .card .admin-form label input{margin-right:0}}@media screen and (max-width:700px){#admin .admin-card[data-v-64629971] .card .admin-form label input{width:100%}}#admin .admin-card[data-v-64629971] .card .admin-form label input:disabled{-webkit-appearance:none;-moz-appearance:textfield;background-color:#fff;border-color:#fff;color:var(--app-color)}#admin .admin-card[data-v-64629971] .card .admin-form .form-buttons{display:flex;gap:10px;margin-bottom:10px}

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

View File

@ -1 +0,0 @@
#account-confirmation[data-v-785df978]{display:flex;flex-direction:column;align-items:center}#account-confirmation svg[data-v-785df978]{stroke:none;fill-rule:nonzero;fill:var(--app-color);filter:var(--svg-filter);width:100px}#account-confirmation .error-message[data-v-785df978]{font-size:1.1em;text-align:center;display:flex;flex-direction:column}@media screen and (max-width:1000px){#account-confirmation .error-message[data-v-785df978]{font-size:1em}}#email-update[data-v-8c2ec9ce]{display:flex;flex-direction:column;align-items:center}#email-update svg[data-v-8c2ec9ce]{stroke:none;fill-rule:nonzero;fill:var(--app-color);filter:var(--svg-filter);width:100px}#email-update .error-message[data-v-8c2ec9ce]{font-size:1.1em;text-align:center;display:flex;flex-direction:column}@media screen and (max-width:1000px){#email-update .error-message[data-v-8c2ec9ce]{font-size:1em}}#profile[data-v-641164f3]{padding:0 10px 40px}#profile[data-v-641164f3],#profile[data-v-641164f3] .profile-form{display:flex;flex-direction:column}#profile[data-v-641164f3] .profile-form hr{border-color:var(--card-border-color);border-width:1px 0 0 0}#profile[data-v-641164f3] .profile-form .form-items{display:flex;flex-direction:column}#profile[data-v-641164f3] .profile-form .form-items input{margin:5px 0}#profile[data-v-641164f3] .profile-form .form-items select{height:35px;padding:5px 0}#profile[data-v-641164f3] .profile-form .form-items ::v-deep(.custom-textarea) textarea{padding:5px}#profile[data-v-641164f3] .profile-form .form-items .form-item{display:flex;flex-direction:column;padding:10px}#profile[data-v-641164f3] .profile-form .form-items .birth-date{height:20px}#profile[data-v-641164f3] .profile-form .form-buttons{display:flex;margin-top:10px;padding:10px 0;gap:10px}#user[data-v-af7007f4]{margin:auto;width:700px}@media screen and (max-width:1000px){#user[data-v-af7007f4]{width:100%;margin:0 auto 50px auto}}

View File

@ -1 +0,0 @@
#account-confirmation-email[data-v-66aca424]{display:flex;flex-direction:column}#account-confirmation-email .email-sent[data-v-66aca424]{display:flex;flex-direction:column;align-items:center}#account-confirmation-email .email-sent svg[data-v-66aca424]{stroke:none;fill-rule:nonzero;fill:var(--app-color);filter:var(--svg-filter);width:100px}#account-confirmation-email .email-sent .email-sent-message[data-v-66aca424]{font-size:1.1em;text-align:center}@media screen and (max-width:1000px){#account-confirmation-email .email-sent .email-sent-message[data-v-66aca424]{font-size:1em}}#account-confirmation-email[data-v-66aca424] .card .card-content #user-auth-form{margin-top:0}#account-confirmation-email[data-v-66aca424] .card .card-content #user-auth-form #user-form{width:100%}#account-confirmation[data-v-35aad344]{display:flex}#account-confirmation .container[data-v-35aad344]{display:flex;justify-content:center;width:50%}@media screen and (max-width:700px){#account-confirmation .container[data-v-35aad344]{width:100%}}#password-action-done[data-v-eac78356]{display:flex;flex-direction:column;align-items:center}#password-action-done svg[data-v-eac78356]{stroke:none;fill-rule:nonzero;fill:var(--app-color);filter:var(--svg-filter);width:100px}#password-action-done .password-message[data-v-eac78356]{font-size:1.1em;text-align:center}@media screen and (max-width:1000px){#password-action-done .password-message[data-v-eac78356]{font-size:1em}}#password-reset-request[data-v-68377e44] .card .card-content #user-form{width:100%}#password-reset[data-v-a1cc55c4]{display:flex}#password-reset .container[data-v-a1cc55c4]{display:flex;justify-content:center;width:50%}@media screen and (max-width:700px){#password-reset .container[data-v-a1cc55c4]{width:100%}}

View File

@ -1 +0,0 @@
.chart-menu[data-v-361ef577]{display:flex;align-items:center}.chart-menu .chart-arrow[data-v-361ef577],.chart-menu .time-frames[data-v-361ef577]{flex-grow:1;text-align:center}.chart-menu .chart-arrow[data-v-361ef577]{cursor:pointer}.sports-menu{display:flex;flex-wrap:wrap;padding:10px}.sports-menu label{display:flex;align-items:center;font-size:.9em;font-weight:400;min-width:120px;padding:10px}@media screen and (max-width:1000px){.sports-menu label{min-width:100px}}@media screen and (max-width:500px){.sports-menu label{min-width:20px}.sports-menu label .sport-label{display:none}}.sports-menu .sport-img{padding:3px;width:20px;height:20px}#user-statistics.stats-disabled[data-v-742b02d0]{opacity:.3;pointer-events:none}#user-statistics[data-v-742b02d0] .chart-radio{justify-content:space-around;padding:30px 10px 10px 10px}#statistics[data-v-19ce09a2]{display:flex;width:100%}#statistics .container[data-v-19ce09a2]{display:flex;flex-direction:column;width:100%}

File diff suppressed because one or more lines are too long

View File

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

View File

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View File

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

448
fittrackee/dist/static/index-51012998.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[431],{6431:function(c){c.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAABSCAMAAAAhFXfZAAAC91BMVEVMaXEzeak2f7I4g7g3g7cua5gzeKg8hJo3grY4g7c3grU0gLI2frE0daAubJc2gbQwd6QzeKk2gLMtd5sxdKIua5g1frA2f7IydaM0e6w2fq41fK01eqo3grgubJgta5cxdKI1f7AydaQydaMxc6EubJgvbJkwcZ4ubZkwcJwubZgubJcydqUydKIxapgubJctbJcubZcubJcvbJYubJcvbZkubJctbJctbZcubJg2f7AubJcrbZcubJcubJcua5g3grY0fq8ubJcubJdEkdEwhsw6i88vhswuhcsuhMtBjMgthMsrg8srgss6is8qgcs8i9A9iMYtg8spgcoogMo7hcMngMonf8olfso4gr8kfck5iM8jfMk4iM8he8k1fro7itAgesk2hs8eecgzfLcofssdeMg0hc4cd8g2hcsxeLQbdsgZdcgxeLImfcszhM0vda4xgckzhM4xg84wf8Yxgs4udKsvfcQucqhUndROmdM1fK0wcZ8vb5w0eqpQm9MzeKhXoNVcpdYydKNWn9VZotVKltJFjsIwcJ1Rms9OlslLmtH///8+kc9epdYzd6dbo9VHkMM2f7FHmNBClM8ydqVcpNY9hro3gLM9hLczealQmcw3fa46f7A8gLMxc6I3eagyc6FIldJMl9JSnNRSntNNl9JPnNJFi75UnM9ZodVKksg8kM45jc09e6ZHltFBk883gbRBh7pDk9EwcaBzn784g7dKkcY2i81Om9M7j85Llc81is09g7Q4grY/j9A0eqxKmdFFltBEjcXf6fFImdBCiLxJl9FGlNFBi78yiMxVndEvbpo6js74+vx+psPP3+o/ks5HkcpGmNCjwdZCkNDM3ehYoNJEls+lxNkxh8xHks0+jdC1zd5Lg6r+/v/H2ufz9/o3jM3t8/edvdM/k89Th61OiLBSjbZklbaTt9BfptdjmL1AicBHj8hGk9FAgK1dkLNTjLRekrdClc/k7fM0icy0y9tgp9c4jc2NtM9Dlc8zicxeXZn3AAAAQ3RSTlMAHDdTb4yPA+LtnEQmC4L2EmHqB7XA0d0sr478x4/Yd5i1zOfyPkf1sLVq4Nh3FvjxopQ2/STNuFzUwFIwxKaejILpIBEV9wAABhVJREFUeF6s1NdyFEcYBeBeoQIhRAkLlRDGrhIgY3BJL8CVeKzuyXFzzjkn5ZxzzuScg3PO8cKzu70JkO0LfxdTU//pM9vTu7Xgf6KqOVTb9X7toRrVEfBf1HTVjZccrT/2by1VV928Yty9ZbVuucdz90frG8DBjl9pVApbOstvmMuvVgaNXSfAAd6pGxpy6yxf5ph43pS/4f3uoaGm2rdu72S9xzOvMymkZFq/ptDrk90mhW7e4zl7HLzhxGWPR20xmSxJ/VqldG5m9XhaVOA1DadsNh3Pu5L2N6QtPO/32JpqQBVVk20oy/Pi2s23WEvyfHbe1thadVQttvm7Llf65gGmXK67XtupyoM7HQhmXdLS8oGWJNeOJ3C5fG5XCEJnkez3/oFdsvgJ4l2ANZwhrJKk/7OSXa+3Vw2WJMlKnGkobouYk6T0TyX30klOUnTD9HJ5qpckL3EW/w4XF3Xd0FGywXUrstrclVsqz5Pd/sXFYyDnPdrLcQODmGOK47IZb4CmibmMn+MYRzFZ5jg33ZL/EJrWcszHmANy3ARBK/IXtciJy8VsitPSdE3uuHxzougojcUdr8/32atnz/ev3f/K5wtpxUTpcaI45zusVDpYtZi+jg0oU9b3x74h7+n9ABvYEZeKaVq0sh0AtLKsFtqNBdeT0MrSzwwlq9+x6xAO4tgOtSzbCjrNQQiNvQUbUEubvzBUeGw26yDCsRHCoLkTHDa7IdOLIThs/gHvChszh2CimE8peRs47cxANI0lYNB5y1DljpOF0IhzBDPOZnDOqYYbeGKECbPzWnXludPphw5c2YBq5zlwXphIbO4VDCZ0gnPfUO1TwZoYwAs2ExPCedAu9DAjfQUjzITQb3jNj0KG2Sgt6BHaQUdYzWz+XmBktOHwanXjaSTcwwziBcuMOtwBmqPrTOxFQR/DRKKPqyur0aiW6cULYsx6tBm0jXpR/AUWR6HRq9WVW6MRhIq5jLyjbaCTDCijyYJNpCajdyobP/eTw0iexBAKkJ3gA5KcQb2zBXsIBckn+xVv8jkZSaEFHE+jFEleAEfayRU0MouNoBmB/L50Ai/HSLIHxcrpCvnhSQAuakKp2C/YbCylJjXRVy/z3+Kv/RrNcCo+WUzlVEhzKffnTQnxeN9fWF88fiNCUdSTsaufaChKWInHeysygfpIqagoakW+vV20J8uyl6TyNKEZWV4oRSPyCkWpgOLSbkCObT8o2r6tlG58HQquf6O0v50tB7JM7F4EORd2dx/K0w/KHsVkLPaoYrwgP/y7krr3SSMA4zj+OBgmjYkxcdIJQyQRKgg2viX9Hddi9UBb29LrKR7CVVEEEXWojUkXNyfTNDE14W9gbHJNuhjDettN3ZvbOvdOqCD3Jp/9l+/wJE+9PkYGjx/fqkys3S2rMozM/o2106rfMUINo6hVqz+eu/hd1c4xTg0TAfy5kV+4UG6+IthHTU9woWmxuKNbTfuCSfovBCxq7EtHqvYL4Sm6F8GVxsSXHMQ07TOi1DKtZxjWaaIyi4CXWjxPccUw8WVbMYY5wxC1mzEyXMJWkllpRloi+Kkoq69sxBTlElF6aAxYUbjXNlhlDZilDnM4U5SlN5biRsRHnbx3mbeWjEh4mEyiuJDl5XcWVmX5GvNkFgLWZM5qwsop4/AWfLhU1cR7k1VVvcYCWRkOI6Xy5gmnphCYIkvzuNYzHzosq2oNk2RtSs8khfUOfHIDgR6ysYBaMpl4uEgk2U/oJTs9AaTSwma7dT69geAE2ZpEjUsn2ieJNHeKfrI3EcAGJ2ZaNgVuC8EBctCLc57P5u5led6IOBkIYkuQMrmmjChs4VkfOerHqSBkPzZlhe06RslZ3zMjk2sscqKwY0RcjKK+LWbzd7KiHhkncs/siFJ+V5eXxD34B8nVuJEpGJNmxN2gH3vSvp7J70tF+D1Ej8qUJD1TkErAND2GZwTFg/LubvmgiBG3SOvdlsqFQrkEzJCL1rstlnVFROixZoDDSuXQFHESwVGlcuQcMb/b42NgjLowh5MTDFE3vNB5qStRIErdCQEh6pLPR92anSUb/wAIhldAaDMpGgAAAABJRU5ErkJggg=="}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[858],{8858:function(A){A.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACkAAAApCAQAAAACach9AAACMUlEQVR4Ae3ShY7jQBAE0Aoz/f9/HTMzhg1zrdKUrJbdx+Kd2nD8VNudfsL/Th///dyQN2TH6f3y/BGpC379rV+S+qqetBOxImNQXL8JCAr2V4iMQXHGNJxeCfZXhSRBcQMfvkOWUdtfzlLgAENmZDcmo2TVmt8OSM2eXxBp3DjHSMFutqS7SbmemzBiR+xpKCNUIRkdkkYxhAkyGoBvyQFEJEefwSmmvBfJuJ6aKqKWnAkvGZOaZXTUgFqYULWNSHUckZuR1HIIimUExutRxwzOLROIG4vKmCKQt364mIlhSyzAf1m9lHZHJZrlAOMMztRRiKimp/rpdJDc9Awry5xTZCte7FHtuS8wJgeYGrex28xNTd086Dik7vUMscQOa8y4DoGtCCSkAKlNwpgNtphjrC6MIHUkR6YWxxs6Sc5xqn222mmCRFzIt8lEdKx+ikCtg91qS2WpwVfBelJCiQJwvzixfI9cxZQWgiSJelKnwBElKYtDOb2MFbhmUigbReQBV0Cg4+qMXSxXSyGUn4UbF8l+7qdSGnTC0XLCmahIgUHLhLOhpVCtw4CzYXvLQWQbJNmxoCsOKAxSgBJno75avolkRw8iIAFcsdc02e9iyCd8tHwmeSSoKTowIgvscSGZUOA7PuCN5b2BX9mQM7S0wYhMNU74zgsPBj3HU7wguAfnxxjFQGBE6pwN+GjME9zHY7zGp8wVxMShYX9NXvEWD3HbwJf4giO4CFIQxXScH1/TM+04kkBiAAAAAElFTkSuQmCC"}}]);

View File

@ -1 +0,0 @@
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[93],{7093:function(A){A.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAApCAYAAADAk4LOAAAFgUlEQVR4Aa1XA5BjWRTN2oW17d3YaZtr2962HUzbDNpjszW24mRt28p47v7zq/bXZtrp/lWnXr337j3nPCe85NcypgSFdugCpW5YoDAMRaIMqRi6aKq5E3YqDQO3qAwjVWrD8Ncq/RBpykd8oZUb/kaJutow8r1aP9II0WmLKLIsJyv1w/kqw9Ch2MYdB++12Onxee/QMwvf4/Dk/Lfp/i4nxTXtOoQ4pW5Aj7wpici1A9erdAN2OH64x8OSP9j3Ft3b7aWkTg/Fm91siTra0f9on5sQr9INejH6CUUUpavjFNq1B+Oadhxmnfa8RfEmN8VNAsQhPqF55xHkMzz3jSmChWU6f7/XZKNH+9+hBLOHYozuKQPxyMPUKkrX/K0uWnfFaJGS1QPRtZsOPtr3NsW0uyh6NNCOkU3Yz+bXbT3I8G3xE5EXLXtCXbbqwCO9zPQYPRTZ5vIDXD7U+w7rFDEoUUf7ibHIR4y6bLVPXrz8JVZEql13trxwue/uDivd3fkWRbS6/IA2bID4uk0UpF1N8qLlbBlXs4Ee7HLTfV1j54APvODnSfOWBqtKVvjgLKzF5YdEk5ewRkGlK0i33Eofffc7HT56jD7/6U+qH3Cx7SBLNntH5YIPvODnyfIXZYRVDPqgHtLs5ABHD3YzLuespb7t79FY34DjMwrVrcTuwlT55YMPvOBnRrJ4VXTdNnYug5ucHLBjEpt30701A3Ts+HEa73u6dT3FNWwflY86eMHPk+Yu+i6pzUpRrW7SNDg5JHR4KapmM5Wv2E8Tfcb1HoqqHMHU+uWDD7zg54mz5/2BSnizi9T1Dg4QQXLToGNCkb6tb1NU+QAlGr1++eADrzhn/u8Q2YZhQVlZ5+CAOtqfbhmaUCS1ezNFVm2imDbPmPng5wmz+gwh+oHDce0eUtQ6OGDIyR0uUhUsoO3vfDmmgOezH0mZN59x7MBi++WDL1g/eEiU3avlidO671bkLfwbw5XV2P8Pzo0ydy4t2/0eu33xYSOMOD8hTf4CrBtGMSoXfPLchX+J0ruSePw3LZeK0juPJbYzrhkH0io7B3k164hiGvawhOKMLkrQLyVpZg8rHFW7E2uHOL888IBPlNZ1FPzstSJM694fWr6RwpvcJK60+0HCILTBzZLFNdtAzJaohze60T8qBzyh5ZuOg5e7uwQppofEmf2++DYvmySqGBuKaicF1blQjhuHdvCIMvp8whTTfZzI7RldpwtSzL+F1+wkdZ2TBOW2gIF88PBTzD/gpeREAMEbxnJcaJHNHrpzji0gQCS6hdkEeYt9DF/2qPcEC8RM28Hwmr3sdNyht00byAut2k3gufWNtgtOEOFGUwcXWNDbdNbpgBGxEvKkOQsxivJx33iow0Vw5S6SVTrpVq11ysA2Rp7gTfPfktc6zhtXBBC+adRLshf6sG2RfHPZ5EAc4sVZ83yCN00Fk/4kggu40ZTvIEm5g24qtU4KjBrx/BTTH8ifVASAG7gKrnWxJDcU7x8X6Ecczhm3o6YicvsLXWfh3Ch1W0k8x0nXF+0fFxgt4phz8QvypiwCCFKMqXCnqXExjq10beH+UUA7+nG6mdG/Pu0f3LgFcGrl2s0kNNjpmoJ9o4B29CMO8dMT4Q5ox8uitF6fqsrJOr8qnwNbRzv6hSnG5wP+64C7h9lp30hKNtKdWjtdkbuPA19nJ7Tz3zR/ibgARbhb4AlhavcBebmTHcFl2fvYEnW0ox9xMxKBS8btJ+KiEbq9zA4RthQXDhPa0T9TEe69gWupwc6uBUphquXgf+/FrIjweHQS4/pduMe5ERUMHUd9xv8ZR98CxkS4F2n3EUrUZ10EYNw7BWm9x1GiPssi3GgiGRDKWRYZfXlON+dfNbM+GgIwYdwAAAAASUVORK5CYII="}}]);

View File

@ -1,2 +0,0 @@
"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.757bc8af.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"static/js/admin.757bc8af.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,MAGN,CAEJ,I,UCvDA,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":""}

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

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

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

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,2 +0,0 @@
"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},4669: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-641164f3"),e=e(),(0,n.Cn)(),e),i={key:0,id:"profile",class:"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-641164f3"]]);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(9977),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.df2cbb8b.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

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

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

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
VUE_APP_API_URL=http://localhost:5000 VITE_APP_API_URL=http://localhost:5000
PORT=3000 PORT=3000

View File

@ -0,0 +1,40 @@
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript',
'@vue/eslint-config-prettier/skip-formatting',
'plugin:import/recommended',
'plugin:import/typescript'
],
parserOptions: {
ecmaVersion: 'latest'
},
settings: {
'import/resolver': {
typescript: {
alwaysTryTypes: true,
project: 'tsconfig.json'
}
}
},
rules: {
'import/order': [
'error',
{
'newlines-between': 'always',
alphabetize: {
order: 'asc',
caseInsensitive: true
}
}
],
'import/no-unresolved': ['off', { ignore: ['^@/'] }],
'vue/multi-word-component-names': 'off',
'@typescript-eslint/no-unused-vars': 'error'
}
}

28
fittrackee_client/.gitignore vendored Normal file
View File

@ -0,0 +1,28 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@ -1,4 +1,5 @@
{ {
"$schema": "https://json.schemastore.org/prettierrc",
"tabWidth": 2, "tabWidth": 2,
"semi": false, "semi": false,
"singleQuote": true, "singleQuote": true,

View File

@ -1,4 +1,4 @@
FROM node:16 FROM node:18
MAINTAINER SamR1@users.noreply.github.com MAINTAINER SamR1@users.noreply.github.com
@ -11,14 +11,14 @@ ENV PATH /usr/src/app/node_modules/.bin:$PATH
# add environment variables # add environment variables
ARG NODE_ENV ARG NODE_ENV
ARG VUE_APP_API_URL ARG VITE_APP_API_URL
ENV NODE_ENV $NODE_ENV ENV NODE_ENV $NODE_ENV
ENV VUE_APP_API_URL $VUE_APP_API_URL ENV VITE_APP_API_URL $VITE_APP_API_URL
# install dependencies # install dependencies
COPY package.json /usr/src/app/package.json COPY package.json /usr/src/app/package.json
COPY yarn.lock /usr/src/app/yarn.lock
RUN yarn install --silent RUN yarn install --silent
RUN yarn global add @vue/cli
# copy source # copy source
COPY . /usr/src/app/ COPY . /usr/src/app/

View File

@ -1,29 +1,46 @@
# fittrackee_client # fittrackee_client
## Project setup This template should help get you started developing with Vue 3 in Vite.
```
yarn install ## Recommended IDE Setup
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
## Type Support for `.vue` Imports in TS
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
1. Disable the built-in TypeScript Extension
1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
## Customize configuration
See [Vite Configuration Reference](https://vitejs.dev/config/).
## Project Setup
```sh
yarn
``` ```
### Compiles and hot-reloads for development ### Compile and Hot-Reload for Development
```
yarn serve ```sh
yarn dev
``` ```
### Compiles and minifies for production ### Type-Check, Compile and Minify for Production
```
```sh
yarn build yarn build
``` ```
### Run your unit tests ### Lint with [ESLint](https://eslint.org/)
```
yarn test:unit
```
### Lints and fixes files ```sh
```
yarn lint yarn lint
``` ```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

View File

@ -1,3 +0,0 @@
module.exports = {
presets: ['@vue/cli-plugin-babel/preset'],
}

1
fittrackee_client/env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="vite/client" />

View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/static/css/fork-awesome.min.css"/>
<link rel="stylesheet" href="/static/css/leaflet.css"/>
<title>FitTrackee</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@ -3,127 +3,67 @@
"version": "0.7.25", "version": "0.7.25",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "dev": "vite",
"build": "vue-cli-service build", "build": "run-p type-check \"build-only {@}\" --",
"test:unit": "vue-cli-service test:unit", "preview": "vite preview",
"lint": "vue-cli-service lint", "test:unit": "vitest",
"lint-fix": "vue-cli-service lint --fix", "build-only": "vite build",
"i18n:report": "vue-cli-service i18n:report --src \"./src/**/*.?(js|vue)\" --locales \"./src/locales/**/*.json\"" "type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
"format": "prettier --write src/"
}, },
"dependencies": { "dependencies": {
"@tmcw/togeojson": "^5.8.1", "@tmcw/togeojson": "^5.8.1",
"@vue-leaflet/vue-leaflet": "0.9.0", "@vue-leaflet/vue-leaflet": "^0.10.1",
"@zxcvbn-ts/core": "^3.0.4", "@zxcvbn-ts/core": "^3.0.4",
"@zxcvbn-ts/language-common": "^3.0.3", "@zxcvbn-ts/language-common": "^3.0.4",
"@zxcvbn-ts/language-de": "^3.0.2", "@zxcvbn-ts/language-de": "^3.0.2",
"@zxcvbn-ts/language-en": "^3.0.2", "@zxcvbn-ts/language-en": "^3.0.2",
"@zxcvbn-ts/language-es-es": "^3.0.2", "@zxcvbn-ts/language-es-es": "^3.0.2",
"@zxcvbn-ts/language-fr": "^3.0.2", "@zxcvbn-ts/language-fr": "^3.0.2",
"@zxcvbn-ts/language-it": "^3.0.2", "@zxcvbn-ts/language-it": "^3.0.2",
"@zxcvbn-ts/language-pl": "^3.0.2", "@zxcvbn-ts/language-pl": "^3.0.2",
"axios": "^1.5.1", "axios": "^1.6.1",
"chart.js": "^4.4.0", "chart.js": "^4.4.0",
"chartjs-plugin-datalabels": "^2.2.0", "chartjs-plugin-datalabels": "^2.2.0",
"core-js": "^3.33.0", "core-js": "^3.33.2",
"date-fns": "2.29.3", "date-fns": "2.30.0",
"date-fns-tz": "^2.0.0", "date-fns-tz": "^2.0.0",
"leaflet": "^1.9.4", "leaflet": "^1.9.4",
"linkify-html": "^4.1.1", "linkify-html": "^4.1.2",
"linkifyjs": "^4.1.1", "linkifyjs": "^4.1.2",
"register-service-worker": "^1.7.1",
"sanitize-html": "^2.11.0", "sanitize-html": "^2.11.0",
"snarkdown": "^2.0.0", "snarkdown": "^2.0.0",
"vue": "3.2.47", "vue": "^3.3.8",
"vue-chart-3": "3.1.1", "vue-chartjs": "^5.2.0",
"vue-fullscreen": "^3.1.1", "vue-fullscreen": "^3.1.1",
"vue-i18n": "^9.5.0", "vue-i18n": "^9.6.5",
"vue-router": "^4.2.5", "vue-router": "^4.2.5",
"vuex": "^4.1.0" "vuex": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@intlify/vue-i18n-loader": "^4.2.0", "@intlify/vue-i18n-loader": "^4.2.0",
"@types/chai": "^4.3.6", "@rushstack/eslint-patch": "^1.3.3",
"@types/mocha": "^10.0.2", "@tsconfig/node18": "^18.2.2",
"@types/sanitize-html": "^2.9.1", "@types/jsdom": "^21.1.3",
"@typescript-eslint/eslint-plugin": "^5.60.0", "@types/node": "^20.9.0",
"@typescript-eslint/parser": "^5.60.0", "@types/sanitize-html": "^2.9.4",
"@vue/cli-plugin-babel": "~5.0.8", "@vitejs/plugin-vue": "^4.4.0",
"@vue/cli-plugin-eslint": "~5.0.8", "@vue/eslint-config-prettier": "^8.0.0",
"@vue/cli-plugin-pwa": "~5.0.8", "@vue/eslint-config-typescript": "^12.0.0",
"@vue/cli-plugin-router": "~5.0.8",
"@vue/cli-plugin-typescript": "~5.0.8",
"@vue/cli-plugin-unit-mocha": "~5.0.8",
"@vue/cli-plugin-vuex": "~5.0.8",
"@vue/cli-service": "~5.0.8",
"@vue/eslint-config-typescript": "^11.0.3",
"@vue/test-utils": "^2.4.1", "@vue/test-utils": "^2.4.1",
"chai": "^4.3.10", "@vue/tsconfig": "^0.4.0",
"eslint": "8.42.0", "eslint": "^8.49.0",
"eslint-config-prettier": "^8.10.0",
"eslint-import-resolver-typescript": "^3.6.1", "eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.28.1", "eslint-plugin-import": "^2.29.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-vue": "^9.17.0", "eslint-plugin-vue": "^9.17.0",
"prettier": "^2.8.8", "jsdom": "^22.1.0",
"sass": "^1.68.0", "npm-run-all2": "^6.1.1",
"sass-loader": "^13.3.2", "prettier": "^3.0.3",
"typescript": "5.0.4", "sass": "^1.69.5",
"vue-cli-plugin-i18n": "~2.3.2" "typescript": "~5.2.0",
}, "vite": "^4.4.11",
"eslintConfig": { "vitest": "^0.34.6",
"root": true, "vue-tsc": "^1.8.19"
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended",
"@vue/typescript/recommended",
"plugin:import/recommended",
"plugin:import/typescript"
],
"globals": {
"defineProps": "readonly",
"defineEmits": "readonly",
"defineExpose": "readonly",
"withDefaults": "readonly"
},
"settings": {
"import/resolver": "typescript"
},
"parserOptions": {
"ecmaVersion": 2020,
"parser": "@typescript-eslint/parser"
},
"rules": {
"import/order": [
"error",
{
"newlines-between": "always",
"alphabetize": {
"order": "asc",
"caseInsensitive": true
} }
}
],
"vue/multi-word-component-names": "off"
},
"overrides": [
{
"files": [
"**/__tests__/*.{j,t}s?(x)",
"**/tests/unit/**/*.spec.{j,t}s?(x)"
],
"env": {
"mocha": true
}
}
]
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead",
"not ie 11"
]
} }

View File

@ -1,19 +0,0 @@
<!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.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="stylesheet" href="<%= BASE_URL %>static/css/fork-awesome.min.css"/>
<link rel="stylesheet" href="<%= BASE_URL %>static/css/leaflet.css"/>
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -29,15 +29,17 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ComputedRef, computed, ref, onBeforeMount, onMounted } from 'vue' import { computed, ref, onBeforeMount, onMounted } from 'vue'
import type { ComputedRef } from 'vue'
import Footer from '@/components/Footer.vue' import Footer from '@/components/Footer.vue'
import NavBar from '@/components/NavBar.vue' import NavBar from '@/components/NavBar.vue'
import NoConfig from '@/components/NoConfig.vue' import NoConfig from '@/components/NoConfig.vue'
import { ROOT_STORE } from '@/store/constants' import { ROOT_STORE } from '@/store/constants'
import { TAppConfig } from '@/types/application' import type { TAppConfig } from '@/types/application'
import type { TLanguage } from '@/types/locales'
import { useStore } from '@/use/useStore' import { useStore } from '@/use/useStore'
import { localeFromLanguage } from '@/utils/locales' import { isLanguageSupported } from '@/utils/locales'
const store = useStore() const store = useStore()
@ -81,10 +83,10 @@
}, 300) }, 300)
} }
function initLanguage() { function initLanguage() {
let language = 'en' let language: TLanguage = 'en'
try { try {
const navigatorLanguage = navigator.language.split('-')[0] const navigatorLanguage = navigator.language.split('-')[0]
if (navigatorLanguage in localeFromLanguage) { if (isLanguageSupported(navigatorLanguage)) {
language = navigatorLanguage language = navigatorLanguage
} }
} catch (e) { } catch (e) {

View File

@ -1,4 +1,4 @@
import { AxiosRequestConfig } from 'axios' import type { AxiosRequestConfig } from 'axios'
export const pendingRequests = new Map() export const pendingRequests = new Map()

View File

@ -49,9 +49,7 @@
</div> </div>
<template v-if="appConfig.about"> <template v-if="appConfig.about">
<p class="about-instance">{{ $t('about.ABOUT_THIS_INSTANCE') }}</p> <p class="about-instance">{{ $t('about.ABOUT_THIS_INSTANCE') }}</p>
<div <div v-html="snarkdown(linkifyAndClean(appConfig.about))" />
v-html="snarkdown(linkifyAndClean(appConfig.about))"
/>
</template> </template>
</div> </div>
</div> </div>
@ -59,10 +57,11 @@
<script lang="ts" setup> <script lang="ts" setup>
import snarkdown from 'snarkdown' import snarkdown from 'snarkdown'
import { ComputedRef, computed, capitalize } from 'vue' import { computed, capitalize } from 'vue'
import type { ComputedRef } from 'vue'
import { ROOT_STORE } from '@/store/constants' import { ROOT_STORE } from '@/store/constants'
import { TAppConfig } from '@/types/application' import type { TAppConfig } from '@/types/application'
import { useStore } from '@/use/useStore' import { useStore } from '@/use/useStore'
import { linkifyAndClean } from '@/utils/inputs' import { linkifyAndClean } from '@/utils/inputs'
@ -113,7 +112,7 @@
} }
.about-instance { .about-instance {
font-weight: bold; font-weight: bold;
margin-top: $default-margin*3; margin-top: $default-margin * 3;
} }
} }
</style> </style>

View File

@ -88,7 +88,13 @@
/> />
<div <div
v-else v-else
v-html="snarkdown(linkifyAndClean(appData.about ? appData.about : $t('admin.NO_TEXT_ENTERED')))" v-html="
snarkdown(
linkifyAndClean(
appData.about ? appData.about : $t('admin.NO_TEXT_ENTERED')
)
)
"
class="textarea-content" class="textarea-content"
/> />
<label class="privacy-policy-label" for="privacy_policy"> <label class="privacy-policy-label" for="privacy_policy">
@ -106,7 +112,15 @@
/> />
<div <div
v-else v-else
v-html="snarkdown(linkifyAndClean(appData.privacy_policy ? appData.privacy_policy : $t('admin.NO_TEXT_ENTERED')))" v-html="
snarkdown(
linkifyAndClean(
appData.privacy_policy
? appData.privacy_policy
: $t('admin.NO_TEXT_ENTERED')
)
)
"
class="textarea-content" class="textarea-content"
/> />
<ErrorMessage :message="errorMessages" v-if="errorMessages" /> <ErrorMessage :message="errorMessages" v-if="errorMessages" />
@ -137,19 +151,12 @@
<script setup lang="ts"> <script setup lang="ts">
import snarkdown from 'snarkdown' import snarkdown from 'snarkdown'
import { import { capitalize, computed, reactive, onBeforeMount, toRefs } from 'vue'
ComputedRef, import type { ComputedRef } from 'vue'
capitalize,
computed,
reactive,
withDefaults,
onBeforeMount,
toRefs,
} from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { ROOT_STORE } from '@/store/constants' import { ROOT_STORE } from '@/store/constants'
import { TAppConfig, TAppConfigForm } from '@/types/application' import type { TAppConfig, TAppConfigForm } from '@/types/application'
import { useStore } from '@/use/useStore' import { useStore } from '@/use/useStore'
import { getFileSizeInMB } from '@/utils/files' import { getFileSizeInMB } from '@/utils/files'
import { linkifyAndClean } from '@/utils/inputs' import { linkifyAndClean } from '@/utils/inputs'
@ -187,19 +194,17 @@
function updateForm(appConfig: TAppConfig) { function updateForm(appConfig: TAppConfig) {
Object.keys(appData).map((key) => { Object.keys(appData).map((key) => {
['max_single_file_size', 'max_zip_file_size'].includes(key) ;['max_single_file_size', 'max_zip_file_size'].includes(key)
? // eslint-disable-next-line @typescript-eslint/ban-ts-comment ? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
(appData[key] = getFileSizeInMB(appConfig[key])) (appData[key] = getFileSizeInMB(appConfig[key]))
: ['about', 'privacy_policy'].includes(key) : ['about', 'privacy_policy'].includes(key)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment ? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
? appData[key] = appConfig[key]!== null (appData[key] = appConfig[key] !== null ? appConfig[key] : '')
? appConfig[key] : // eslint-disable-next-line @typescript-eslint/ban-ts-comment
: ''
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
: (appData[key] = appConfig[key]) (appData[key] = appConfig[key])
}) })
} }
function onCancel() { function onCancel() {
@ -242,6 +247,5 @@
margin-bottom: $default-margin; margin-bottom: $default-margin;
padding: $default-padding; padding: $default-padding;
} }
} }
</style> </style>

View File

@ -54,18 +54,18 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { capitalize, onMounted, toRefs, withDefaults } from 'vue' import { capitalize, onMounted, toRefs } from 'vue'
import AppStatsCards from '@/components/Administration/AppStatsCards.vue' import AppStatsCards from '@/components/Administration/AppStatsCards.vue'
import Card from '@/components/Common/Card.vue' import Card from '@/components/Common/Card.vue'
import { IAppStatistics, TAppConfig } from '@/types/application' import type { IAppStatistics, TAppConfig } from '@/types/application'
interface Props { interface Props {
appConfig: TAppConfig appConfig: TAppConfig
appStatistics?: IAppStatistics appStatistics?: IAppStatistics
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
appStatistics: () => ({} as IAppStatistics), appStatistics: () => ({}) as IAppStatistics,
}) })
const { appConfig, appStatistics } = toRefs(props) const { appConfig, appStatistics } = toRefs(props)

View File

@ -84,11 +84,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ComputedRef, computed } from 'vue' import { computed } from 'vue'
import type { ComputedRef } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { ROOT_STORE, SPORTS_STORE } from '@/store/constants' import { ROOT_STORE, SPORTS_STORE } from '@/store/constants'
import { ITranslatedSport } from '@/types/sports' import type { ITranslatedSport } from '@/types/sports'
import { useStore } from '@/use/useStore' import { useStore } from '@/use/useStore'
import { translateSports } from '@/utils/sports' import { translateSports } from '@/utils/sports'

View File

@ -134,8 +134,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { import {
ComputedRef,
Ref,
computed, computed,
reactive, reactive,
watch, watch,
@ -143,15 +141,17 @@
onBeforeMount, onBeforeMount,
onUnmounted, onUnmounted,
} from 'vue' } from 'vue'
import { LocationQuery, useRoute, useRouter } from 'vue-router' import type { ComputedRef, Ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import type { LocationQuery } from 'vue-router'
import FilterSelects from '@/components/Common/FilterSelects.vue' import FilterSelects from '@/components/Common/FilterSelects.vue'
import Pagination from '@/components/Common/Pagination.vue' import Pagination from '@/components/Common/Pagination.vue'
import UserPicture from '@/components/User/UserPicture.vue' import UserPicture from '@/components/User/UserPicture.vue'
import UsersNameFilter from '@/components/Users/UsersNameFilter.vue' import UsersNameFilter from '@/components/Users/UsersNameFilter.vue'
import { AUTH_USER_STORE, ROOT_STORE, USERS_STORE } from '@/store/constants' import { AUTH_USER_STORE, ROOT_STORE, USERS_STORE } from '@/store/constants'
import { IPagination, TPaginationPayload } from '@/types/api' import type { IPagination, TPaginationPayload } from '@/types/api'
import { IAuthUserProfile, IUserProfile } from '@/types/user' import type { 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 { formatDate } from '@/utils/dates' import { formatDate } from '@/utils/dates'

View File

@ -27,7 +27,7 @@
import { computed, toRefs } from 'vue' import { computed, toRefs } from 'vue'
import StatCard from '@/components/Common/StatCard.vue' import StatCard from '@/components/Common/StatCard.vue'
import { IAppStatistics } from '@/types/application' import type { IAppStatistics } from '@/types/application'
import { getReadableFileSize } from '@/utils/files' import { getReadableFileSize } from '@/utils/files'
interface Props { interface Props {
@ -37,7 +37,7 @@
const { appStatistics } = toRefs(props) const { appStatistics } = toRefs(props)
const uploadDirSize = computed(() => const uploadDirSize = computed(() =>
getReadableFileSize(appStatistics.value.uploads_dir_size, false) getReadableFileSize(appStatistics.value.uploads_dir_size)
) )
</script> </script>

View File

@ -15,7 +15,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch, withDefaults } from 'vue' import { ref, watch } from 'vue'
interface Props { interface Props {
name: string name: string
@ -33,8 +33,8 @@
const text = ref('') const text = ref('')
function updateText(event: Event & { target: HTMLInputElement }) { function updateText(event: Event) {
emit('updateValue', event.target.value) emit('updateValue', (event.target as HTMLInputElement).value)
} }
watch( watch(

View File

@ -7,9 +7,10 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ComputedRef, computed, toRefs, withDefaults } from 'vue' import { computed, toRefs } from 'vue'
import type { ComputedRef } from 'vue'
import { TUnit } from '@/types/units' import type { TUnit } from '@/types/units'
import { units, convertDistance } from '@/utils/units' import { units, convertDistance } from '@/utils/units'
interface Props { interface Props {

Some files were not shown because too many files have changed in this diff Show More