Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Homework 7 #53

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7,065 changes: 3,535 additions & 3,530 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"connected-react-router": "^5.0.1",
"history": "^4.7.2",
"immutable": "^4.0.0-rc.11",
"moment": "^2.22.2",
"prop-types": "^15.6.2",
"react": "^16.5.2",
"react-addons-css-transition-group": "^15.6.2",
Expand Down
57 changes: 36 additions & 21 deletions src/components/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,54 @@ import Counter from './counter'
import CommentsPage from './routes/comments-page'
import Menu, { MenuItem } from './menu'
import { Provider as UserProvider } from '../contexts/user'
import { Provider as LanguageProvider } from '../contexts/language'
import LanguageSelect from './language-select'
const errorTranslations = require('../translations/error.json')

class App extends Component {
state = {
user: 'roma'
user: 'roma',
lng: 'en'
}

setUser = (user) => this.setState({ user })
setLanguage = (lng) => this.setState({ lng })

render() {
const { lng } = this.state
return (
<UserProvider value={this.state.user}>
<div>
<Menu>
<MenuItem link="/articles" children="Articles" />
<MenuItem link="/filters">Filters</MenuItem>
<MenuItem link="/counter">Counter</MenuItem>
<MenuItem link="/comments">Comments</MenuItem>
</Menu>
<UserForm value={this.state.user} onChange={this.setUser} />
<LanguageSelect lng={this.state.lng} onChange={this.setLanguage} />
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ты же просто создаешь компонент, там и не будет никакие params. params могут быть, если бы ты сделала что-то вроде <Route path="/:lng" render = {(routerProps) => <LanguageSelect lng={this.state.lng} onChange={this.setLanguage} {...routerProps} />} />

<LanguageProvider value={this.state.lng}>
<Menu>
<MenuItem link={`/${lng}/articles`} children="articles" />
<MenuItem link={`/${lng}/filters`}>filters</MenuItem>
<MenuItem link={`/${lng}/counter`}>counter</MenuItem>
<MenuItem link={`/${lng}/comments`}>comments</MenuItem>
</Menu>
<UserForm value={this.state.user} onChange={this.setUser} />

<Switch>
<Redirect from="/" exact to="/articles" />
<Route path="/counter" component={Counter} exact />
<Route path="/comments" component={CommentsPage} />
<Route path="/filters" component={Filters} />
<Route
path="/articles/new"
render={() => <h1>New Article Page</h1>}
/>
<Route path="/articles" component={ArticlesPage} />
<Route path="/error" render={() => <h1>Error Page</h1>} />
<Route path="*" render={() => <h1>Not Found Page</h1>} />
</Switch>
<Switch>
<Redirect from="/" exact to={`/${lng}/articles`} />
<Redirect from="/:lng/" exact to={`/${lng}/articles`} />
<Route path={`/:lng/counter`} component={Counter} exact />
<Route path={`/:lng/comments`} component={CommentsPage} />
<Route path={`/:lng/filters`} component={Filters} />
<Route
path={`/:lng/articles/new`}
render={() => <h1>New Article Page</h1>}
/>
<Route path={`/:lng/articles`} component={ArticlesPage} />
<Route path={`/:lng/error`} render={() => <h1>Error Page</h1>} />
<Route
path="*"
render={() => (
<h1>{errorTranslations[this.state.lng].notFoundPage}</h1>
)}
/>
</Switch>
</LanguageProvider>
</div>
</UserProvider>
)
Expand Down
14 changes: 11 additions & 3 deletions src/components/article-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { loadAllArticles } from '../ac'
import Loader from './common/loader'
import { NavLink, withRouter } from 'react-router-dom'
import { Consumer as LanguageConsumer } from '../contexts/language'

export class ArticleList extends Component {
static propTypes = {
Expand All @@ -26,9 +27,16 @@ export class ArticleList extends Component {
const { articles } = this.props
return articles.map((article) => (
<li key={article.id} className="test--article-list__item">
<NavLink to={`/articles/${article.id}`} activeStyle={{ color: 'red' }}>
{article.title}
</NavLink>
<LanguageConsumer>
{(lng) => (
<NavLink
to={`/${lng}/articles/${article.id}`}
activeStyle={{ color: 'red' }}
>
{article.title}
</NavLink>
)}
</LanguageConsumer>
</li>
))
}
Expand Down
8 changes: 7 additions & 1 deletion src/components/article/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { deleteArticle, loadArticleById } from '../../ac'
import './style.css'
import Loader from '../common/loader'
import { articleSelector } from '../../selectors'
import { Consumer as LanguageConsumer } from '../../contexts/language'
const articleTranslations = require('../../translations/article.json')

class Article extends PureComponent {
static propTypes = {
Expand Down Expand Up @@ -41,7 +43,11 @@ class Article extends PureComponent {
<div>
<h3>
{article.title}
<button onClick={this.handleDeleteClick}>delete me</button>
<button onClick={this.handleDeleteClick}>
<LanguageConsumer>
{(lng) => articleTranslations[lng].delete}
</LanguageConsumer>
</button>
</h3>
<CSSTransition
transitionAppear
Expand Down
20 changes: 17 additions & 3 deletions src/components/comment-form/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { addComment } from '../../ac'
import { Consumer as LanguageConsumer } from '../../contexts/language'
import './style.css'
const formTranslations = require('../../translations/form.json')

class CommentForm extends Component {
static propTypes = {}
Expand All @@ -14,19 +16,31 @@ class CommentForm extends Component {
render() {
return (
<form onSubmit={this.handleSubmit}>
user:{' '}
<LanguageConsumer>
{(lng) => `${formTranslations[lng].username}:${' '}`}
</LanguageConsumer>
<input
value={this.state.user}
onChange={this.handleChange('user')}
className={this.getClassName('user')}
/>
comment:{' '}
<LanguageConsumer>
{(lng) => `${formTranslations[lng].comment}:${' '}`}
</LanguageConsumer>
<input
value={this.state.text}
onChange={this.handleChange('text')}
className={this.getClassName('text')}
/>
<input type="submit" value="submit" disabled={!this.isValidForm()} />
<LanguageConsumer>
{(lng) => (
<input
type="submit"
value={formTranslations[lng].submit}
disabled={!this.isValidForm()}
/>
)}
</LanguageConsumer>
</form>
)
}
Expand Down
14 changes: 11 additions & 3 deletions src/components/comment-list/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { loadArticleComments } from '../../ac'
import './style.css'
import Loader from '../common/loader'
import { Consumer as UserConsumer } from '../../contexts/user'
import { Consumer as LanguageConsumer } from '../../contexts/language'
const articleTranslations = require('../../translations/article.json')

class CommentList extends Component {
static propTypes = {
Expand Down Expand Up @@ -37,11 +39,13 @@ class CommentList extends Component {

render() {
const { isOpen, toggleOpen } = this.props
const text = isOpen ? 'hide comments' : 'show comments'
const text = isOpen ? 'hideComments' : 'showComments'
return (
<div>
<button onClick={toggleOpen} className="test__comment-list--btn">
{text}
<LanguageConsumer>
{(lng) => articleTranslations[lng][text]}
</LanguageConsumer>
</button>
<CSSTransition
transitionName="comments"
Expand Down Expand Up @@ -71,7 +75,11 @@ class CommentList extends Component {
{comments.length ? (
this.comments
) : (
<h3 className="test__comment-list--empty">No comments yet</h3>
<h3 className="test__comment-list--empty">
<LanguageConsumer>
{(lng) => articleTranslations[lng].noComments}
</LanguageConsumer>
</h3>
)}
<CommentForm articleId={id} />
</div>
Expand Down
14 changes: 11 additions & 3 deletions src/components/comments-pagination.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
commentsPageIdsSelector,
totalCommentsSelector
} from '../selectors/index'
import { Consumer as LanguageConsumer } from '../contexts/language'

class CommentsPagination extends Component {
componentDidMount() {
Expand Down Expand Up @@ -48,9 +49,16 @@ class CommentsPagination extends Component {
.fill()
.map((_, i) => (
<li key={i}>
<NavLink to={`/comments/${i + 1}`} activeStyle={{ color: 'red' }}>
{i + 1}
</NavLink>
<LanguageConsumer>
{(lng) => (
<NavLink
to={`/${lng}/comments/${i + 1}`}
activeStyle={{ color: 'red' }}
>
{i + 1}
</NavLink>
)}
</LanguageConsumer>
</li>
))
return <ul>{items}</ul>
Expand Down
13 changes: 12 additions & 1 deletion src/components/common/loader.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import React from 'react'
import { Consumer as LanguageConsumer } from '../../contexts/language'
const loaderTranslations = require('../../translations/loader.json')

function Loader() {
return <h3>Loading...</h3>
return (
<LanguageConsumer>
{(lng) => (
<h3>
{loaderTranslations[lng].loading}
...
</h3>
)}
</LanguageConsumer>
)
}

Loader.propTypes = {}
Expand Down
8 changes: 7 additions & 1 deletion src/components/counter.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React, { Component } from 'react'
import { Consumer as LanguageConsumer } from '../contexts/language'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { increment } from '../ac'
const counterTranslations = require('../translations/counter.json')

class Counter extends Component {
static propTypes = {
Expand All @@ -13,7 +15,11 @@ class Counter extends Component {
return (
<div>
<h2>{this.props.count}</h2>
<button onClick={this.handleClick}>increment</button>
<button onClick={this.handleClick}>
<LanguageConsumer>
{(lng) => counterTranslations[lng].increment}
</LanguageConsumer>
</button>
</div>
)
}
Expand Down
17 changes: 13 additions & 4 deletions src/components/filters/date-range.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import React, { Component } from 'react'
import DayPicker, { DateUtils } from 'react-day-picker'
import MomentLocaleUtils from 'react-day-picker/moment'
import 'moment/locale/ru'
import { connect } from 'react-redux'
import { changeDateRange } from '../../ac'
import { Consumer as LanguageConsumer } from '../../contexts/language'

import 'react-day-picker/lib/style.css'
import { dateRangeSelector } from '../../selectors'
Expand All @@ -18,10 +21,16 @@ class DateRange extends Component {
from && to && `${from.toDateString()} - ${to.toDateString()}`
return (
<div className="date-range">
<DayPicker
selectedDays={(day) => DateUtils.isDayInRange(day, { from, to })}
onDayClick={this.handleDayClick}
/>
<LanguageConsumer>
{(lng) => (
<DayPicker
localeUtils={MomentLocaleUtils}
locale={lng}
selectedDays={(day) => DateUtils.isDayInRange(day, { from, to })}
onDayClick={this.handleDayClick}
/>
)}
</LanguageConsumer>
{selectedRange}
</div>
)
Expand Down
66 changes: 66 additions & 0 deletions src/components/language-select.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React, { Component } from 'react'
import Select from 'react-select'
import { withRouter, matchPath } from 'react-router-dom'
import { replace, push } from 'connected-react-router'
const languages = require('../translations/language.json')

class LanguageSelect extends Component {
componentDidMount = (props) => {
const { onChange, history, location } = this.props

const lng = this.toGetLngFromUrl()

if (lng) {
if (languages[lng]) {
onChange(lng)
} else {
//Why does not it (replace from 'connected-react-router') work??
//replace(location.pathname.replace(new RegExp(lng), 'en'))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace - это просто ac, пего нужно задиспатчить, для этого connect нужен


history.replace(location.pathname.replace(new RegExp(lng), 'en'))
}
}
}

handleLanguageChange = (selected) => {
const { onChange, history, location } = this.props
onChange(selected.value)

const lng = this.toGetLngFromUrl()

if (lng && lng !== selected.value) {
history.replace(
location.pathname.replace(new RegExp(lng), selected.value)
)
}
}

toGetLngFromUrl = () => {
const { location } = this.props

const parsedParam = matchPath(location.pathname, {
path: '/:lng/'
})

return parsedParam.params.lng
}

render() {
const { lng } = this.props
return (
<div>
{languages[lng][lng]}
<Select
options={Object.keys(languages[lng]).map((key) => ({
label: languages[lng][key],
value: key
}))}
value={{ value: lng, label: languages[lng][lng] }}
onChange={this.handleLanguageChange}
/>
</div>
)
}
}

export default withRouter(LanguageSelect)
Loading