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

Ht1 #6

Open
wants to merge 2 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
4 changes: 2 additions & 2 deletions admin/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
## HT1.1 Сделать /admin закрытым роутом, только для авторизированых пользоватилей
## HT1.2 При загрузке брать пользоватиля из сесии
## HT1.1 Сделать /admin закрытым роутом, только для авторизированых пользователей
## HT1.2 При загрузке брать пользователя из сессии
## HT1.3 Реализовать роут для добавления людей(форма, список, чистить форму при успешном добавлении)
36 changes: 20 additions & 16 deletions admin/src/App.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React, { Component } from 'react'
import { Route, NavLink } from 'react-router-dom'
import React, {Component} from 'react'
import {NavLink, Route} from 'react-router-dom'
import AuthPage from './components/routes/auth'
import AdminPage from './components/routes/admin'
import ProtectedRoute from "./components/common/protected-route";
import AuthProvider from "./components/common/auth-provider";

class App extends Component {
static propTypes = {
Expand All @@ -11,20 +13,22 @@ class App extends Component {
render() {
return (
<div>
<nav>
<ul>
<li>
<NavLink to="/auth" activeStyle={{ color: 'red'}}>auth</NavLink>
</li>
<li>
<NavLink to="/admin" activeStyle={{ color: 'red'}}>admin</NavLink>
</li>
</ul>
</nav>
<section>
<Route path="/auth" component={AuthPage}/>
<Route path="/admin" component={AdminPage}/>
</section>
<AuthProvider>
<nav>
<ul>
<li>
<NavLink to="/auth" activeStyle={{ color: 'red'}}>auth</NavLink>
</li>
<li>
<NavLink to="/admin" activeStyle={{ color: 'red'}}>admin</NavLink>
</li>
</ul>
</nav>
<section>
<Route path="/auth" component={AuthPage}/>
<ProtectedRoute path="/admin" component={AdminPage}/>
</section>
</AuthProvider>
</div>
)
}
Expand Down
3 changes: 3 additions & 0 deletions admin/src/components/auth/auth-context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import React from 'react';

export const AuthContext = React.createContext({user: undefined});
18 changes: 18 additions & 0 deletions admin/src/components/common/auth-provider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react'
import {connect} from "react-redux";
import {checkAuth} from "../../ducks/auth";
import {AuthContext} from "../auth/auth-context";

class AuthProvider extends React.Component {
render() {
return <AuthContext.Provider value={{user: this.props.auth && this.props.auth.user}}>
Copy link
Owner

Choose a reason for hiding this comment

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

Ок, но не вижу смысла держать в отдельном контексте, если уже есть редакс

{this.props.children}
</AuthContext.Provider>;
}

componentDidMount() {
this.props.checkAuth();
}
}

export default connect(({auth}) => ({auth}), {checkAuth})(AuthProvider);
20 changes: 20 additions & 0 deletions admin/src/components/common/protected-route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import {AuthContext} from '../auth/auth-context';
import {Redirect, Route} from "react-router-dom";

const ProtectedRoute = ({component: Component, ...rest}) => (
<AuthContext.Consumer>
{({ user }) => {
return <Route
render={
props =>
user
? <Component {...props} />
: <Redirect to="/auth/sign-in" />
}
Copy link
Owner

Choose a reason for hiding this comment

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

Это очень плохо читается, вынеси в отдельный метод

{...rest}
/>
}}
</AuthContext.Consumer>
);
export default ProtectedRoute;
36 changes: 36 additions & 0 deletions admin/src/components/people-list/add-people-form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, {Component} from 'react'
import {Field, reduxForm} from 'redux-form'
import validator from "email-validator";
import ErrorField from "../common/error-field";

class AddPeopleForm extends Component {
render() {
return (
<div>
<h3>Add user</h3>
<form onSubmit={this.props.handleSubmit}>
<Field component={ErrorField} name="firstName" label="First Name"/>
<Field component={ErrorField} name="secondName" label="Second Name"/>
<Field component={ErrorField} name="email" label="Email"/>
<button type="submit">Add Person</button>
</form>
</div>
)
}
}

const validate = ({email, firstName, secondName}) => {
const errors = {}
if (!email) errors.email = 'email is a required field'
else if (!validator.validate(email)) errors.email = 'invalid email'

if (!firstName) errors.firstName = 'firstName is a required field'
if (!secondName) errors.secondName = 'secondName is a required field'
return errors
}

export default reduxForm({
form: 'add-people',
validate
})(AddPeopleForm)

24 changes: 24 additions & 0 deletions admin/src/components/people-list/people-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React, {Component} from 'react'
import {personSelector} from '../../ducks/person';
import {connect} from "react-redux";

class PeopleList extends Component {
render() {
return (
<div>
<nav>
<ul>
{
this.props.people.map(person => {
return (<li>{person.firstName} {person.secondName} {person.email}</li>)
})
}
</ul>
</nav>
</div>
)
}
}

export default PeopleList

24 changes: 22 additions & 2 deletions admin/src/components/routes/admin/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import React, { Component } from 'react'
import React, {Component} from 'react'
import {NavLink, Route} from "react-router-dom";
import AddPeopleForm from "../../people-list/add-people-form";
import PeopleList from "../../people-list/people-list";
import {addPerson, personSelector} from "../../../ducks/person";
import connect from "react-redux/es/connect/connect";

class AdminPage extends Component {
static propTypes = {
Expand All @@ -9,9 +14,24 @@ class AdminPage extends Component {
return (
<div>
<h1>Admin</h1>
<div>
<NavLink to="/admin/people-list">People list</NavLink>
</div>

<Route path="/admin/people-list" render={() => {
return (<div>
<AddPeopleForm onSubmit={this.handleAddPerson}/>
<PeopleList people={this.props.people}/>
</div>)
}}/>
</div>
)
}

handleAddPerson = ({email, firstName, secondName}) => this.props.addPerson(email, firstName, secondName)
}

export default AdminPage
export default connect(state => {
return {
people: personSelector(state)
}}, {addPerson})(AdminPage)
12 changes: 6 additions & 6 deletions admin/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import 'firebase/auth'
export const appName = 'adv-react-29-01'

const config = {
apiKey: "AIzaSyD3RIBQ59em4ZGOdRLQpS1velxhcgImTeI",
authDomain: `${appName}.firebaseapp.com`,
databaseURL: `https://${appName}.firebaseio.com`,
projectId: appName,
storageBucket: `${appName}.appspot.com`,
messagingSenderId: "832921987414"
apiKey: "AIzaSyDpSawbqegA5phH76jzcYeIXbDx3OW15Co",
authDomain: "react-adv-d6603.firebaseapp.com",
databaseURL: "https://react-adv-d6603.firebaseio.com",
projectId: "react-adv-d6603",
storageBucket: "react-adv-d6603.appspot.com",
messagingSenderId: "997818573207"
}

firebase.initializeApp(config)
27 changes: 18 additions & 9 deletions admin/src/ducks/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export function signIn(email, password) {

dispatch({
type: SIGN_IN_SUCCESS,
payload: { user }
payload: {user}
})
}
}
Expand All @@ -66,15 +66,24 @@ export function signUp(email, password) {

dispatch({
type: SIGN_UP_SUCCESS,
payload: { user }
payload: {user}
})
}
}

/**
* Init
**/

firebase.auth().onAuthStateChanged((user) => {
console.log('--- user', user)
})
export function checkAuth() {
return async (dispatch) => {
dispatch({
type: SIGN_IN_START
});

firebase.auth().onAuthStateChanged((user) => {

Choose a reason for hiding this comment

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

Есть подозрение, что без перелогина второй раз checkAuth повесит приложение в SIGN_IN_START.
https://firebase.google.com/docs/reference/js/firebase.auth.Auth#onAuthStateChanged

The observer will be triggered in the following scenarios:

When auth().onAuthStateChanged() is first called. It will trigger with the initial Auth state. If the user is returning from an auth().signInWithRedirect() operation, the observer will wait for that operation to resolve before initially triggering.
When a new user signs.
When an already signed in user signs out.

if (user) {
dispatch({
type: SIGN_IN_SUCCESS,
payload: {user}
});
}
})
}
}
55 changes: 55 additions & 0 deletions admin/src/ducks/person.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {List, Record} from 'immutable'
import {appName} from '../config'
import {createSelector} from 'reselect'

/**
* Constants
* */
export const moduleName = 'person'
const prefix = `${appName}/${moduleName}`

export const ADD_PERSON = `${prefix}/ADD_PERSON`

/**
* Reducer
* */
export const ReducerRecord = Record({
peopleList: List()
})

export default function reducer(state = new ReducerRecord(), action) {
const {type, payload} = action

switch (type) {
case ADD_PERSON:
return state.set('peopleList', state.peopleList.push(payload.person))
default:
return state
}
}

/**
* Selectors
* */

export const rootSelector = ({person}) => person
export const personSelector = createSelector(
rootSelector,
(person) => {
return person.peopleList.toArray()

}
)

/**
* Action Creators
* */

export function addPerson(firstName, secondName, email) {
return (dispatch) => {
dispatch({
type: ADD_PERSON,
payload: {person: {firstName, secondName, email}}
})
}
}
4 changes: 3 additions & 1 deletion admin/src/redux/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import { combineReducers } from 'redux'
import {connectRouter} from 'connected-react-router'
import {reducer as form} from 'redux-form'
import authReducer from '../ducks/auth'
import personReducer from '../ducks/person'
import history from '../history'

export default combineReducers({
auth: authReducer,
router: connectRouter(history),
form
form,
person: personReducer
})
Loading