Client - fix type errors
This commit is contained in:
parent
b6d6a91549
commit
473d0aca53
3
.github/workflows/.tests-javascript.yml
vendored
3
.github/workflows/.tests-javascript.yml
vendored
@ -28,6 +28,9 @@ jobs:
|
||||
- name: Lint
|
||||
working-directory: ${{env.working-directory}}
|
||||
run: yarn lint
|
||||
- name: Type check
|
||||
working-directory: ${{env.working-directory}}
|
||||
run: yarn type-check
|
||||
- name: Tests
|
||||
working-directory: ${{env.working-directory}}
|
||||
run: yarn test:unit
|
||||
|
@ -37,8 +37,9 @@
|
||||
import NoConfig from '@/components/NoConfig.vue'
|
||||
import { ROOT_STORE } from '@/store/constants'
|
||||
import type { TAppConfig } from '@/types/application'
|
||||
import type { TLanguage } from '@/types/locales'
|
||||
import { useStore } from '@/use/useStore'
|
||||
import { localeFromLanguage } from '@/utils/locales'
|
||||
import { isLanguageSupported } from '@/utils/locales'
|
||||
|
||||
const store = useStore()
|
||||
|
||||
@ -82,10 +83,10 @@
|
||||
}, 300)
|
||||
}
|
||||
function initLanguage() {
|
||||
let language = 'en'
|
||||
let language: TLanguage = 'en'
|
||||
try {
|
||||
const navigatorLanguage = navigator.language.split('-')[0]
|
||||
if (navigatorLanguage in localeFromLanguage) {
|
||||
if (isLanguageSupported(navigatorLanguage)) {
|
||||
language = navigatorLanguage
|
||||
}
|
||||
} catch (e) {
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
const { appStatistics } = toRefs(props)
|
||||
const uploadDirSize = computed(() =>
|
||||
getReadableFileSize(appStatistics.value.uploads_dir_size, false)
|
||||
getReadableFileSize(appStatistics.value.uploads_dir_size)
|
||||
)
|
||||
</script>
|
||||
|
||||
|
@ -33,8 +33,8 @@
|
||||
|
||||
const text = ref('')
|
||||
|
||||
function updateText(event: Event & { target: HTMLInputElement }) {
|
||||
emit('updateValue', event.target.value)
|
||||
function updateText(event: Event) {
|
||||
emit('updateValue', (event.target as HTMLInputElement).value)
|
||||
}
|
||||
|
||||
watch(
|
||||
|
@ -60,8 +60,12 @@
|
||||
const { order_by, query, sort, message } = toRefs(props)
|
||||
const perPage = [10, 25, 50, 100]
|
||||
|
||||
function onSelectUpdate(event: Event & { target: HTMLInputElement }) {
|
||||
emit('updateSelect', event.target.id, event.target.value)
|
||||
function onSelectUpdate(event: Event) {
|
||||
emit(
|
||||
'updateSelect',
|
||||
(event.target as HTMLInputElement).id,
|
||||
(event.target as HTMLInputElement).value
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { inject, toRefs, withDefaults } from 'vue'
|
||||
import { inject, toRefs } from 'vue'
|
||||
|
||||
import CyclingSport from '@/components/Common/Images/SportImage/CyclingSport.vue'
|
||||
import CyclingTransport from '@/components/Common/Images/SportImage/CyclingTransport.vue'
|
||||
@ -55,5 +55,5 @@
|
||||
})
|
||||
|
||||
const { color, sportLabel, title } = toRefs(props)
|
||||
const sportColors = inject('sportColors')
|
||||
const sportColors = inject('sportColors') as Record<string, string>
|
||||
</script>
|
||||
|
@ -50,7 +50,7 @@
|
||||
strongMessage?: string | null
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
strongMessage: () => null,
|
||||
strongMessage: () => '',
|
||||
})
|
||||
|
||||
const emit = defineEmits(['cancelAction', 'confirmAction'])
|
||||
@ -63,7 +63,7 @@
|
||||
)
|
||||
let confirmButton: HTMLElement | null = null
|
||||
let cancelButton: HTMLElement | null = null
|
||||
let previousFocusedElement: Element | null = null
|
||||
let previousFocusedElement: HTMLInputElement | null = null
|
||||
|
||||
function focusTrap(e: KeyboardEvent) {
|
||||
if (e.key === 'Tab' || e.keyCode === 9) {
|
||||
@ -77,7 +77,7 @@
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
previousFocusedElement = document.activeElement
|
||||
previousFocusedElement = document.activeElement as HTMLInputElement | null
|
||||
cancelButton = document.getElementById('cancel-button')
|
||||
confirmButton = document.getElementById('confirm-button')
|
||||
if (cancelButton) {
|
||||
|
@ -50,6 +50,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { toRefs } from 'vue'
|
||||
import type { LocationQuery } from 'vue-router'
|
||||
|
||||
import type { IPagination, TPaginationPayload } from '@/types/api'
|
||||
import type { IOauth2ClientsPayload } from '@/types/oauth'
|
||||
@ -65,13 +66,10 @@
|
||||
|
||||
const { pagination, path, query } = toRefs(props)
|
||||
|
||||
function getQuery(
|
||||
page: number,
|
||||
cursor?: number
|
||||
): TPaginationPayload | IOauth2ClientsPayload {
|
||||
function getQuery(page: number, cursor?: number): LocationQuery {
|
||||
const newQuery = Object.assign({}, query.value)
|
||||
newQuery.page = cursor ? page + cursor : page
|
||||
return newQuery
|
||||
return newQuery as LocationQuery
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -62,8 +62,8 @@
|
||||
function togglePassword() {
|
||||
showPassword.value = !showPassword.value
|
||||
}
|
||||
function updatePassword(event: Event & { target: HTMLInputElement }) {
|
||||
emit('updatePassword', event.target.value)
|
||||
function updatePassword(event: Event) {
|
||||
emit('updatePassword', (event.target as HTMLInputElement).value)
|
||||
}
|
||||
function invalidPassword() {
|
||||
emit('passwordError')
|
||||
|
@ -163,12 +163,9 @@
|
||||
params: apiParams,
|
||||
})
|
||||
}
|
||||
function updateDisplayData(
|
||||
event: Event & {
|
||||
target: HTMLInputElement & { name: TStatisticsDatasetKeys }
|
||||
}
|
||||
) {
|
||||
displayedData.value = event.target.name
|
||||
function updateDisplayData(event: Event) {
|
||||
displayedData.value = (event.target as HTMLInputElement)
|
||||
.name as TStatisticsDatasetKeys
|
||||
}
|
||||
function getApiParams(
|
||||
chartParams: IStatisticsDateParams,
|
||||
|
@ -40,14 +40,14 @@
|
||||
import NoWorkouts from '@/components/Workouts/NoWorkouts.vue'
|
||||
import { WORKOUTS_STORE } from '@/store/constants'
|
||||
import type { ISport } from '@/types/sports'
|
||||
import type { IUserProfile } from '@/types/user'
|
||||
import type { IAuthUserProfile } from '@/types/user'
|
||||
import type { IWorkout } from '@/types/workouts'
|
||||
import { useStore } from '@/use/useStore'
|
||||
import { defaultOrder } from '@/utils/workouts'
|
||||
|
||||
interface Props {
|
||||
sports: ISport[]
|
||||
user: IUserProfile
|
||||
user: IAuthUserProfile
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const days = []
|
||||
const days: Date[] = []
|
||||
for (let i = 0; i < 7; i++) {
|
||||
days.push(addDays(props.startDate, i))
|
||||
}
|
||||
|
@ -20,7 +20,9 @@
|
||||
.filter((record) =>
|
||||
displayHARecord ? true : record.record_type !== 'HA'
|
||||
)
|
||||
.map((record) => ` ${$t(`workouts.RECORD_${record.record_type}`)}`)
|
||||
.map(
|
||||
(record) => ` ${$t(`workouts.RECORD_${record.record_type}`)}`
|
||||
)[0]
|
||||
"
|
||||
/>
|
||||
</sup>
|
||||
|
@ -20,6 +20,7 @@
|
||||
:sports="sports"
|
||||
:datasets="chartDatasets"
|
||||
:colors="colors"
|
||||
:displayHARecord="displayHARecord"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -30,6 +31,7 @@
|
||||
:sports="sports"
|
||||
:datasets="chartDatasets"
|
||||
:colors="colors"
|
||||
:displayHARecord="displayHARecord"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -14,6 +14,7 @@
|
||||
<CalendarWorkout
|
||||
v-for="(workout, index) in workouts"
|
||||
:key="index"
|
||||
:displayHARecord="displayHARecord"
|
||||
:workout="workout"
|
||||
:sportLabel="getSportLabel(workout, sports)"
|
||||
:sportColor="getSportColor(workout, sports)"
|
||||
@ -37,13 +38,14 @@
|
||||
datasets: Record<number, Record<string, number>>
|
||||
sports: ISport[]
|
||||
workouts: IWorkout[]
|
||||
displayHARecord: boolean
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const { colors, datasets, sports, workouts } = toRefs(props)
|
||||
const isHidden = ref(true)
|
||||
|
||||
function togglePane(event: Event & { target: HTMLElement }) {
|
||||
function togglePane(event: Event) {
|
||||
event.stopPropagation()
|
||||
isHidden.value = !isHidden.value
|
||||
}
|
||||
|
@ -21,11 +21,11 @@
|
||||
|
||||
import StatChart from '@/components/Common/StatsChart/index.vue'
|
||||
import type { ISport } from '@/types/sports'
|
||||
import type { IUserProfile } from '@/types/user'
|
||||
import type { IAuthUserProfile } from '@/types/user'
|
||||
|
||||
interface Props {
|
||||
sports: ISport[]
|
||||
user: IUserProfile
|
||||
user: IAuthUserProfile
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
|
||||
|
@ -35,11 +35,11 @@
|
||||
import { toRefs } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import type { ICardRecord, IRecord, IRecordsBySports } from '@/types/workouts'
|
||||
import type { ICardRecord, IRecord, IRecordsBySport } from '@/types/workouts'
|
||||
import { sortRecords } from '@/utils/records'
|
||||
|
||||
interface Props {
|
||||
records: IRecordsBySports
|
||||
records: IRecordsBySport
|
||||
sportTranslatedLabel: string
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
|
@ -99,6 +99,7 @@
|
||||
import UserPicture from '@/components/User/UserPicture.vue'
|
||||
import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'
|
||||
import type { IDropdownOption } from '@/types/forms'
|
||||
import type { TLanguage } from '@/types/locales'
|
||||
import type { IAuthUserProfile } from '@/types/user'
|
||||
import { useStore } from '@/use/useStore'
|
||||
import { availableLanguages } from '@/utils/locales'
|
||||
@ -130,7 +131,7 @@
|
||||
function updateLanguage(option: IDropdownOption) {
|
||||
store.dispatch(
|
||||
ROOT_STORE.ACTIONS.UPDATE_APPLICATION_LANGUAGE,
|
||||
option.value.toString()
|
||||
option.value as TLanguage
|
||||
)
|
||||
}
|
||||
function logout() {
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const sportColors: Record<string, string> | undefined = inject('sportColors')
|
||||
const sportColors = inject('sportColors') as Record<string, string>
|
||||
const { selectedSportIds } = toRefs(props)
|
||||
const translatedSports: ComputedRef<ITranslatedSport[]> = computed(() =>
|
||||
translateSports(props.userSports, t)
|
||||
|
@ -125,6 +125,7 @@
|
||||
|
||||
import { AUTH_USER_STORE, ROOT_STORE, USERS_STORE } from '@/store/constants'
|
||||
import type { TAppConfig } from '@/types/application'
|
||||
import type { TLanguage } from '@/types/locales'
|
||||
import type { IAuthUserProfile, IUserProfile } from '@/types/user'
|
||||
import { useStore } from '@/use/useStore'
|
||||
import { formatDate, getDateFormat } from '@/utils/dates'
|
||||
@ -141,7 +142,7 @@
|
||||
const store = useStore()
|
||||
|
||||
const { user, fromAdmin } = toRefs(props)
|
||||
const language: ComputedRef<string> = computed(
|
||||
const language: ComputedRef<TLanguage> = computed(
|
||||
() => store.getters[ROOT_STORE.GETTERS.LANGUAGE]
|
||||
)
|
||||
const authUser: ComputedRef<IAuthUserProfile> = computed(
|
||||
|
@ -60,6 +60,7 @@
|
||||
import type { ComputedRef } from 'vue'
|
||||
|
||||
import { ROOT_STORE } from '@/store/constants'
|
||||
import type { TLanguage } from '@/types/locales'
|
||||
import type { IAuthUserProfile } from '@/types/user'
|
||||
import { useStore } from '@/use/useStore'
|
||||
import { getDateFormat } from '@/utils/dates'
|
||||
@ -72,7 +73,7 @@
|
||||
|
||||
const store = useStore()
|
||||
|
||||
const appLanguage: ComputedRef<string> = computed(
|
||||
const appLanguage: ComputedRef<TLanguage> = computed(
|
||||
() => store.getters[ROOT_STORE.GETTERS.LANGUAGE]
|
||||
)
|
||||
const userLanguage = computed(() =>
|
||||
|
@ -60,16 +60,16 @@
|
||||
isOpen.value = false
|
||||
emit('updateTimezone', value)
|
||||
}
|
||||
function onEnter(event: Event & { target: HTMLInputElement }) {
|
||||
function onEnter(event: Event) {
|
||||
event.preventDefault()
|
||||
if (tzList.value?.firstElementChild?.innerHTML) {
|
||||
onUpdateTimezone(tzList.value?.firstElementChild?.innerHTML)
|
||||
}
|
||||
}
|
||||
function openDropdown(event: Event & { target: HTMLInputElement }) {
|
||||
function openDropdown(event: Event) {
|
||||
event.preventDefault()
|
||||
isOpen.value = true
|
||||
timezone.value = event.target.value.trim()
|
||||
timezone.value = (event.target as HTMLInputElement).value.trim()
|
||||
}
|
||||
|
||||
watch(
|
||||
|
@ -87,7 +87,7 @@
|
||||
>
|
||||
<i class="fa fa-download" aria-hidden="true" />
|
||||
{{ $t('user.EXPORT_REQUEST.DOWNLOAD_ARCHIVE') }}
|
||||
({{ getReadableFileSize(exportRequest.file_size) }})
|
||||
({{ getReadableFileSizeAsText(exportRequest.file_size) }})
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ $t(`user.EXPORT_REQUEST.STATUS.${exportRequest.status}`) }}
|
||||
@ -126,7 +126,7 @@
|
||||
} from '@/types/user'
|
||||
import { useStore } from '@/use/useStore'
|
||||
import { formatDate } from '@/utils/dates'
|
||||
import { getReadableFileSize } from '@/utils/files'
|
||||
import { getReadableFileSizeAsText } from '@/utils/files'
|
||||
|
||||
interface Props {
|
||||
user: IAuthUserProfile
|
||||
|
@ -41,7 +41,7 @@
|
||||
import type { TAppConfig } from '@/types/application'
|
||||
import type { IUserProfile } from '@/types/user'
|
||||
import { useStore } from '@/use/useStore'
|
||||
import { getReadableFileSize } from '@/utils/files'
|
||||
import { getReadableFileSizeAsText } from '@/utils/files'
|
||||
|
||||
interface Props {
|
||||
user: IUserProfile
|
||||
@ -58,16 +58,18 @@
|
||||
() => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]
|
||||
)
|
||||
const fileSizeLimit = appConfig.value.max_single_file_size
|
||||
? getReadableFileSize(appConfig.value.max_single_file_size)
|
||||
? getReadableFileSizeAsText(appConfig.value.max_single_file_size)
|
||||
: ''
|
||||
const pictureFile: Ref<File | null> = ref(null)
|
||||
|
||||
function deleteUserPicture() {
|
||||
store.dispatch(AUTH_USER_STORE.ACTIONS.DELETE_PICTURE)
|
||||
}
|
||||
function updatePictureFile(event: Event & { target: HTMLInputElement }) {
|
||||
if (event.target.files) {
|
||||
pictureFile.value = event.target.files[0]
|
||||
function updatePictureFile(event: Event) {
|
||||
if ((event.target as HTMLInputElement).files !== null) {
|
||||
pictureFile.value = (
|
||||
(event.target as HTMLInputElement).files as FileList
|
||||
)[0]
|
||||
}
|
||||
}
|
||||
function updateUserPicture() {
|
||||
|
@ -185,10 +185,12 @@
|
||||
const userForm: IUserPreferencesPayload = reactive({
|
||||
display_ascent: true,
|
||||
imperial_units: false,
|
||||
language: '',
|
||||
language: 'en',
|
||||
timezone: 'Europe/Paris',
|
||||
date_format: 'dd/MM/yyyy',
|
||||
weekm: false,
|
||||
start_elevation_at_zero: false,
|
||||
use_raw_gpx_speed: false,
|
||||
})
|
||||
const weekStart = [
|
||||
{
|
||||
|
@ -104,6 +104,7 @@
|
||||
client_name: '',
|
||||
client_uri: '',
|
||||
client_description: '',
|
||||
description: '',
|
||||
redirect_uri: '',
|
||||
})
|
||||
const scopes: string[] = reactive([])
|
||||
|
@ -122,8 +122,8 @@
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import { OAUTH2_STORE, ROOT_STORE } from '@/store/constants'
|
||||
import { IOAuth2Client } from '@/types/oauth'
|
||||
import { IAuthUserProfile } from '@/types/user'
|
||||
import type { IOAuth2Client } from '@/types/oauth'
|
||||
import type { IAuthUserProfile } from '@/types/user'
|
||||
import { useStore } from '@/use/useStore'
|
||||
import { formatDate } from '@/utils/dates'
|
||||
|
||||
@ -145,7 +145,7 @@
|
||||
() => store.getters[OAUTH2_STORE.GETTERS.REVOCATION_SUCCESSFUL]
|
||||
)
|
||||
const displayModal: Ref<boolean> = ref(false)
|
||||
const messageToDisplay: Ref<string | null> = ref(null)
|
||||
const messageToDisplay: Ref<string> = ref('')
|
||||
const idCopied: Ref<boolean> = ref(false)
|
||||
const secretCopied: Ref<boolean> = ref(false)
|
||||
const clipboardSupport: Ref<boolean> = ref(false)
|
||||
@ -176,7 +176,7 @@
|
||||
function updateDisplayModal(value: boolean) {
|
||||
displayModal.value = value
|
||||
if (!value) {
|
||||
messageToDisplay.value = null
|
||||
messageToDisplay.value = ''
|
||||
}
|
||||
}
|
||||
function confirmAction(clientId: number) {
|
||||
|
@ -186,7 +186,7 @@
|
||||
|
||||
const { isEdition, user } = toRefs(props)
|
||||
const defaultColor = '#838383'
|
||||
const sportColors: Record<string, string> | undefined = inject('sportColors')
|
||||
const sportColors = inject('sportColors') as Record<string, string>
|
||||
const sports: ComputedRef<ISport[]> = computed(
|
||||
() => store.getters[SPORTS_STORE.GETTERS.SPORTS]
|
||||
)
|
||||
@ -223,14 +223,16 @@
|
||||
function isSportInEdition(sportId: number) {
|
||||
return sportPayload.sport_id === sportId
|
||||
}
|
||||
function updateColor(event: Event & { target: HTMLInputElement }) {
|
||||
sportPayload.color = event.target.value
|
||||
function updateColor(event: Event) {
|
||||
sportPayload.color = (event.target as HTMLInputElement).value
|
||||
}
|
||||
function updateThreshold(event: Event & { target: HTMLInputElement }) {
|
||||
sportPayload.stopped_speed_threshold = parseFloat(event.target.value)
|
||||
function updateThreshold(event: Event) {
|
||||
sportPayload.stopped_speed_threshold = parseFloat(
|
||||
(event.target as HTMLInputElement).value
|
||||
)
|
||||
}
|
||||
function updateIsActive(event: Event & { target: HTMLInputElement }) {
|
||||
sportPayload.is_active = event.target.checked
|
||||
function updateIsActive(event: Event) {
|
||||
sportPayload.is_active = (event.target as HTMLInputElement).checked
|
||||
}
|
||||
function resetSportPayload() {
|
||||
sportPayload.sport_id = 0
|
||||
|
@ -73,7 +73,7 @@
|
||||
>
|
||||
<div class="img">
|
||||
<SportImage
|
||||
v-if="sport.label"
|
||||
v-if="sport?.label"
|
||||
:sport-label="sport.label"
|
||||
:color="sport.color"
|
||||
/>
|
||||
@ -147,16 +147,16 @@
|
||||
import UserPicture from '@/components/User/UserPicture.vue'
|
||||
import { ROOT_STORE } from '@/store/constants'
|
||||
import type { ISport } from '@/types/sports'
|
||||
import type { IUserProfile } from '@/types/user'
|
||||
import type { IAuthUserProfile } from '@/types/user'
|
||||
import type { IWorkout } from '@/types/workouts'
|
||||
import { useStore } from '@/use/useStore'
|
||||
import { formatDate } from '@/utils/dates'
|
||||
|
||||
interface Props {
|
||||
user: IUserProfile
|
||||
user: IAuthUserProfile
|
||||
useImperialUnits: boolean
|
||||
workout?: IWorkout
|
||||
sport?: ISport
|
||||
sport?: ISport | null
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
workout: () => ({}) as IWorkout,
|
||||
|
@ -24,7 +24,7 @@
|
||||
notes?: string | null
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
notes: () => null,
|
||||
notes: () => '',
|
||||
})
|
||||
|
||||
const { notes } = toRefs(props)
|
||||
|
@ -11,6 +11,7 @@
|
||||
<Card>
|
||||
<template #title>
|
||||
<WorkoutCardTitle
|
||||
v-if="sport"
|
||||
:sport="sport"
|
||||
:workoutObject="workoutObject"
|
||||
@displayModal="updateDisplayModal(true)"
|
||||
@ -84,7 +85,7 @@
|
||||
? props.sports.find(
|
||||
(sport) => sport.id === props.workoutData.workout.sport_id
|
||||
)
|
||||
: {}
|
||||
: ({} as ISport)
|
||||
)
|
||||
const workoutObject = computed(() =>
|
||||
getWorkoutObject(workout.value, segment.value)
|
||||
|
@ -281,12 +281,12 @@
|
||||
|
||||
import { ROOT_STORE, WORKOUTS_STORE } from '@/store/constants'
|
||||
import type { TAppConfig } from '@/types/application'
|
||||
import type { ISport } from '@/types/sports'
|
||||
import type { ISport, ITranslatedSport } from '@/types/sports'
|
||||
import type { IAuthUserProfile } from '@/types/user'
|
||||
import type { IWorkout, IWorkoutForm } from '@/types/workouts'
|
||||
import { useStore } from '@/use/useStore'
|
||||
import { formatWorkoutDate, getDateWithTZ } from '@/utils/dates'
|
||||
import { getReadableFileSize } from '@/utils/files'
|
||||
import { getReadableFileSizeAsText } from '@/utils/files'
|
||||
import { translateSports } from '@/utils/sports'
|
||||
import { convertDistance } from '@/utils/units'
|
||||
|
||||
@ -308,7 +308,7 @@
|
||||
const router = useRouter()
|
||||
|
||||
const { authUser, workout, isCreation, loading } = toRefs(props)
|
||||
const translatedSports: ComputedRef<ISport[]> = computed(() =>
|
||||
const translatedSports: ComputedRef<ITranslatedSport[]> = computed(() =>
|
||||
translateSports(
|
||||
props.sports,
|
||||
t,
|
||||
@ -320,11 +320,11 @@
|
||||
() => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]
|
||||
)
|
||||
const fileSizeLimit = appConfig.value.max_single_file_size
|
||||
? getReadableFileSize(appConfig.value.max_single_file_size)
|
||||
? getReadableFileSizeAsText(appConfig.value.max_single_file_size)
|
||||
: ''
|
||||
const gpx_limit_import = appConfig.value.gpx_limit_import
|
||||
const zipSizeLimit = appConfig.value.max_zip_file_size
|
||||
? getReadableFileSize(appConfig.value.max_zip_file_size)
|
||||
? getReadableFileSizeAsText(appConfig.value.max_zip_file_size)
|
||||
: ''
|
||||
const errorMessages: ComputedRef<string | string[] | null> = computed(
|
||||
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
|
||||
@ -369,9 +369,9 @@
|
||||
withGpx.value = !withGpx.value
|
||||
formErrors.value = false
|
||||
}
|
||||
function updateFile(event: Event & { target: HTMLInputElement }) {
|
||||
if (event.target.files) {
|
||||
gpxFile = event.target.files[0]
|
||||
function updateFile(event: Event) {
|
||||
if ((event.target as HTMLInputElement).files) {
|
||||
gpxFile = ((event.target as HTMLInputElement).files as FileList)[0]
|
||||
}
|
||||
}
|
||||
function formatWorkoutForm(workout: IWorkout) {
|
||||
|
@ -192,7 +192,7 @@
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import type { LocationQuery } from 'vue-router'
|
||||
|
||||
import type { ISport } from '@/types/sports'
|
||||
import type { ISport, ITranslatedSport } from '@/types/sports'
|
||||
import type { IAuthUserProfile } from '@/types/user'
|
||||
import { translateSports } from '@/utils/sports'
|
||||
import { units } from '@/utils/units'
|
||||
@ -214,7 +214,7 @@
|
||||
const toUnit = authUser.value.imperial_units
|
||||
? units['km'].defaultTarget
|
||||
: 'km'
|
||||
const translatedSports: ComputedRef<ISport[]> = computed(() =>
|
||||
const translatedSports: ComputedRef<ITranslatedSport[]> = computed(() =>
|
||||
translateSports(props.sports, t)
|
||||
)
|
||||
let params: LocationQuery = Object.assign({}, route.query)
|
||||
@ -226,11 +226,13 @@
|
||||
}
|
||||
})
|
||||
|
||||
function handleFilterChange(event: Event & { target: HTMLInputElement }) {
|
||||
if (event.target.value === '') {
|
||||
delete params[event.target.name]
|
||||
function handleFilterChange(event: Event) {
|
||||
const name = (event.target as HTMLInputElement).name
|
||||
const value = (event.target as HTMLInputElement).value
|
||||
if (value === '') {
|
||||
delete params[name]
|
||||
} else {
|
||||
params[event.target.name] = event.target.value
|
||||
params[name] = value
|
||||
}
|
||||
}
|
||||
function onFilter() {
|
||||
|
@ -5,7 +5,7 @@
|
||||
<span class="total-label">
|
||||
{{ $t('common.TOTAL').toLowerCase() }}:
|
||||
</span>
|
||||
<span v-if="pagination.total !== null">
|
||||
<span v-if="pagination.total">
|
||||
{{ pagination.total }}
|
||||
{{ $t('workouts.WORKOUT', pagination.total) }}
|
||||
</span>
|
||||
@ -47,7 +47,7 @@
|
||||
<SportImage
|
||||
v-if="sports.length > 0"
|
||||
:title="
|
||||
sports.find((s) => s.id === workout.sport_id)
|
||||
sports.filter((s) => s.id === workout.sport_id)[0]
|
||||
.translatedLabel
|
||||
"
|
||||
:sport-label="getSportLabel(workout, sports)"
|
||||
|
@ -6,6 +6,7 @@ import router from '@/router'
|
||||
import { ROOT_STORE } from '@/store/constants'
|
||||
import type { IRootActions, IRootState } from '@/store/modules/root/types'
|
||||
import type { TAppConfigForm } from '@/types/application'
|
||||
import type { TLanguage } from '@/types/locales'
|
||||
import { handleError } from '@/utils'
|
||||
|
||||
const { locale } = createI18n.global
|
||||
@ -91,7 +92,7 @@ export const actions: ActionTree<IRootState, IRootState> & IRootActions = {
|
||||
},
|
||||
[ROOT_STORE.ACTIONS.UPDATE_APPLICATION_LANGUAGE](
|
||||
context: ActionContext<IRootState, IRootState>,
|
||||
language: string
|
||||
language: TLanguage
|
||||
): void {
|
||||
document.querySelector('html')?.setAttribute('lang', language)
|
||||
context.commit(ROOT_STORE.MUTATIONS.UPDATE_LANG, language)
|
||||
|
@ -3,6 +3,7 @@ import type { MutationTree } from 'vuex'
|
||||
import { ROOT_STORE } from '@/store/constants'
|
||||
import type { IRootState, TRootMutations } from '@/store/modules/root/types'
|
||||
import type { TAppConfig, IAppStatistics } from '@/types/application'
|
||||
import type { TLanguage } from '@/types/locales'
|
||||
import { localeFromLanguage } from '@/utils/locales'
|
||||
|
||||
export const mutations: MutationTree<IRootState> & TRootMutations = {
|
||||
@ -40,7 +41,7 @@ export const mutations: MutationTree<IRootState> & TRootMutations = {
|
||||
) {
|
||||
state.application.statistics = statistics
|
||||
},
|
||||
[ROOT_STORE.MUTATIONS.UPDATE_LANG](state: IRootState, language: string) {
|
||||
[ROOT_STORE.MUTATIONS.UPDATE_LANG](state: IRootState, language: TLanguage) {
|
||||
state.language = language
|
||||
state.locale = localeFromLanguage[language]
|
||||
},
|
||||
|
@ -13,10 +13,11 @@ import type {
|
||||
IAppStatistics,
|
||||
TAppConfigForm,
|
||||
} from '@/types/application'
|
||||
import type { TLanguage } from '@/types/locales'
|
||||
|
||||
export interface IRootState {
|
||||
root: boolean
|
||||
language: string
|
||||
language: TLanguage
|
||||
locale: Locale
|
||||
errorMessages: string | string[] | null
|
||||
application: IApplication
|
||||
@ -39,7 +40,7 @@ export interface IRootActions {
|
||||
): void
|
||||
[ROOT_STORE.ACTIONS.UPDATE_APPLICATION_LANGUAGE](
|
||||
context: ActionContext<IRootState, IRootState>,
|
||||
langauge: string
|
||||
language: TLanguage
|
||||
): void
|
||||
}
|
||||
|
||||
@ -54,7 +55,7 @@ export interface IRootGetters {
|
||||
state: IRootState
|
||||
): string | string[] | null
|
||||
|
||||
[ROOT_STORE.GETTERS.LANGUAGE](state: IRootState): string
|
||||
[ROOT_STORE.GETTERS.LANGUAGE](state: IRootState): TLanguage
|
||||
|
||||
[ROOT_STORE.GETTERS.LOCALE](state: IRootState): Locale
|
||||
}
|
||||
@ -81,7 +82,7 @@ export type TRootMutations<S = IRootState> = {
|
||||
state: S,
|
||||
statistics: IAppStatistics
|
||||
): void
|
||||
[ROOT_STORE.MUTATIONS.UPDATE_LANG](state: S, language: string): void
|
||||
[ROOT_STORE.MUTATIONS.UPDATE_LANG](state: S, language: TLanguage): void
|
||||
}
|
||||
|
||||
export type TRootStoreModule<S = IRootState> = Omit<
|
||||
|
@ -37,3 +37,8 @@ export type TAppConfigForm = {
|
||||
max_zip_file_size: number
|
||||
privacy_policy: string
|
||||
}
|
||||
|
||||
export interface IFileSize {
|
||||
size: string
|
||||
suffix: string
|
||||
}
|
||||
|
10
fittrackee_client/src/types/locales.ts
Normal file
10
fittrackee_client/src/types/locales.ts
Normal file
@ -0,0 +1,10 @@
|
||||
export type TLanguage =
|
||||
| 'en'
|
||||
| 'de'
|
||||
| 'es'
|
||||
| 'fr'
|
||||
| 'gl'
|
||||
| 'it'
|
||||
| 'nb'
|
||||
| 'nl'
|
||||
| 'pl'
|
@ -1,5 +1,6 @@
|
||||
import type { LocationQueryValue } from 'vue-router'
|
||||
|
||||
import type { TLanguage } from '@/types/locales'
|
||||
import type { IRecord } from '@/types/workouts'
|
||||
|
||||
export interface IUserProfile {
|
||||
@ -30,7 +31,7 @@ export interface IAuthUserProfile extends IUserProfile {
|
||||
imperial_units: boolean
|
||||
start_elevation_at_zero: boolean
|
||||
use_raw_gpx_speed: boolean
|
||||
language: string | null
|
||||
language: TLanguage | null
|
||||
timezone: string
|
||||
date_format: string
|
||||
weekm: boolean
|
||||
@ -68,7 +69,7 @@ export interface IUserPreferencesPayload {
|
||||
start_elevation_at_zero: boolean
|
||||
use_raw_gpx_speed: boolean
|
||||
imperial_units: boolean
|
||||
language: string
|
||||
language: TLanguage
|
||||
timezone: string
|
||||
date_format: string
|
||||
weekm: boolean
|
||||
|
@ -34,10 +34,10 @@ export interface IRecord {
|
||||
}
|
||||
|
||||
export interface IRecordsBySport {
|
||||
[key: string]: string | Record<string, string | number>[] | null
|
||||
[key: string]: string | IRecord[] | null
|
||||
label: string
|
||||
color: string | null
|
||||
records: Record<string, string | number>[]
|
||||
records: IRecord[]
|
||||
}
|
||||
|
||||
export interface IRecordsBySports {
|
||||
@ -59,8 +59,8 @@ export interface IWorkout {
|
||||
bounds: number[]
|
||||
creation_date: string
|
||||
descent: number | null
|
||||
distance: number | null
|
||||
duration: string | null
|
||||
distance: number
|
||||
duration: string
|
||||
id: string
|
||||
map: string | null
|
||||
max_alt: number | null
|
||||
|
@ -12,6 +12,7 @@ import {
|
||||
import { utcToZonedTime } from 'date-fns-tz'
|
||||
|
||||
import createI18n from '@/i18n'
|
||||
import type { TLanguage } from '@/types/locales'
|
||||
import { localeFromLanguage } from '@/utils/locales'
|
||||
|
||||
const { locale } = createI18n.global
|
||||
@ -114,7 +115,7 @@ export const formatDate = (
|
||||
timezone: string,
|
||||
dateFormat: string,
|
||||
withTime = true,
|
||||
language: string | null = null,
|
||||
language: TLanguage | null = null,
|
||||
withSeconds = false
|
||||
): string => {
|
||||
if (!language) {
|
||||
@ -131,9 +132,9 @@ export const formatDate = (
|
||||
export const availableDateFormatOptions = (
|
||||
inputDate: string,
|
||||
timezone: string,
|
||||
language: string | null = null
|
||||
language: TLanguage | null = null
|
||||
) => {
|
||||
const l: string = language ? language : locale.value
|
||||
const l: TLanguage = language ? language : locale.value
|
||||
const options: Record<string, string>[] = []
|
||||
availableDateFormats.map((df) => {
|
||||
const dateFormat = getDateFormat(df, l)
|
||||
|
@ -1,16 +1,23 @@
|
||||
import type { IFileSize } from '@/types/application'
|
||||
|
||||
const suffixes = ['bytes', 'KB', 'MB', 'GB', 'TB']
|
||||
|
||||
export const getReadableFileSize = (
|
||||
fileSize: number,
|
||||
asText = true
|
||||
): string | Record<string, string> => {
|
||||
const i = Math.floor(Math.log(fileSize) / Math.log(1024))
|
||||
export const getReadableFileSize = (fileSize: number): IFileSize => {
|
||||
if (!fileSize) {
|
||||
return asText ? '0 bytes' : { size: '0', suffix: 'bytes' }
|
||||
return { size: '0', suffix: 'bytes' }
|
||||
}
|
||||
const i = Math.floor(Math.log(fileSize) / Math.log(1024))
|
||||
const size = (fileSize / Math.pow(1024, i)).toFixed(1)
|
||||
const suffix = suffixes[i]
|
||||
return asText ? `${size}${suffix}` : { size, suffix }
|
||||
return { size, suffix }
|
||||
}
|
||||
|
||||
export const getReadableFileSizeAsText = (fileSize: number): string => {
|
||||
if (!fileSize) {
|
||||
return '0 bytes'
|
||||
}
|
||||
const readableFileSize = getReadableFileSize(fileSize)
|
||||
return `${readableFileSize.size}${readableFileSize.suffix}`
|
||||
}
|
||||
|
||||
export const getFileSizeInMB = (fileSize: number): number => {
|
||||
|
@ -2,20 +2,37 @@ import type { Locale } from 'date-fns'
|
||||
import { de, enUS, es, fr, gl, it, nb, nl, pl } from 'date-fns/locale'
|
||||
|
||||
import createI18n from '@/i18n'
|
||||
import type { TLanguage } from '@/types/locales'
|
||||
|
||||
export const localeFromLanguage: Record<string, Locale> = {
|
||||
export const isLanguageSupported = (
|
||||
language: string
|
||||
): language is TLanguage => {
|
||||
return (
|
||||
language === 'de' ||
|
||||
language === 'en' ||
|
||||
language === 'es' ||
|
||||
language === 'fr' ||
|
||||
language === 'gl' ||
|
||||
language === 'it' ||
|
||||
language === 'nb' ||
|
||||
language === 'nl' ||
|
||||
language === 'pl'
|
||||
)
|
||||
}
|
||||
|
||||
export const localeFromLanguage: Record<TLanguage, Locale> = {
|
||||
de: de,
|
||||
en: enUS,
|
||||
es: es,
|
||||
fr: fr,
|
||||
gl: gl,
|
||||
it: it,
|
||||
pl: pl,
|
||||
nb: nb,
|
||||
nl: nl,
|
||||
pl: pl,
|
||||
}
|
||||
|
||||
export const languageLabels: Record<string, string> = {
|
||||
export const languageLabels: Record<TLanguage, string> = {
|
||||
de: 'Deutsch',
|
||||
en: 'English',
|
||||
es: 'Español',
|
||||
|
@ -12,7 +12,7 @@ export const formatRecord = (
|
||||
tz: string,
|
||||
useImperialUnits: boolean,
|
||||
date_format: string
|
||||
): Record<string, string | number> => {
|
||||
): IRecord => {
|
||||
const distanceUnitFrom: TUnit = 'km'
|
||||
const distanceUnitTo: TUnit = useImperialUnits
|
||||
? units[distanceUnitFrom].defaultTarget
|
||||
@ -57,11 +57,13 @@ export const formatRecord = (
|
||||
)
|
||||
}
|
||||
return {
|
||||
workout_date: formatDate(record.workout_date, tz, date_format, false),
|
||||
workout_id: record.workout_id,
|
||||
id: record.id,
|
||||
record_type: record.record_type,
|
||||
sport_id: record.sport_id,
|
||||
value: value,
|
||||
user: record.user,
|
||||
workout_date: formatDate(record.workout_date, tz, date_format, false),
|
||||
workout_id: record.workout_id,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
const router = useRouter()
|
||||
|
||||
const { action } = toRefs(props)
|
||||
const token = computed(() => route.query.token)
|
||||
const token = computed(() => route.query.token as string)
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (props.action === 'reset' && !token.value) {
|
||||
|
@ -1,8 +1,12 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
|
||||
import { getFileSizeInMB, getReadableFileSize } from '@/utils/files'
|
||||
import {
|
||||
getFileSizeInMB,
|
||||
getReadableFileSize,
|
||||
getReadableFileSizeAsText,
|
||||
} from '@/utils/files'
|
||||
|
||||
describe('getReadableFileSize (as text)', () => {
|
||||
describe('getReadableFileSizeAsText', () => {
|
||||
const testsParams = [
|
||||
{
|
||||
description: 'returns 0 bytes if provided file size is 0',
|
||||
@ -23,7 +27,7 @@ describe('getReadableFileSize (as text)', () => {
|
||||
|
||||
testsParams.map((testParams) => {
|
||||
it(testParams.description, () => {
|
||||
expect(getReadableFileSize(testParams.inputFileSize, true)).toStrictEqual(
|
||||
expect(getReadableFileSizeAsText(testParams.inputFileSize)).toStrictEqual(
|
||||
testParams.expectedReadableFileSize
|
||||
)
|
||||
})
|
||||
@ -51,9 +55,9 @@ describe('getReadableFileSize (as object)', () => {
|
||||
|
||||
testsParams.map((testParams) => {
|
||||
it(testParams.description, () => {
|
||||
expect(
|
||||
getReadableFileSize(testParams.inputFileSize, false)
|
||||
).toStrictEqual(testParams.expectedReadableFileSize)
|
||||
expect(getReadableFileSize(testParams.inputFileSize)).toStrictEqual(
|
||||
testParams.expectedReadableFileSize
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -24,6 +24,8 @@ describe('formatRecord', () => {
|
||||
expected: {
|
||||
id: 9,
|
||||
record_type: 'AS',
|
||||
sport_id: 1,
|
||||
user: 'admin',
|
||||
value: '18 km/h',
|
||||
workout_date: '2019/07/07',
|
||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||
@ -47,6 +49,8 @@ describe('formatRecord', () => {
|
||||
expected: {
|
||||
id: 10,
|
||||
record_type: 'FD',
|
||||
sport_id: 1,
|
||||
user: 'admin',
|
||||
value: '18 km',
|
||||
workout_date: '2019/07/08',
|
||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||
@ -70,6 +74,8 @@ describe('formatRecord', () => {
|
||||
expected: {
|
||||
id: 11,
|
||||
record_type: 'LD',
|
||||
sport_id: 1,
|
||||
user: 'admin',
|
||||
value: '1:01:00',
|
||||
workout_date: '2019/07/07',
|
||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||
@ -93,6 +99,8 @@ describe('formatRecord', () => {
|
||||
expected: {
|
||||
id: 12,
|
||||
record_type: 'MS',
|
||||
sport_id: 1,
|
||||
user: 'admin',
|
||||
value: '18 km/h',
|
||||
workout_date: '08/07/2019',
|
||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||
@ -116,6 +124,8 @@ describe('formatRecord', () => {
|
||||
expected: {
|
||||
id: 13,
|
||||
record_type: 'HA',
|
||||
sport_id: 1,
|
||||
user: 'admin',
|
||||
value: '100 m',
|
||||
workout_date: 'Jul. 7th, 2019',
|
||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||
@ -156,6 +166,8 @@ describe('formatRecord after conversion', () => {
|
||||
expected: {
|
||||
id: 9,
|
||||
record_type: 'AS',
|
||||
sport_id: 1,
|
||||
user: 'admin',
|
||||
value: '11.18 mi/h',
|
||||
workout_date: '2019/07/07',
|
||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||
@ -179,6 +191,8 @@ describe('formatRecord after conversion', () => {
|
||||
expected: {
|
||||
id: 10,
|
||||
record_type: 'FD',
|
||||
sport_id: 1,
|
||||
user: 'admin',
|
||||
value: '11.185 mi',
|
||||
workout_date: '2019/08/07',
|
||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||
@ -202,6 +216,8 @@ describe('formatRecord after conversion', () => {
|
||||
expected: {
|
||||
id: 11,
|
||||
record_type: 'LD',
|
||||
sport_id: 1,
|
||||
user: 'admin',
|
||||
value: '1:01:00',
|
||||
workout_date: '2019/07/07',
|
||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||
@ -225,6 +241,8 @@ describe('formatRecord after conversion', () => {
|
||||
expected: {
|
||||
id: 12,
|
||||
record_type: 'MS',
|
||||
sport_id: 1,
|
||||
user: 'admin',
|
||||
value: '11.18 mi/h',
|
||||
workout_date: '2019/08/07',
|
||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||
@ -248,6 +266,8 @@ describe('formatRecord after conversion', () => {
|
||||
expected: {
|
||||
id: 13,
|
||||
record_type: 'HA',
|
||||
sport_id: 1,
|
||||
user: 'admin',
|
||||
value: '328.08 ft',
|
||||
workout_date: '2019/07/07',
|
||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||
@ -327,6 +347,8 @@ describe('getRecordsBySports', () => {
|
||||
{
|
||||
id: 9,
|
||||
record_type: 'AS',
|
||||
sport_id: 1,
|
||||
user: 'admin',
|
||||
value: '18 km/h',
|
||||
workout_date: '2019/07/07',
|
||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||
@ -378,6 +400,8 @@ describe('getRecordsBySports', () => {
|
||||
{
|
||||
id: 9,
|
||||
record_type: 'AS',
|
||||
sport_id: 1,
|
||||
user: 'admin',
|
||||
value: '18 km/h',
|
||||
workout_date: '2019/07/07',
|
||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||
@ -385,6 +409,8 @@ describe('getRecordsBySports', () => {
|
||||
{
|
||||
id: 12,
|
||||
record_type: 'MS',
|
||||
sport_id: 1,
|
||||
user: 'admin',
|
||||
value: '18 km/h',
|
||||
workout_date: '2019/07/07',
|
||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||
@ -398,6 +424,8 @@ describe('getRecordsBySports', () => {
|
||||
{
|
||||
id: 10,
|
||||
record_type: 'FD',
|
||||
sport_id: 2,
|
||||
user: 'admin',
|
||||
value: '18 km',
|
||||
workout_date: '2019/08/07',
|
||||
workout_id: 'n6JcLPQt3QtZWFfiSnYm4C',
|
||||
@ -459,6 +487,8 @@ describe('getRecordsBySports after conversion', () => {
|
||||
{
|
||||
id: 9,
|
||||
record_type: 'AS',
|
||||
sport_id: 1,
|
||||
user: 'admin',
|
||||
value: '11.18 mi/h',
|
||||
workout_date: '2019/07/07',
|
||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||
@ -510,6 +540,8 @@ describe('getRecordsBySports after conversion', () => {
|
||||
{
|
||||
id: 9,
|
||||
record_type: 'AS',
|
||||
sport_id: 1,
|
||||
user: 'admin',
|
||||
value: '11.18 mi/h',
|
||||
workout_date: '2019/07/07',
|
||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||
@ -517,6 +549,8 @@ describe('getRecordsBySports after conversion', () => {
|
||||
{
|
||||
id: 12,
|
||||
record_type: 'MS',
|
||||
sport_id: 1,
|
||||
user: 'admin',
|
||||
value: '11.18 mi/h',
|
||||
workout_date: '2019/07/07',
|
||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||
@ -530,6 +564,8 @@ describe('getRecordsBySports after conversion', () => {
|
||||
{
|
||||
id: 10,
|
||||
record_type: 'FD',
|
||||
sport_id: 2,
|
||||
user: 'admin',
|
||||
value: '11.185 mi',
|
||||
workout_date: '2019/08/07',
|
||||
workout_id: 'n6JcLPQt3QtZWFfiSnYm4C',
|
||||
@ -600,6 +636,8 @@ describe('getRecordsBySports with HA record', () => {
|
||||
{
|
||||
id: 9,
|
||||
record_type: 'AS',
|
||||
sport_id: 1,
|
||||
user: 'admin',
|
||||
value: '18 km/h',
|
||||
workout_date: '2019/07/07',
|
||||
workout_id: 'hvYBqYBRa7wwXpaStWR4V2',
|
||||
|
Loading…
Reference in New Issue
Block a user