diff --git a/.gitignore b/.gitignore
index d30f40ef..604bb952 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,6 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
+
+#personal addings
+*.swp
diff --git a/README.md b/README.md
index d6331967..e84c875d 100644
--- a/README.md
+++ b/README.md
@@ -4,16 +4,42 @@ This repo is a code-along with the first project in the [React Nanodegree progra
Most of the commits in this repository correspond to videos in the program.
-## Project Setup
+## How to run this My Reads project locally
-* clone the Project - `git@github.com:udacity/reactnd-chirper-app.git`
-* install the dependencies - `npm install`
+First clone the project from desired repo
+To see current state:
+* clone from MarinEstrada page `git@github.com:MarinEstrada/reactnd-chirper-app.git`
+To see original starter state
+* clone the Project from original Udacity page - `git@github.com:udacity/reactnd-chirper-app.git`
+
+This project runs locally on "localhost:3000/" using
+* npm (Node Package Manager)
+* Docker
+
+### Using npm
+* install all project dependencies with:
+`npm install`
+* start the development server with:
+`npm start`
+
+### Using Docker
+To start the app locally run:
+`docker-compose up -d`
+
+To download extra needed dependencies run:
+`bash add_dependencies.sh {dependency_name}`
+
+To take a look at the logs:
+`docker-compose logs -f`
+
+To tear the containers down
+`docker-compose down`
## Contributing
-Because this is a code-along project and the commits correspond to specific videos in the program, we will not be accepting pull requests.
+Because this is a code-along project and the commits correspond to specific videos in the program, Udacity will not be accepting pull requests.
-If you feel like there's a major problem, please open an issue to discuss the problem and potential resolution.
+If you feel like there's a major problem, please open an issue on the Udacity repo to discuss the problem and potential resolution.
## License
diff --git a/add_dependancies.sh b/add_dependancies.sh
new file mode 100755
index 00000000..9dea923f
--- /dev/null
+++ b/add_dependancies.sh
@@ -0,0 +1,27 @@
+# !/bin/bash
+
+# any parmeter I want to add in, use dollar sign
+# eg $1 == first param, $2 == second, etc
+# can name param whatever you want
+
+dependency=$1
+container_name="reactnd-chirper-app_app_1"
+
+if [ -z "$dependency" ]
+then
+ echo "please call script with dependecy you would like to add"
+ echo "./add_dependancies.sh {dependecy}"
+else
+ echo "installing $dependecy"
+ echo "running: yarn add $dependecy, in docker container $container_name"
+ docker exec $container_name yarn add $dependency
+fi
+
+
+
+
+#yarn add prop-types
+#yarn add escape-string-regexp
+#yarn add sort-by
+#yarn add react-router-dom
+#yarn add prop-types
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 00000000..724770e4
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,14 @@
+version: "3.8"
+
+services:
+ app:
+ image: node:12-alpine
+ command: sh -c "yarn install && yarn start"
+ #command: sh -c "yarn create react-app udacity-goals-todos && cd udacity-goals-todos && yarn add prop-types"
+ ports:
+ - 3000:3000
+ working_dir: /reactnd-chirper-app
+ volumes:
+ - ./:/reactnd-chirper-app:consistent
+ stdin_open: true
+
diff --git a/package.json b/package.json
index 27798f4d..d2d0d2d2 100644
--- a/package.json
+++ b/package.json
@@ -3,9 +3,14 @@
"version": "0.1.0",
"private": true,
"dependencies": {
- "react": "^16.2.0",
- "react-dom": "^16.2.0",
- "react-scripts": "1.1.1"
+ "react": "^17.0.2",
+ "react-dom": "^17.0.2",
+ "react-icons": "^4.2.0",
+ "react-redux": "^7.2.4",
+ "react-redux-loading": "^4.6.1",
+ "react-scripts": "1.1.1",
+ "redux": "^4.1.0",
+ "redux-thunk": "^2.3.0"
},
"scripts": {
"start": "react-scripts start",
diff --git a/src/actions/authedUser.js b/src/actions/authedUser.js
new file mode 100644
index 00000000..39db9ade
--- /dev/null
+++ b/src/actions/authedUser.js
@@ -0,0 +1,8 @@
+export const SET_AUTHED_USER = 'SET_AUTHED_USER'
+
+export function setAuthedUser(id) {
+ return {
+ type: SET_AUTHED_USER,
+ id,
+ }
+}
diff --git a/src/actions/shared.js b/src/actions/shared.js
new file mode 100644
index 00000000..8edf3707
--- /dev/null
+++ b/src/actions/shared.js
@@ -0,0 +1,22 @@
+import { getInitialData } from '../utils/api'
+import { receiveUsers } from './users'
+import { receiveTweets } from './tweets'
+import { setAuthedUser } from './authedUser'
+import { showLoading, hideLoading } from 'react-redux-loading'
+
+//user currently 'logged in'
+const AUTHED_ID = 'tylermcginnis'
+
+export function handleInitialData() {
+ //using redux thunk pattern
+ return (dispatch) => {
+ dispatch(showLoading())
+ return getInitialData()
+ .then(({ users, tweets }) => {
+ dispatch(receiveUsers(users))
+ dispatch(receiveTweets(tweets))
+ dispatch(setAuthedUser(AUTHED_ID))
+ dispatch(hideLoading())
+ })
+ }
+}
diff --git a/src/actions/tweets.js b/src/actions/tweets.js
new file mode 100644
index 00000000..43311e29
--- /dev/null
+++ b/src/actions/tweets.js
@@ -0,0 +1,58 @@
+import { saveLikeToggle, saveTweet } from '../utils/api'
+import { showLoading, hideLoading } from 'react-redux-loading'
+
+export const RECEIVE_TWEETS = 'RECEIVE_TWEETS'
+export const TOGGLE_TWEET = 'TOGGLE_TWEET'
+export const ADD_TWEET = 'ADD_TWEET'
+
+function addTweet(tweet) {
+ return {
+ type: ADD_TWEET,
+ tweet,
+ }
+}
+
+export function handleAddTweet(text, replyingTo) {
+ return (dispatch, getState) => {
+ const { authedUser } = getState()
+
+ dispatch(showLoading())
+
+ return saveTweet({
+ text,
+ author: authedUser,
+ replyingTo
+ })
+ .then((tweet) => dispatch(addTweet(tweet)))
+ .then(() => dispatch(hideLoading()))
+ }
+}
+
+export function receiveTweets(tweets) {
+ return {
+ type: RECEIVE_TWEETS,
+ tweets,
+ }
+}
+
+function toggleTweet({ id, authedUser, hasLiked }) {
+ return {
+ type: TOGGLE_TWEET,
+ id,
+ authedUser,
+ hasLiked,
+ }
+}
+
+export function handleToggleTweet(info) {
+ return(dispatch) => {
+ dispatch(toggleTweet(info))
+
+ return saveLikeToggle(info)
+ .catch((e) => {
+ console.warn('Error in handleToggleTweet: ', e)
+ dispatch(toggleTweet(info))
+ alert("Error: couldn't like tweet. Try again.")
+ })
+ }
+}
diff --git a/src/actions/users.js b/src/actions/users.js
new file mode 100644
index 00000000..bd00beac
--- /dev/null
+++ b/src/actions/users.js
@@ -0,0 +1,8 @@
+export const RECEIVE_USERS = 'RECEIVE_USERS'
+
+export function receiveUsers(users) {
+ return {
+ type: RECEIVE_USERS,
+ users,
+ }
+}
diff --git a/src/components/App.js b/src/components/App.js
index 4859a621..757680c0 100644
--- a/src/components/App.js
+++ b/src/components/App.js
@@ -1,13 +1,34 @@
import React, { Component } from 'react'
+import { connect } from 'react-redux'
+import { handleInitialData } from '../actions/shared'
+import Dashboard from './Dashboard'
+import LoadingBar from 'react-redux-loading'
+import NewTweet from './NewTweet'
+import TweetPage from './TweetPage'
class App extends Component {
- render() {
- return (
-
- Starter Code
-
- )
- }
+ componentDidMount() {
+ this.props.dispatch(handleInitialData())
+ }
+ render() {
+ return (
+
+
+ {this.props.loading === true
+ ? null
+ : }
+
+ )
+ }
}
-export default App
\ No newline at end of file
+function mapStateToProps({ authedUser }) {
+ return{
+ loading: authedUser === null
+ }
+}
+
+//We don't need anything from state, so leave
+//first invocation blank
+//second invocation is where we will render (eg, App)
+export default connect(mapStateToProps)(App)
diff --git a/src/components/Dashboard.js b/src/components/Dashboard.js
new file mode 100644
index 00000000..0ba5476c
--- /dev/null
+++ b/src/components/Dashboard.js
@@ -0,0 +1,31 @@
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
+import Tweet from './Tweet'
+
+class Dashboard extends Component {
+ render() {
+ return(
+
+
Your Timeline
+
+ {this.props.tweetIds.map((id) => (
+ -
+
+
+ ))}
+
+
+ )
+ }
+}
+
+//takes in state of store,
+//specifically only portion it needs (tweets)
+function mapStateToProps ({ tweets }) {
+ return{
+ tweetIds: Object.keys(tweets)
+ .sort((a,b) => tweets[b].timestamp - tweets[a].timestamp)
+ }
+}
+
+export default connect(mapStateToProps)(Dashboard)
diff --git a/src/components/NewTweet.js b/src/components/NewTweet.js
new file mode 100644
index 00000000..3dad2201
--- /dev/null
+++ b/src/components/NewTweet.js
@@ -0,0 +1,63 @@
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
+import { handleAddTweet } from '../actions/tweets'
+
+class NewTweet extends Component {
+ state = {
+ text: '',
+ }
+
+ handleChange = (e) => {
+ const text = e.target.value
+
+ this.setState(() => ({ text }))
+ }
+
+ handleSubmit = (e) => {
+ e.preventDefault()
+
+ const { text } = this.state
+ const { dispatch, id } = this.props
+
+ dispatch(handleAddTweet(text, id))
+
+ this.setState(() => ({ text: '' }))
+
+ }
+
+ render() {
+
+ const { text } = this.state
+
+ {/* todo: Redirect to '/' if submited */}
+
+ const charsLeft = 280 - text.length
+
+ return(
+
+ )
+ }
+}
+
+export default connect()(NewTweet)
diff --git a/src/components/Tweet.js b/src/components/Tweet.js
new file mode 100644
index 00000000..31369f08
--- /dev/null
+++ b/src/components/Tweet.js
@@ -0,0 +1,99 @@
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
+import { formatTweet, formatDate } from '../utils/helpers'
+import { TiArrowBackOutline } from 'react-icons/ti'
+import { TiHeartOutline } from 'react-icons/ti'
+import { TiHeartFullOutline } from 'react-icons/ti'
+import { handleToggleTweet } from '../actions/tweets'
+
+class Tweet extends Component {
+
+ //helper function for like button
+ handleLike = (e) => {
+ e.preventDefault()
+
+ const { dispatch, tweet, authedUser } = this.props
+
+ dispatch(handleToggleTweet({
+ id: tweet.id,
+ hasLiked: tweet.hasLiked,
+ authedUser,
+ }))
+ }
+
+ // helper function for reply button
+ toParent = (e, id) => {
+ e.preventDefault()
+ // todo: Redirect to parent tweet
+ }
+
+ render() {
+ const { tweet } = this.props
+
+ if (tweet === null) {
+ return This Tweet doesn't exit
+ }
+
+ //deconstructing tweet
+ const {
+ name,
+ avatar,
+ timestamp,
+ text,
+ hasLiked,
+ likes,
+ replies,
+ parent } = tweet
+
+ return(
+
+

+
+
+
{name}
+
{formatDate(timestamp)}
+ {parent && (
+
+ )}
+
{text}
+
+
+
+ {replies !== 0 && replies}
+
+ {likes !== 0 && likes}
+
+
+
+ )
+ }
+}
+
+//note how second argument is component we are going to render
+function mapStateToProps({ authedUser, users, tweets }, { id }) {
+ const tweet = tweets[id]
+ const parentTweet = tweet ? tweets[tweet.replyingTo] : null
+
+ return {
+ authedUser,
+ tweet: tweet
+ ? formatTweet(tweet, users[tweet.author], authedUser, parentTweet)
+ : null
+ }
+}
+
+export default connect(mapStateToProps)(Tweet)
diff --git a/src/components/TweetPage.js b/src/components/TweetPage.js
new file mode 100644
index 00000000..b86c6062
--- /dev/null
+++ b/src/components/TweetPage.js
@@ -0,0 +1,43 @@
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
+import Tweet from './Tweet'
+import NewTweet from './NewTweet'
+
+class TweetPage extends Component {
+ render() {
+
+ const {id, replies} = this.props
+
+ return(
+
+
+
+ {replies.length !== 0 &&(
+
Replies
+ )}
+
+ {replies.map((replyId) => (
+ -
+
+
+ ))}
+
+
+ )
+ }
+}
+
+function mapStateToProps({ authedUser, tweets, users }, props) {
+ const {id} = props.match.params
+
+ return {
+ id,
+ replies: !tweets[id]
+ ? []
+ : tweets[id].replies.sort((a,b) => (
+ tweets[b].timestamp - tweets[a].timestamp
+ ))
+ }
+}
+
+export default connect(mapStateToProps)(TweetPage)
diff --git a/src/index.js b/src/index.js
index 67b4ea1e..9313e0af 100644
--- a/src/index.js
+++ b/src/index.js
@@ -2,5 +2,15 @@ import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './components/App'
+import { createStore } from 'redux'
+import { Provider } from 'react-redux'
+import reducer from './reducers'
+import middleware from './middleware'
-ReactDOM.render(, document.getElementById('root'))
\ No newline at end of file
+const store = createStore(reducer, middleware)
+
+ReactDOM.render(
+
+
+ ,
+document.getElementById('root'))
diff --git a/src/middleware/index.js b/src/middleware/index.js
new file mode 100644
index 00000000..aa1cf17a
--- /dev/null
+++ b/src/middleware/index.js
@@ -0,0 +1,8 @@
+import thunk from 'redux-thunk'
+import logger from './logger'
+import { applyMiddleware } from 'redux'
+
+export default applyMiddleware(
+ thunk,
+ logger,
+)
diff --git a/src/middleware/logger.js b/src/middleware/logger.js
new file mode 100644
index 00000000..a1873e1b
--- /dev/null
+++ b/src/middleware/logger.js
@@ -0,0 +1,11 @@
+//middleware to log changes to state on console
+const logger = (store) => (next) => (action) => {
+ console.group(action.type)
+ console.log('The action: ', action)
+ const returnValue = next(action)
+ console.log('The new state: ', store.getState())
+ console.groupEnd()
+ return returnValue
+}
+
+export default logger
diff --git a/src/reducers/authedUser.js b/src/reducers/authedUser.js
new file mode 100644
index 00000000..a6ee3d81
--- /dev/null
+++ b/src/reducers/authedUser.js
@@ -0,0 +1,10 @@
+import { SET_AUTHED_USER } from '../actions/authedUser'
+
+export default function authedUser(state = null, action) {
+ switch (action.type) {
+ case SET_AUTHED_USER:
+ return action.id
+ default:
+ return state
+ }
+}
diff --git a/src/reducers/index.js b/src/reducers/index.js
new file mode 100644
index 00000000..b615c5fe
--- /dev/null
+++ b/src/reducers/index.js
@@ -0,0 +1,14 @@
+import { combineReducers } from 'redux'
+import authedUser from './authedUser'
+import tweets from './tweets'
+import users from './users'
+import { loadingBarReducer } from 'react-redux-loading'
+
+//Use Redux combineReducers by passing it an object containing
+//all your reducers
+export default combineReducers({
+ authedUser,
+ tweets,
+ users,
+ loadingBar: loadingBarReducer,
+})
diff --git a/src/reducers/tweets.js b/src/reducers/tweets.js
new file mode 100644
index 00000000..5e792803
--- /dev/null
+++ b/src/reducers/tweets.js
@@ -0,0 +1,42 @@
+import { RECEIVE_TWEETS, TOGGLE_TWEET, ADD_TWEET } from '../actions/tweets'
+
+export default function tweets(state = {}, action) {
+ switch (action.type) {
+ case RECEIVE_TWEETS:
+ return {
+ ...state,
+ ...action.tweets
+ }
+ case TOGGLE_TWEET:
+ return {
+ ...state,
+ [action.id]: {
+ ...state[action.id],
+ likes: action.hasLiked === true
+ ? state[action.id].likes.filter((userId) => userId !== action.authedUser)
+ : state[action.id].likes.concat([action.authedUser])
+ }
+ }
+ case ADD_TWEET:
+ const { tweet } = action
+
+ let replyingTo = {}
+ if(tweet.replyingTo !== null){
+ replyingTo = {
+ [tweet.replyingTo]: {
+ ...state[tweet.replyingTo],
+ replies: state[tweet.replyingTo].replies.concat([tweet.id])
+ }
+ }
+ }
+
+ return {
+ ...state,
+ [action.tweet.id]: action.tweet,
+ ...replyingTo,
+ }
+
+ default:
+ return state
+ }
+}
diff --git a/src/reducers/users.js b/src/reducers/users.js
new file mode 100644
index 00000000..c75b892d
--- /dev/null
+++ b/src/reducers/users.js
@@ -0,0 +1,13 @@
+import { RECEIVE_USERS } from '../actions/users'
+
+export default function users(state = {}, action) {
+ switch (action.type) {
+ case RECEIVE_USERS:
+ return {
+ ...state,
+ ...action.users
+ }
+ default:
+ return state
+ }
+}
diff --git a/yarn.lock b/yarn.lock
index bd36e402..281585c8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,6 +2,50 @@
# yarn lockfile v1
+"@babel/runtime@^7.12.1", "@babel/runtime@^7.9.2":
+ version "7.14.6"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.6.tgz#535203bc0892efc7dec60bdc27b2ecf6e409062d"
+ integrity sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==
+ dependencies:
+ regenerator-runtime "^0.13.4"
+
+"@types/hoist-non-react-statics@^3.3.0":
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
+ integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
+ dependencies:
+ "@types/react" "*"
+ hoist-non-react-statics "^3.3.0"
+
+"@types/prop-types@*":
+ version "15.7.4"
+ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11"
+ integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==
+
+"@types/react-redux@^7.1.16":
+ version "7.1.18"
+ resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.18.tgz#2bf8fd56ebaae679a90ebffe48ff73717c438e04"
+ integrity sha512-9iwAsPyJ9DLTRH+OFeIrm9cAbIj1i2ANL3sKQFATqnPWRbg+jEFXyZOKHiQK/N86pNRXbb4HRxAxo0SIX1XwzQ==
+ dependencies:
+ "@types/hoist-non-react-statics" "^3.3.0"
+ "@types/react" "*"
+ hoist-non-react-statics "^3.3.0"
+ redux "^4.0.0"
+
+"@types/react@*":
+ version "17.0.14"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.14.tgz#f0629761ca02945c4e8fea99b8177f4c5c61fb0f"
+ integrity sha512-0WwKHUbWuQWOce61UexYuWTGuGY/8JvtUe/dtQ6lR4sZ3UiylHotJeWpf3ArP9+DSGUoLY3wbU59VyMrJps5VQ==
+ dependencies:
+ "@types/prop-types" "*"
+ "@types/scheduler" "*"
+ csstype "^3.0.2"
+
+"@types/scheduler@*":
+ version "0.16.2"
+ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
+ integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
+
abab@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e"
@@ -1725,6 +1769,11 @@ cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
dependencies:
cssom "0.3.x"
+csstype@^3.0.2:
+ version "3.0.8"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.8.tgz#d2266a792729fb227cd216fb572f43728e1ad340"
+ integrity sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==
+
currently-unhandled@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
@@ -2951,6 +3000,13 @@ hoek@4.x.x:
version "4.2.1"
resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb"
+hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
+ integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
+ dependencies:
+ react-is "^16.7.0"
+
home-or-tmp@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
@@ -3708,6 +3764,11 @@ js-tokens@^3.0.0, js-tokens@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
+"js-tokens@^3.0.0 || ^4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
+ integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+
js-yaml@^3.4.3, js-yaml@^3.7.0, js-yaml@^3.9.1:
version "3.10.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc"
@@ -3981,6 +4042,13 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1:
dependencies:
js-tokens "^3.0.0"
+loose-envify@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
+ integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
+ dependencies:
+ js-tokens "^3.0.0 || ^4.0.0"
+
loud-rejection@^1.0.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
@@ -4990,7 +5058,7 @@ promise@^7.1.1:
dependencies:
asap "~2.0.3"
-prop-types@^15.5.10, prop-types@^15.6.0:
+prop-types@^15.5.10:
version "15.6.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca"
dependencies:
@@ -4998,6 +5066,15 @@ prop-types@^15.5.10, prop-types@^15.6.0:
loose-envify "^1.3.1"
object-assign "^4.1.1"
+prop-types@^15.6.2, prop-types@^15.7.2:
+ version "15.7.2"
+ resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
+ integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
+ dependencies:
+ loose-envify "^1.4.0"
+ object-assign "^4.1.1"
+ react-is "^16.8.1"
+
proxy-addr@~2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.3.tgz#355f262505a621646b3130a728eb647e22055341"
@@ -5137,19 +5214,54 @@ react-dev-utils@^5.0.0:
strip-ansi "3.0.1"
text-table "0.2.0"
-react-dom@^16.2.0:
- version "16.2.0"
- resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044"
+react-dom@^17.0.2:
+ version "17.0.2"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
+ integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
dependencies:
- fbjs "^0.8.16"
loose-envify "^1.1.0"
object-assign "^4.1.1"
- prop-types "^15.6.0"
+ scheduler "^0.20.2"
react-error-overlay@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-4.0.0.tgz#d198408a85b4070937a98667f500c832f86bd5d4"
+react-icons@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.2.0.tgz#6dda80c8a8f338ff96a1851424d63083282630d0"
+ integrity sha512-rmzEDFt+AVXRzD7zDE21gcxyBizD/3NqjbX6cmViAgdqfJ2UiLer8927/QhhrXQV7dEj/1EGuOTPp7JnLYVJKQ==
+
+react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.1:
+ version "16.13.1"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
+ integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+
+react-lifecycles-compat@^3.0.2:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
+ integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
+
+react-redux-loading@^4.6.1:
+ version "4.6.1"
+ resolved "https://registry.yarnpkg.com/react-redux-loading/-/react-redux-loading-4.6.1.tgz#29b3e3d90625b00cd795423fd9cdb1b4ca09438e"
+ integrity sha512-MrpabKX0LTwqVq/gQjffV44GvVN7F1nZD7Ur1g8twYt4D/Yoq3ezL2f3nQybcXkmlMuYH6YFXgalLKoDDmPIrg==
+ dependencies:
+ prop-types "^15.6.2"
+ react-lifecycles-compat "^3.0.2"
+
+react-redux@^7.2.4:
+ version "7.2.4"
+ resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.4.tgz#1ebb474032b72d806de2e0519cd07761e222e225"
+ integrity sha512-hOQ5eOSkEJEXdpIKbnRyl04LhaWabkDPV+Ix97wqQX3T3d2NQ8DUblNXXtNMavc7DpswyQM6xfaN4HQDKNY2JA==
+ dependencies:
+ "@babel/runtime" "^7.12.1"
+ "@types/react-redux" "^7.1.16"
+ hoist-non-react-statics "^3.3.2"
+ loose-envify "^1.4.0"
+ prop-types "^15.7.2"
+ react-is "^16.13.1"
+
react-scripts@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-1.1.1.tgz#279d449f7311fed910506987a1ade014027788a8"
@@ -5194,14 +5306,13 @@ react-scripts@1.1.1:
optionalDependencies:
fsevents "^1.1.3"
-react@^16.2.0:
- version "16.2.0"
- resolved "https://registry.yarnpkg.com/react/-/react-16.2.0.tgz#a31bd2dab89bff65d42134fa187f24d054c273ba"
+react@^17.0.2:
+ version "17.0.2"
+ resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
+ integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
dependencies:
- fbjs "^0.8.16"
loose-envify "^1.1.0"
object-assign "^4.1.1"
- prop-types "^15.6.0"
read-pkg-up@^1.0.1:
version "1.0.1"
@@ -5290,6 +5401,18 @@ reduce-function-call@^1.0.1:
dependencies:
balanced-match "^0.4.2"
+redux-thunk@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622"
+ integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==
+
+redux@^4.0.0, redux@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.0.tgz#eb049679f2f523c379f1aff345c8612f294c88d4"
+ integrity sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==
+ dependencies:
+ "@babel/runtime" "^7.9.2"
+
regenerate@^1.2.1:
version "1.3.3"
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f"
@@ -5298,6 +5421,11 @@ regenerator-runtime@^0.11.0:
version "0.11.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
+regenerator-runtime@^0.13.4:
+ version "0.13.7"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55"
+ integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==
+
regenerator-transform@^0.10.0:
version "0.10.1"
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd"
@@ -5553,6 +5681,14 @@ sax@^1.2.1, sax@~1.2.1:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+scheduler@^0.20.2:
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
+ integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+
schema-utils@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf"