Client - application translation
This commit is contained in:
parent
77bc32d4a5
commit
131f315911
@ -11,6 +11,7 @@ export default function ActivityCardHeader(props) {
|
|||||||
displayModal,
|
displayModal,
|
||||||
segmentId,
|
segmentId,
|
||||||
sport,
|
sport,
|
||||||
|
t,
|
||||||
title,
|
title,
|
||||||
user,
|
user,
|
||||||
} = props
|
} = props
|
||||||
@ -40,14 +41,14 @@ export default function ActivityCardHeader(props) {
|
|||||||
<i
|
<i
|
||||||
className="fa fa-chevron-left"
|
className="fa fa-chevron-left"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
title={`See previous ${dataType}`}
|
title={t(`activities:See previous ${dataType}`)}
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<i
|
<i
|
||||||
className="fa fa-chevron-left inactive-link"
|
className="fa fa-chevron-left inactive-link"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
title={`No previous ${dataType}`}
|
title={t(`activities:No previous ${dataType}`)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -62,14 +63,14 @@ export default function ActivityCardHeader(props) {
|
|||||||
<i
|
<i
|
||||||
className="fa fa-edit custom-fa"
|
className="fa fa-edit custom-fa"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
title="Edit activity"
|
title={t('activities:Edit activity')}
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<i
|
<i
|
||||||
className="fa fa-trash custom-fa"
|
className="fa fa-trash custom-fa"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
onClick={() => displayModal(true)}
|
onClick={() => displayModal(true)}
|
||||||
title="Delete activity"
|
title={t('activities:Delete activity')}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
@ -80,7 +81,7 @@ export default function ActivityCardHeader(props) {
|
|||||||
>
|
>
|
||||||
{title}
|
{title}
|
||||||
</Link>{' '}
|
</Link>{' '}
|
||||||
- segment {segmentId}
|
- {t('activities:segment')} {segmentId}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<br />
|
<br />
|
||||||
@ -96,14 +97,14 @@ export default function ActivityCardHeader(props) {
|
|||||||
<i
|
<i
|
||||||
className="fa fa-chevron-right"
|
className="fa fa-chevron-right"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
title={`See next ${dataType}`}
|
title={t(`activities:See next ${dataType}`)}
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<i
|
<i
|
||||||
className="fa fa-chevron-right inactive-link"
|
className="fa fa-chevron-right inactive-link"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
title={`No next ${dataType}`}
|
title={t(`activities:No next ${dataType}`)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -79,7 +79,7 @@ class ActivityCharts extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { chartData, updateCoordinates } = this.props
|
const { chartData, t, updateCoordinates } = this.props
|
||||||
const { displayDistance } = this.state
|
const { displayDistance } = this.state
|
||||||
const xInterval = chartData ? parseInt(chartData.length / 10, 10) : 0
|
const xInterval = chartData ? parseInt(chartData.length / 10, 10) : 0
|
||||||
let xDataKey, xScale
|
let xDataKey, xScale
|
||||||
@ -102,7 +102,7 @@ class ActivityCharts extends React.Component {
|
|||||||
checked={displayDistance}
|
checked={displayDistance}
|
||||||
onChange={e => this.handleRadioChange(e)}
|
onChange={e => this.handleRadioChange(e)}
|
||||||
/>
|
/>
|
||||||
distance
|
{t('activities:distance')}
|
||||||
</label>
|
</label>
|
||||||
<label className="radioLabel col-md-1">
|
<label className="radioLabel col-md-1">
|
||||||
<input
|
<input
|
||||||
@ -111,7 +111,7 @@ class ActivityCharts extends React.Component {
|
|||||||
checked={!displayDistance}
|
checked={!displayDistance}
|
||||||
onChange={e => this.handleRadioChange(e)}
|
onChange={e => this.handleRadioChange(e)}
|
||||||
/>
|
/>
|
||||||
duration
|
{t('activities:duration')}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="row chart-radio">
|
<div className="row chart-radio">
|
||||||
@ -123,7 +123,7 @@ class ActivityCharts extends React.Component {
|
|||||||
checked={this.displayData('speed')}
|
checked={this.displayData('speed')}
|
||||||
onChange={e => this.handleLegendChange(e)}
|
onChange={e => this.handleLegendChange(e)}
|
||||||
/>
|
/>
|
||||||
speed
|
{t('activities:speed')}
|
||||||
</label>
|
</label>
|
||||||
<label className="radioLabel col-md-1">
|
<label className="radioLabel col-md-1">
|
||||||
<input
|
<input
|
||||||
@ -132,7 +132,7 @@ class ActivityCharts extends React.Component {
|
|||||||
checked={this.displayData('elevation')}
|
checked={this.displayData('elevation')}
|
||||||
onChange={e => this.handleLegendChange(e)}
|
onChange={e => this.handleLegendChange(e)}
|
||||||
/>
|
/>
|
||||||
elevation
|
{t('activities:elevation')}
|
||||||
</label>
|
</label>
|
||||||
<div className="col-md-5" />
|
<div className="col-md-5" />
|
||||||
</div>
|
</div>
|
||||||
@ -147,7 +147,11 @@ class ActivityCharts extends React.Component {
|
|||||||
<XAxis
|
<XAxis
|
||||||
allowDecimals={false}
|
allowDecimals={false}
|
||||||
dataKey={xDataKey}
|
dataKey={xDataKey}
|
||||||
label={{ value: xDataKey, offset: 0, position: 'bottom' }}
|
label={{
|
||||||
|
value: t(`activities:${xDataKey}`),
|
||||||
|
offset: 0,
|
||||||
|
position: 'bottom',
|
||||||
|
}}
|
||||||
scale={xScale}
|
scale={xScale}
|
||||||
interval={xInterval}
|
interval={xInterval}
|
||||||
tickFormatter={value =>
|
tickFormatter={value =>
|
||||||
@ -157,7 +161,7 @@ class ActivityCharts extends React.Component {
|
|||||||
/>
|
/>
|
||||||
<YAxis
|
<YAxis
|
||||||
label={{
|
label={{
|
||||||
value: 'speed (km/h)',
|
value: `${t('activities:speed')} (km/h)`,
|
||||||
angle: -90,
|
angle: -90,
|
||||||
position: 'left',
|
position: 'left',
|
||||||
}}
|
}}
|
||||||
@ -165,7 +169,7 @@ class ActivityCharts extends React.Component {
|
|||||||
/>
|
/>
|
||||||
<YAxis
|
<YAxis
|
||||||
label={{
|
label={{
|
||||||
value: 'altitude (m)',
|
value: `${t('activities:elevation')} (m)`,
|
||||||
angle: -90,
|
angle: -90,
|
||||||
position: 'right',
|
position: 'right',
|
||||||
}}
|
}}
|
||||||
@ -177,6 +181,7 @@ class ActivityCharts extends React.Component {
|
|||||||
yAxisId="right"
|
yAxisId="right"
|
||||||
type="linear"
|
type="linear"
|
||||||
dataKey="elevation"
|
dataKey="elevation"
|
||||||
|
name={t('activities:elevation')}
|
||||||
fill="#e5e5e5"
|
fill="#e5e5e5"
|
||||||
stroke="#cccccc"
|
stroke="#cccccc"
|
||||||
dot={false}
|
dot={false}
|
||||||
@ -188,6 +193,7 @@ class ActivityCharts extends React.Component {
|
|||||||
yAxisId="left"
|
yAxisId="left"
|
||||||
type="linear"
|
type="linear"
|
||||||
dataKey="speed"
|
dataKey="speed"
|
||||||
|
name={t('activities:speed')}
|
||||||
stroke="#8884d8"
|
stroke="#8884d8"
|
||||||
strokeWidth={2}
|
strokeWidth={2}
|
||||||
dot={false}
|
dot={false}
|
||||||
@ -197,19 +203,22 @@ class ActivityCharts extends React.Component {
|
|||||||
<Tooltip
|
<Tooltip
|
||||||
labelFormatter={value =>
|
labelFormatter={value =>
|
||||||
displayDistance
|
displayDistance
|
||||||
? `distance: ${value} km`
|
? `${t('activities:distance')}: ${value} km`
|
||||||
: `duration: ${format(value, 'HH:mm:ss')}`
|
: `${t('activities:duration')}: ${format(
|
||||||
|
value,
|
||||||
|
'HH:mm:ss'
|
||||||
|
)}`
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</ComposedChart>
|
</ComposedChart>
|
||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
</div>
|
</div>
|
||||||
<div className="chart-info">
|
<div className="chart-info">
|
||||||
data from gpx, without any cleaning
|
{t('activities:data from gpx, without any cleaning')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
'No data to display'
|
t('activities:No data to display')
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -3,13 +3,13 @@ import React from 'react'
|
|||||||
import ActivityWeather from './ActivityWeather'
|
import ActivityWeather from './ActivityWeather'
|
||||||
|
|
||||||
export default function ActivityDetails(props) {
|
export default function ActivityDetails(props) {
|
||||||
const { activity } = props
|
const { activity, t } = props
|
||||||
const withPauses = activity.pauses !== '0:00:00' && activity.pauses !== null
|
const withPauses = activity.pauses !== '0:00:00' && activity.pauses !== null
|
||||||
return (
|
return (
|
||||||
<div className="activity-details">
|
<div className="activity-details">
|
||||||
<p>
|
<p>
|
||||||
<i className="fa fa-clock-o custom-fa" aria-hidden="true" />
|
<i className="fa fa-clock-o custom-fa" aria-hidden="true" />
|
||||||
Duration: {activity.moving}
|
{t('activities:Duration')}: {activity.moving}
|
||||||
{activity.records &&
|
{activity.records &&
|
||||||
activity.records.find(r => r.record_type === 'LD') && (
|
activity.records.find(r => r.record_type === 'LD') && (
|
||||||
<sup>
|
<sup>
|
||||||
@ -18,14 +18,14 @@ export default function ActivityDetails(props) {
|
|||||||
)}
|
)}
|
||||||
{withPauses && (
|
{withPauses && (
|
||||||
<span>
|
<span>
|
||||||
<br />
|
<br />({t('activities:pauses')}: {activity.pauses},{' '}
|
||||||
(pauses: {activity.pauses}, total duration: {activity.duration})
|
{t('activities:total duration')}: {activity.duration})
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<i className="fa fa-road custom-fa" aria-hidden="true" />
|
<i className="fa fa-road custom-fa" aria-hidden="true" />
|
||||||
Distance: {activity.distance} km
|
{t('activities:Distance')}: {activity.distance} km
|
||||||
{activity.records &&
|
{activity.records &&
|
||||||
activity.records.find(r => r.record_type === 'FD') && (
|
activity.records.find(r => r.record_type === 'FD') && (
|
||||||
<sup>
|
<sup>
|
||||||
@ -35,7 +35,7 @@ export default function ActivityDetails(props) {
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<i className="fa fa-tachometer custom-fa" aria-hidden="true" />
|
<i className="fa fa-tachometer custom-fa" aria-hidden="true" />
|
||||||
Average speed: {activity.ave_speed} km/h
|
{t('activities:Average speed')}: {activity.ave_speed} km/h
|
||||||
{activity.records &&
|
{activity.records &&
|
||||||
activity.records.find(r => r.record_type === 'AS') && (
|
activity.records.find(r => r.record_type === 'AS') && (
|
||||||
<sup>
|
<sup>
|
||||||
@ -43,7 +43,7 @@ export default function ActivityDetails(props) {
|
|||||||
</sup>
|
</sup>
|
||||||
)}
|
)}
|
||||||
<br />
|
<br />
|
||||||
Max speed : {activity.max_speed} km/h
|
{t('activities:Max. speed')}: {activity.max_speed} km/h
|
||||||
{activity.records &&
|
{activity.records &&
|
||||||
activity.records.find(r => r.record_type === 'MS') && (
|
activity.records.find(r => r.record_type === 'MS') && (
|
||||||
<sup>
|
<sup>
|
||||||
@ -54,20 +54,20 @@ export default function ActivityDetails(props) {
|
|||||||
{activity.min_alt && activity.max_alt && (
|
{activity.min_alt && activity.max_alt && (
|
||||||
<p>
|
<p>
|
||||||
<i className="fi-mountains custom-fa" />
|
<i className="fi-mountains custom-fa" />
|
||||||
Min altitude: {activity.min_alt}m
|
{t('activities:Min. altitude')}: {activity.min_alt}m
|
||||||
<br />
|
<br />
|
||||||
Max altitude: {activity.max_alt}m
|
{t('activities:Max. altitude')}: {activity.max_alt}m
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{activity.ascent && activity.descent && (
|
{activity.ascent && activity.descent && (
|
||||||
<p>
|
<p>
|
||||||
<i className="fa fa-location-arrow custom-fa" />
|
<i className="fa fa-location-arrow custom-fa" />
|
||||||
Ascent: {activity.ascent}m
|
{t('activities:Ascent')}: {activity.ascent}m
|
||||||
<br />
|
<br />
|
||||||
Descent: {activity.descent}m
|
{t('activities:Descent')}: {activity.descent}m
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
<ActivityWeather activity={activity} />
|
<ActivityWeather activity={activity} t={t} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
export default function ActivityNoMap() {
|
export default function ActivityNoMap(props) {
|
||||||
return <div className="activity-no-map text-center">No Map</div>
|
const { t } = props
|
||||||
|
return (
|
||||||
|
<div className="activity-no-map text-center">{t('activities:No Map')}</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
export default function ActivityNotes(props) {
|
export default function ActivityNotes(props) {
|
||||||
const { notes } = props
|
const { notes, t } = props
|
||||||
return (
|
return (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col">
|
<div className="col">
|
||||||
<div className="card activity-card">
|
<div className="card activity-card">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
Notes
|
Notes
|
||||||
<div className="activity-notes">{notes ? notes : 'No notes'}</div>
|
<div className="activity-notes">
|
||||||
|
{notes ? notes : t('activities:No notes')}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,13 +2,13 @@ import React from 'react'
|
|||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
|
|
||||||
export default function ActivitySegments(props) {
|
export default function ActivitySegments(props) {
|
||||||
const { segments } = props
|
const { segments, t } = props
|
||||||
return (
|
return (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col">
|
<div className="col">
|
||||||
<div className="card activity-card">
|
<div className="card activity-card">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
Segments
|
{t('activities:Segments')}
|
||||||
<div className="activity-segments">
|
<div className="activity-segments">
|
||||||
<ul>
|
<ul>
|
||||||
{segments.map((segment, index) => (
|
{segments.map((segment, index) => (
|
||||||
@ -21,9 +21,10 @@ export default function ActivitySegments(props) {
|
|||||||
to={`/activities/${segment.activity_id}/segment/${index +
|
to={`/activities/${segment.activity_id}/segment/${index +
|
||||||
1}`}
|
1}`}
|
||||||
>
|
>
|
||||||
segment {index + 1}
|
{t('activities:segment')} {index + 1}
|
||||||
</Link>{' '}
|
</Link>{' '}
|
||||||
({segment.distance} km, duration: {segment.duration})
|
({t('activities:distance')}: {segment.distance} km,{' '}
|
||||||
|
{t('activities:duration')}: {segment.duration})
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
export default function ActivityWeather(props) {
|
export default function ActivityWeather(props) {
|
||||||
const { activity } = props
|
const { activity, t } = props
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
{activity.weather_start && activity.weather_end && (
|
{activity.weather_start && activity.weather_end && (
|
||||||
@ -10,7 +10,7 @@ export default function ActivityWeather(props) {
|
|||||||
<tr>
|
<tr>
|
||||||
<th />
|
<th />
|
||||||
<th>
|
<th>
|
||||||
Start
|
{t('activities:Start')}
|
||||||
<br />
|
<br />
|
||||||
<img
|
<img
|
||||||
className="weather-img"
|
className="weather-img"
|
||||||
@ -20,7 +20,7 @@ export default function ActivityWeather(props) {
|
|||||||
/>
|
/>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
End
|
{t('activities:End')}
|
||||||
<br />
|
<br />
|
||||||
<img
|
<img
|
||||||
className="weather-img"
|
className="weather-img"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Helmet } from 'react-helmet'
|
import { Helmet } from 'react-helmet'
|
||||||
|
import { withTranslation } from 'react-i18next'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
|
|
||||||
import ActivityCardHeader from './ActivityCardHeader'
|
import ActivityCardHeader from './ActivityCardHeader'
|
||||||
@ -62,7 +63,14 @@ class ActivityDisplay extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { activities, message, onDeleteActivity, sports, user } = this.props
|
const {
|
||||||
|
activities,
|
||||||
|
message,
|
||||||
|
onDeleteActivity,
|
||||||
|
sports,
|
||||||
|
t,
|
||||||
|
user,
|
||||||
|
} = this.props
|
||||||
const { coordinates, displayModal } = this.state
|
const { coordinates, displayModal } = this.state
|
||||||
const [activity] = activities
|
const [activity] = activities
|
||||||
const title = activity ? activity.title : 'Activity'
|
const title = activity ? activity.title : 'Activity'
|
||||||
@ -82,8 +90,10 @@ class ActivityDisplay extends React.Component {
|
|||||||
<div className="container">
|
<div className="container">
|
||||||
{displayModal && (
|
{displayModal && (
|
||||||
<CustomModal
|
<CustomModal
|
||||||
title="Confirmation"
|
title={t('activities:Confirmation')}
|
||||||
text="Are you sure you want to delete this activity?"
|
text={t(
|
||||||
|
'activities:Are you sure you want to delete this activity?'
|
||||||
|
)}
|
||||||
confirm={() => {
|
confirm={() => {
|
||||||
onDeleteActivity(activity.id)
|
onDeleteActivity(activity.id)
|
||||||
this.displayModal(false)
|
this.displayModal(false)
|
||||||
@ -102,6 +112,7 @@ class ActivityDisplay extends React.Component {
|
|||||||
dataType={dataType}
|
dataType={dataType}
|
||||||
segmentId={segmentId}
|
segmentId={segmentId}
|
||||||
sport={sport}
|
sport={sport}
|
||||||
|
t={t}
|
||||||
title={title}
|
title={title}
|
||||||
user={user}
|
user={user}
|
||||||
displayModal={() => this.displayModal(true)}
|
displayModal={() => this.displayModal(true)}
|
||||||
@ -118,7 +129,7 @@ class ActivityDisplay extends React.Component {
|
|||||||
segmentId={segmentId}
|
segmentId={segmentId}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<ActivityNoMap />
|
<ActivityNoMap t={t} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="col">
|
<div className="col">
|
||||||
@ -128,6 +139,7 @@ class ActivityDisplay extends React.Component {
|
|||||||
? activity
|
? activity
|
||||||
: activity.segments[segmentId - 1]
|
: activity.segments[segmentId - 1]
|
||||||
}
|
}
|
||||||
|
t={t}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -147,6 +159,7 @@ class ActivityDisplay extends React.Component {
|
|||||||
activity={activity}
|
activity={activity}
|
||||||
dataType={dataType}
|
dataType={dataType}
|
||||||
segmentId={segmentId}
|
segmentId={segmentId}
|
||||||
|
t={t}
|
||||||
updateCoordinates={e =>
|
updateCoordinates={e =>
|
||||||
this.updateCoordinates(e)
|
this.updateCoordinates(e)
|
||||||
}
|
}
|
||||||
@ -160,9 +173,9 @@ class ActivityDisplay extends React.Component {
|
|||||||
)}
|
)}
|
||||||
{dataType === 'activity' && (
|
{dataType === 'activity' && (
|
||||||
<>
|
<>
|
||||||
<ActivityNotes notes={activity.notes} />
|
<ActivityNotes notes={activity.notes} t={t} />
|
||||||
{activity.segments.length > 1 && (
|
{activity.segments.length > 1 && (
|
||||||
<ActivitySegments segments={activity.segments} />
|
<ActivitySegments segments={activity.segments} t={t} />
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@ -175,7 +188,8 @@ class ActivityDisplay extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
export default withTranslation()(
|
||||||
|
connect(
|
||||||
state => ({
|
state => ({
|
||||||
activities: state.activities.data,
|
activities: state.activities.data,
|
||||||
message: state.message,
|
message: state.message,
|
||||||
@ -191,3 +205,4 @@ export default connect(
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
)(ActivityDisplay)
|
)(ActivityDisplay)
|
||||||
|
)
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
export default function CustomModal(props) {
|
export default function CustomModal(props) {
|
||||||
|
const { t } = useTranslation()
|
||||||
return (
|
return (
|
||||||
<div className="custom-modal-backdrop">
|
<div className="custom-modal-backdrop">
|
||||||
<div className="custom-modal">
|
<div className="custom-modal">
|
||||||
@ -11,7 +13,7 @@ export default function CustomModal(props) {
|
|||||||
type="button"
|
type="button"
|
||||||
className="close"
|
className="close"
|
||||||
aria-label="Close"
|
aria-label="Close"
|
||||||
onClick={() => props.close}
|
onClick={() => props.close()}
|
||||||
>
|
>
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
@ -25,14 +27,14 @@ export default function CustomModal(props) {
|
|||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
onClick={() => props.confirm()}
|
onClick={() => props.confirm()}
|
||||||
>
|
>
|
||||||
Yes
|
{t('common:Yes')}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
onClick={() => props.close()}
|
onClick={() => props.close()}
|
||||||
>
|
>
|
||||||
No
|
{t('common:No')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -89,6 +89,7 @@ export default class StatsCharts extends React.PureComponent {
|
|||||||
''
|
''
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
name={t(`sports:${s.label}`)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</BarChart>
|
</BarChart>
|
||||||
|
@ -6,7 +6,7 @@ import StaticMap from '../Common/StaticMap'
|
|||||||
import { getDateWithTZ } from '../../utils'
|
import { getDateWithTZ } from '../../utils'
|
||||||
|
|
||||||
export default function ActivityCard(props) {
|
export default function ActivityCard(props) {
|
||||||
const { activity, sports, user } = props
|
const { activity, sports, t, user } = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card activity-card text-center">
|
<div className="card activity-card text-center">
|
||||||
@ -14,7 +14,7 @@ export default function ActivityCard(props) {
|
|||||||
<Link to={`/activities/${activity.id}`}>
|
<Link to={`/activities/${activity.id}`}>
|
||||||
{sports
|
{sports
|
||||||
.filter(sport => sport.id === activity.sport_id)
|
.filter(sport => sport.id === activity.sport_id)
|
||||||
.map(sport => sport.label)}{' '}
|
.map(sport => t(`sports:${sport.label}`))}{' '}
|
||||||
-{' '}
|
-{' '}
|
||||||
{format(
|
{format(
|
||||||
getDateWithTZ(activity.activity_date, user.timezone),
|
getDateWithTZ(activity.activity_date, user.timezone),
|
||||||
@ -31,8 +31,8 @@ export default function ActivityCard(props) {
|
|||||||
)}
|
)}
|
||||||
<div className="col">
|
<div className="col">
|
||||||
<p>
|
<p>
|
||||||
<i className="fa fa-clock-o" aria-hidden="true" /> Duration:{' '}
|
<i className="fa fa-clock-o" aria-hidden="true" />{' '}
|
||||||
{activity.moving}
|
{t('activities:Duration')}: {activity.moving}
|
||||||
{activity.map ? (
|
{activity.map ? (
|
||||||
<span>
|
<span>
|
||||||
<br />
|
<br />
|
||||||
@ -41,8 +41,8 @@ export default function ActivityCard(props) {
|
|||||||
) : (
|
) : (
|
||||||
' - '
|
' - '
|
||||||
)}
|
)}
|
||||||
<i className="fa fa-road" aria-hidden="true" /> Distance:{' '}
|
<i className="fa fa-road" aria-hidden="true" />{' '}
|
||||||
{activity.distance} km
|
{t('activities:Distance')}: {activity.distance} km
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
|
|
||||||
import { formatRecord } from '../../utils/activities'
|
import { formatRecord, translateSports } from '../../utils/activities'
|
||||||
|
|
||||||
export default function RecordsCard(props) {
|
export default function RecordsCard(props) {
|
||||||
const { records, sports, t, user } = props
|
const { records, sports, t, user } = props
|
||||||
|
const translatedSports = translateSports(sports, t)
|
||||||
const recordsBySport = records.reduce((sportList, record) => {
|
const recordsBySport = records.reduce((sportList, record) => {
|
||||||
const sport = sports.find(s => s.id === record.sport_id)
|
const sport = translatedSports.find(s => s.id === record.sport_id)
|
||||||
if (sportList[sport.label] === void 0) {
|
if (sportList[sport.label] === void 0) {
|
||||||
sportList[sport.label] = {
|
sportList[sport.label] = {
|
||||||
img: sport.img,
|
img: sport.img,
|
||||||
@ -19,11 +20,13 @@ export default function RecordsCard(props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card activity-card">
|
<div className="card activity-card">
|
||||||
<div className="card-header">Personal records</div>
|
<div className="card-header">{t('activities:Personal records')}</div>
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
{Object.keys(recordsBySport).length === 0
|
{Object.keys(recordsBySport).length === 0
|
||||||
? t('common:No records.')
|
? t('common:No records.')
|
||||||
: Object.keys(recordsBySport).map(sportLabel => (
|
: Object.keys(recordsBySport)
|
||||||
|
.sort()
|
||||||
|
.map(sportLabel => (
|
||||||
<table
|
<table
|
||||||
className="table table-borderless table-sm record-table"
|
className="table table-borderless table-sm record-table"
|
||||||
key={sportLabel}
|
key={sportLabel}
|
||||||
@ -43,7 +46,7 @@ export default function RecordsCard(props) {
|
|||||||
<tbody>
|
<tbody>
|
||||||
{recordsBySport[sportLabel].records.map(rec => (
|
{recordsBySport[sportLabel].records.map(rec => (
|
||||||
<tr key={rec.id}>
|
<tr key={rec.id}>
|
||||||
<td>{rec.record_type}</td>
|
<td>{t(`activities:${rec.record_type}`)}</td>
|
||||||
<td className="text-right">{rec.value}</td>
|
<td className="text-right">{rec.value}</td>
|
||||||
<td className="text-right">
|
<td className="text-right">
|
||||||
<Link to={`/activities/${rec.activity_id}`}>
|
<Link to={`/activities/${rec.activity_id}`}>
|
||||||
|
@ -69,6 +69,7 @@ class DashBoard extends React.Component {
|
|||||||
activity={activity}
|
activity={activity}
|
||||||
key={activity.id}
|
key={activity.id}
|
||||||
sports={sports}
|
sports={sports}
|
||||||
|
t={t}
|
||||||
user={user}
|
user={user}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
|
@ -1,22 +1,55 @@
|
|||||||
{
|
{
|
||||||
"Activity Date": "Activity Date",
|
"Activity Date": "Activity Date",
|
||||||
"Add a workout": "Add a workout",
|
"Add a workout": "Add a workout",
|
||||||
|
"Are you sure you want to delete this activity?": "Are you sure you want to delete this activity?",
|
||||||
"Ave. speed": "Ave. speed",
|
"Ave. speed": "Ave. speed",
|
||||||
|
"Ascent": "Ascent",
|
||||||
"Average speed": "Average speed",
|
"Average speed": "Average speed",
|
||||||
|
"Confirmation": "Confirmation",
|
||||||
|
"data from gpx, without any cleaning": "data from gpx, without any cleaning",
|
||||||
"Date": "Date",
|
"Date": "Date",
|
||||||
|
"Delete activity": "Delete activity",
|
||||||
|
"Descent": "Descent",
|
||||||
"Distance": "Distance",
|
"Distance": "Distance",
|
||||||
|
"distance": "distance",
|
||||||
"Duration": "Duration",
|
"Duration": "Duration",
|
||||||
|
"duration": "duration",
|
||||||
"Edit a workout": "Edit a workout",
|
"Edit a workout": "Edit a workout",
|
||||||
|
"Edit activity": "Edit activity",
|
||||||
|
"elevation": "elevation",
|
||||||
|
"End": "End",
|
||||||
|
"Farest distance": "Farest distance",
|
||||||
"Filter": "Filter",
|
"Filter": "Filter",
|
||||||
"From": "From",
|
"From": "From",
|
||||||
"gpxFile": "<strong>gpx</strong> file",
|
"gpxFile": "<strong>gpx</strong> file",
|
||||||
|
"Longest duration": "Longest duration",
|
||||||
|
"Max. altitude" : "Max. altitude",
|
||||||
"Max. speed": "Max. speed",
|
"Max. speed": "Max. speed",
|
||||||
|
"Min. altitude": "Min. altitude",
|
||||||
"no folder inside": "no folder inside",
|
"no folder inside": "no folder inside",
|
||||||
"files max": "files max",
|
"files max": "files max",
|
||||||
"max size": "max size",
|
"max size": "max size",
|
||||||
|
"No data to display": "No data to display",
|
||||||
|
"No Map": "No Map",
|
||||||
|
"No next activity": "No next activity",
|
||||||
|
"No next segment": "No next segment",
|
||||||
|
"No notes": "No notes",
|
||||||
|
"No previous activity": "No previous activity",
|
||||||
|
"No previous segment": "No previous segment",
|
||||||
"Notes": "Notes",
|
"Notes": "Notes",
|
||||||
|
"pauses": "pauses",
|
||||||
|
"Personal records": "Personal records",
|
||||||
|
"See next activity": "See next activity",
|
||||||
|
"See next segment": "See next segment",
|
||||||
|
"See previous activity": "See previous activity",
|
||||||
|
"See previous segment": "See previous segment",
|
||||||
|
"segment": "segment",
|
||||||
|
"Segments": "Segments",
|
||||||
|
"speed": "speed",
|
||||||
|
"Start": "Start",
|
||||||
"Title": "Title",
|
"Title": "Title",
|
||||||
"To": "To",
|
"To": "To",
|
||||||
|
"total duration": "total duration",
|
||||||
"with gpx file": "with gpx file",
|
"with gpx file": "with gpx file",
|
||||||
"without gpx file": "without gpx file",
|
"without gpx file": "without gpx file",
|
||||||
"zipFile": "or <strong> zip</strong> file containing <strong>gpx </strong> files"
|
"zipFile": "or <strong> zip</strong> file containing <strong>gpx </strong> files"
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
"days": "days",
|
"days": "days",
|
||||||
"Login": "Login",
|
"Login": "Login",
|
||||||
"Logout": "Logout",
|
"Logout": "Logout",
|
||||||
|
"No": "No",
|
||||||
"No records.": "No records.",
|
"No records.": "No records.",
|
||||||
"No workouts.": "No workouts.",
|
"No workouts.": "No workouts.",
|
||||||
"Register": "Register",
|
"Register": "Register",
|
||||||
@ -19,5 +20,6 @@
|
|||||||
"Workout": "Workout",
|
"Workout": "Workout",
|
||||||
"Workouts": "Workouts",
|
"Workouts": "Workouts",
|
||||||
"workout": "workout",
|
"workout": "workout",
|
||||||
"workouts": "workouts"
|
"workouts": "workouts",
|
||||||
|
"Yes": "Yes"
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,55 @@
|
|||||||
{
|
{
|
||||||
"Activity Date": "Date de l'activité",
|
"Activity Date": "Date de l'activité",
|
||||||
"Add a workout": "Ajouter une activité",
|
"Add a workout": "Ajouter une activité",
|
||||||
|
"Are you sure you want to delete this activity?": "Etes-vous sûr de vouloir supprimer cette activité ?",
|
||||||
"Ave. speed": "Vitesse moyenne",
|
"Ave. speed": "Vitesse moyenne",
|
||||||
|
"Ascent": "Dénivelé positif",
|
||||||
"Average speed": "Vitesse moyenne",
|
"Average speed": "Vitesse moyenne",
|
||||||
|
"Confirmation": "Confirmation",
|
||||||
|
"data from gpx, without any cleaning": "données issues du fichier gpx, sans correction",
|
||||||
"Date": "Date",
|
"Date": "Date",
|
||||||
|
"Delete activity": "Supprimer l'activité",
|
||||||
|
"Descent": "Dénivelé négatif",
|
||||||
"Distance": "Distance",
|
"Distance": "Distance",
|
||||||
|
"distance": "distance",
|
||||||
"Duration": "Durée",
|
"Duration": "Durée",
|
||||||
|
"duration": "durée",
|
||||||
"Edit a workout": "Editer une activité",
|
"Edit a workout": "Editer une activité",
|
||||||
|
"Edit activity": "Editer une activity",
|
||||||
|
"elevation": "altitude",
|
||||||
|
"End": "Arrivée",
|
||||||
|
"Farest distance": "Distance la + longue",
|
||||||
"Filter": "Filtrer",
|
"Filter": "Filtrer",
|
||||||
"From": "A partir de",
|
"From": "A partir de",
|
||||||
"gpxFile": "fichier <strong>gpx</strong>",
|
"gpxFile": "fichier <strong>gpx</strong>",
|
||||||
|
"Longest duration": "Durée la + longue",
|
||||||
|
"Max. altitude" : "Altitude max",
|
||||||
"Max. speed": "Vitesse max",
|
"Max. speed": "Vitesse max",
|
||||||
|
"Min. altitude": "Altitude min",
|
||||||
"no folder inside": "pas de répertoire",
|
"no folder inside": "pas de répertoire",
|
||||||
"files max": " fichiers max",
|
"files max": " fichiers max",
|
||||||
"max size": "taille max",
|
"max size": "taille max",
|
||||||
|
"No data to display": "Pas de données à afficher",
|
||||||
|
"No Map": "Pas de carte",
|
||||||
|
"No next activity": "Pas d'activité suivante",
|
||||||
|
"No next segment": "Pas de segment suivant",
|
||||||
|
"No notes": "Pas de notes",
|
||||||
|
"No previous activity": "Pas d'activité précédente",
|
||||||
|
"No previous segment": "Pas de segment précédent",
|
||||||
"Notes": "Notes",
|
"Notes": "Notes",
|
||||||
|
"pauses": "pauses",
|
||||||
|
"Personal records": "Records personnels",
|
||||||
|
"See next activity": "Voir l'activité suivante",
|
||||||
|
"See next segment": "Voir le segment suivant",
|
||||||
|
"See previous activity": "Voir l'activité précédente",
|
||||||
|
"See previous segment": "Voir le segment précédent",
|
||||||
|
"segment": "segment",
|
||||||
|
"Segments": "Segments",
|
||||||
|
"Start": "Départ",
|
||||||
|
"speed": "vitesse",
|
||||||
"Title": "Titre",
|
"Title": "Titre",
|
||||||
"To": "Jusqu'au",
|
"To": "Jusqu'au",
|
||||||
|
"total duration": "durée totale",
|
||||||
"with gpx file": "avec un fichier gpx",
|
"with gpx file": "avec un fichier gpx",
|
||||||
"without gpx file": "sans fichier gpx",
|
"without gpx file": "sans fichier gpx",
|
||||||
"zipFile": "ou un fichier <strong> zip</strong> contenant des fichiers <strong>gpx</strong>"
|
"zipFile": "ou un fichier <strong> zip</strong> contenant des fichiers <strong>gpx</strong>"
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
"days": "jours",
|
"days": "jours",
|
||||||
"Login": "Se connecter",
|
"Login": "Se connecter",
|
||||||
"Logout": "Se déconnecter",
|
"Logout": "Se déconnecter",
|
||||||
|
"No": "Non",
|
||||||
"No records.": "Pas de records.",
|
"No records.": "Pas de records.",
|
||||||
"No workouts.": "Pas d'activités.",
|
"No workouts.": "Pas d'activités.",
|
||||||
"Register": "S'inscrire",
|
"Register": "S'inscrire",
|
||||||
@ -19,5 +20,6 @@
|
|||||||
"Workout": "Activité",
|
"Workout": "Activité",
|
||||||
"Workouts": "Activités",
|
"Workouts": "Activités",
|
||||||
"workout": "activité",
|
"workout": "activité",
|
||||||
"workouts": "activités"
|
"workouts": "activités",
|
||||||
|
"Yes": "Oui"
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,10 @@ export const activityColors = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
export const recordsLabels = [
|
export const recordsLabels = [
|
||||||
{ record_type: 'AS', label: 'Avg speed' },
|
{ record_type: 'AS', label: 'Ave. speed' },
|
||||||
{ record_type: 'FD', label: 'Farest distance' },
|
{ record_type: 'FD', label: 'Farest distance' },
|
||||||
{ record_type: 'LD', label: 'Longest duration' },
|
{ record_type: 'LD', label: 'Longest duration' },
|
||||||
{ record_type: 'MS', label: 'Max speed' },
|
{ record_type: 'MS', label: 'Max. speed' },
|
||||||
]
|
]
|
||||||
|
|
||||||
export const getGeoJson = gpxContent => {
|
export const getGeoJson = gpxContent => {
|
||||||
|
Loading…
Reference in New Issue
Block a user