Client - display characters limitation on textarea - fix #81

This commit is contained in:
Sam 2021-07-14 15:05:00 +02:00
parent 7cea812d8b
commit fdfd828677
21 changed files with 93 additions and 37 deletions

View File

@ -1,15 +1,15 @@
{
"files": {
"main.css": "/static/css/main.8c7e57e2.chunk.css",
"main.js": "/static/js/main.9a854965.chunk.js",
"main.js.map": "/static/js/main.9a854965.chunk.js.map",
"main.css": "/static/css/main.98601af9.chunk.css",
"main.js": "/static/js/main.99ae4b8a.chunk.js",
"main.js.map": "/static/js/main.99ae4b8a.chunk.js.map",
"runtime-main.js": "/static/js/runtime-main.14e737bb.js",
"runtime-main.js.map": "/static/js/runtime-main.14e737bb.js.map",
"static/js/2.8c02a30e.chunk.js": "/static/js/2.8c02a30e.chunk.js",
"static/js/2.8c02a30e.chunk.js.map": "/static/js/2.8c02a30e.chunk.js.map",
"static/js/2.ce83ecf7.chunk.js": "/static/js/2.ce83ecf7.chunk.js",
"static/js/2.ce83ecf7.chunk.js.map": "/static/js/2.ce83ecf7.chunk.js.map",
"index.html": "/index.html",
"static/css/main.8c7e57e2.chunk.css.map": "/static/css/main.8c7e57e2.chunk.css.map",
"static/js/2.8c02a30e.chunk.js.LICENSE.txt": "/static/js/2.8c02a30e.chunk.js.LICENSE.txt",
"static/css/main.98601af9.chunk.css.map": "/static/css/main.98601af9.chunk.css.map",
"static/js/2.ce83ecf7.chunk.js.LICENSE.txt": "/static/js/2.ce83ecf7.chunk.js.LICENSE.txt",
"static/media/en.9e6dbfb0.svg": "/static/media/en.9e6dbfb0.svg",
"static/media/fr.d0f9280c.svg": "/static/media/fr.d0f9280c.svg",
"static/media/mail-send.619079f0.svg": "/static/media/mail-send.619079f0.svg",
@ -17,8 +17,8 @@
},
"entrypoints": [
"static/js/runtime-main.14e737bb.js",
"static/js/2.8c02a30e.chunk.js",
"static/css/main.8c7e57e2.chunk.css",
"static/js/main.9a854965.chunk.js"
"static/js/2.ce83ecf7.chunk.js",
"static/css/main.98601af9.chunk.css",
"static/js/main.99ae4b8a.chunk.js"
]
}

View File

@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="#000000"><link rel="manifest" href="/manifest.json"><link rel="shortcut icon" href="/favicon.ico"><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fork-awesome@1.1.7/css/fork-awesome.min.css" integrity="sha256-gsmEoJAws/Kd3CjuOQzLie5Q3yshhvmo7YNtBG7aaEY=" crossorigin="anonymous"><link rel="stylesheet" href="https://cdn.jsdelivr.net/foundation-icons/3.0/foundation-icons.min.css"><link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""><title>FitTrackee</title><link href="/static/css/main.8c7e57e2.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script><script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script><script type="text/javascript">$(document).ready((function(){$("li.nav-item").click((function(){$("button.navbar-toggler").toggleClass("collapsed"),$("#navbarSupportedContent").toggleClass("show")}))}))</script><script>!function(e){function t(t){for(var n,i,l=t[0],f=t[1],a=t[2],p=0,s=[];p<l.length;p++)i=l[p],Object.prototype.hasOwnProperty.call(o,i)&&o[i]&&s.push(o[i][0]),o[i]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(c&&c(t);s.length;)s.shift()();return u.push.apply(u,a||[]),r()}function r(){for(var e,t=0;t<u.length;t++){for(var r=u[t],n=!0,l=1;l<r.length;l++){var f=r[l];0!==o[f]&&(n=!1)}n&&(u.splice(t--,1),e=i(i.s=r[0]))}return e}var n={},o={1:0},u=[];function i(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,i),r.l=!0,r.exports}i.m=e,i.c=n,i.d=function(e,t,r){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(i.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)i.d(r,n,function(t){return e[t]}.bind(null,n));return r},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="/";var l=this.webpackJsonpfittrackee_client=this.webpackJsonpfittrackee_client||[],f=l.push.bind(l);l.push=t,l=l.slice();for(var a=0;a<l.length;a++)t(l[a]);var c=f;r()}([])</script><script src="/static/js/2.8c02a30e.chunk.js"></script><script src="/static/js/main.9a854965.chunk.js"></script></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="#000000"><link rel="manifest" href="/manifest.json"><link rel="shortcut icon" href="/favicon.ico"><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fork-awesome@1.1.7/css/fork-awesome.min.css" integrity="sha256-gsmEoJAws/Kd3CjuOQzLie5Q3yshhvmo7YNtBG7aaEY=" crossorigin="anonymous"><link rel="stylesheet" href="https://cdn.jsdelivr.net/foundation-icons/3.0/foundation-icons.min.css"><link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""><title>FitTrackee</title><link href="/static/css/main.98601af9.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script><script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script><script type="text/javascript">$(document).ready((function(){$("li.nav-item").click((function(){$("button.navbar-toggler").toggleClass("collapsed"),$("#navbarSupportedContent").toggleClass("show")}))}))</script><script>!function(e){function t(t){for(var n,i,l=t[0],f=t[1],a=t[2],p=0,s=[];p<l.length;p++)i=l[p],Object.prototype.hasOwnProperty.call(o,i)&&o[i]&&s.push(o[i][0]),o[i]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(c&&c(t);s.length;)s.shift()();return u.push.apply(u,a||[]),r()}function r(){for(var e,t=0;t<u.length;t++){for(var r=u[t],n=!0,l=1;l<r.length;l++){var f=r[l];0!==o[f]&&(n=!1)}n&&(u.splice(t--,1),e=i(i.s=r[0]))}return e}var n={},o={1:0},u=[];function i(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,i),r.l=!0,r.exports}i.m=e,i.c=n,i.d=function(e,t,r){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(i.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)i.d(r,n,function(t){return e[t]}.bind(null,n));return r},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="/";var l=this.webpackJsonpfittrackee_client=this.webpackJsonpfittrackee_client||[],f=l.push.bind(l);l.push=t,l=l.slice();for(var a=0;a<l.length;a++)t(l[a]);var c=f;r()}([])</script><script src="/static/js/2.ce83ecf7.chunk.js"></script><script src="/static/js/main.99ae4b8a.chunk.js"></script></body></html>

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

@ -362,6 +362,11 @@ label {
padding: 0.1em;
}
.remaining-chars {
font-size: 0.8em;
font-style: italic;
}
.sport-img {
max-width: 35px;
max-height: 35px;
@ -440,6 +445,10 @@ label {
color: black;
}
.user-bio, .workout-notes {
white-space: pre-wrap;
}
.user-filters {
font-size: 0.9em;
margin-bottom: 10px;
@ -516,7 +525,7 @@ label {
line-height: 400px;
}
.workout-notes, .actvitiy-segments {
.workout-notes, .actvity-segments {
font-size: 0.9em;
font-style: italic;
margin-top: 10px;

View File

@ -0,0 +1,45 @@
import React from 'react'
import { withTranslation } from 'react-i18next'
import { connect } from 'react-redux'
class CustomTextArea extends React.Component {
constructor(props, context) {
super(props, context)
this.state = {
text: props.defaultValue ? props.defaultValue : '',
}
}
handleOnChange(changeEvent) {
this.setState({ text: changeEvent.target.value })
if (this.props.onTextChange) {
this.props.onTextChange(changeEvent)
}
}
render() {
const { charLimit, loading, name, t } = this.props
const { text } = this.state
return (
<>
<textarea
name={name}
defaultValue={text}
disabled={loading ? loading : false}
className="form-control input-lg"
maxLength={charLimit}
onChange={event => this.handleOnChange(event)}
/>
<div className="remaining-chars">
{t('common:remaining characters')}: {text.length}/{charLimit}
</div>
</>
)
}
}
export default withTranslation()(
connect(state => ({
loading: state.loading,
}))(CustomTextArea)
)

View File

@ -79,7 +79,7 @@ function ProfileDetail({
</p>
<p>
<span className="user-label">{t('user:Bio')}</span>:{' '}
{user.bio}
<span className="user-bio">{user.bio}</span>
</p>
<p>
{/* eslint-disable-next-line max-len */}

View File

@ -10,6 +10,7 @@ import { deleteUser, handleProfileFormSubmit } from '../../actions/user'
import { history } from '../../index'
import { languages } from '../NavBar/LanguageDropdown'
import CustomModal from '../Common/CustomModal'
import CustomTextArea from '../Common/CustomTextArea'
class ProfileEdit extends React.Component {
constructor(props, context) {
@ -198,12 +199,11 @@ class ProfileEdit extends React.Component {
<div className="form-group">
<label>
{t('user:Bio')}:
<textarea
<CustomTextArea
charLimit={200}
name="bio"
className="form-control input-lg"
maxLength="200"
value={formData.bio}
onChange={e => this.handleFormChange(e)}
defaultValue={formData.bio}
onTextChange={e => this.handleFormChange(e)}
/>
</label>
</div>

View File

@ -7,6 +7,7 @@ import { addWorkout, editWorkout } from '../../../actions/workouts'
import { history } from '../../../index'
import { getFileSize } from '../../../utils'
import { translateSports } from '../../../utils/workouts'
import CustomTextArea from '../../Common/CustomTextArea'
function FormWithGpx(props) {
const {
@ -105,12 +106,11 @@ function FormWithGpx(props) {
<div className="form-group">
<label>
{t('workouts:Notes')}:
<textarea
name="notes"
<CustomTextArea
charLimit={500}
defaultValue={workout ? workout.notes : ''}
disabled={loading}
className="form-control input-lg"
maxLength="500"
loading={loading}
name="notes"
/>
</label>
</div>

View File

@ -5,6 +5,7 @@ import { addWorkoutWithoutGpx, editWorkout } from '../../../actions/workouts'
import { history } from '../../../index'
import { getDateWithTZ } from '../../../utils'
import { formatWorkoutDate, translateSports } from '../../../utils/workouts'
import CustomTextArea from '../../Common/CustomTextArea'
function FormWithoutGpx(props) {
const { onAddOrEdit, sports, t, user, workout } = props
@ -106,11 +107,10 @@ function FormWithoutGpx(props) {
<div className="form-group">
<label>
{t('workouts:Notes')}:
<textarea
name="notes"
<CustomTextArea
charLimit={500}
defaultValue={workout ? workout.notes : ''}
className="form-control input-lg"
maxLength="500"
name="notes"
/>
</label>
</div>

View File

@ -20,6 +20,7 @@
"Page not found": "Page not found",
"Previous": "Prev",
"registration date": "registration date",
"remaining characters": "remaining characters",
"Sort": "Sort",
"Sort by": "Sort by",
"Sport": "Sport",

View File

@ -19,6 +19,7 @@
"No workouts.": "Pas de séances.",
"Page not found": "Page introuvable",
"Previous": "Page précédente",
"remaining characters": "nombre de caractères restants ",
"registration date": "date d'inscription",
"Sort": "Tri",
"Sort by": "Trier par",