Skip to content
This repository was archived by the owner on Jun 28, 2022. It is now read-only.

UI #4

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open

UI #4

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*

#personal addings
*.swp
36 changes: 31 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 - `[email protected]: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 `[email protected]:MarinEstrada/reactnd-chirper-app.git`
To see original starter state
* clone the Project from original Udacity page - `[email protected]: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

Expand Down
27 changes: 27 additions & 0 deletions add_dependancies.sh
Original file line number Diff line number Diff line change
@@ -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
14 changes: 14 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -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

11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
8 changes: 8 additions & 0 deletions src/actions/authedUser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const SET_AUTHED_USER = 'SET_AUTHED_USER'

export function setAuthedUser(id) {
return {
type: SET_AUTHED_USER,
id,
}
}
22 changes: 22 additions & 0 deletions src/actions/shared.js
Original file line number Diff line number Diff line change
@@ -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())
})
}
}
58 changes: 58 additions & 0 deletions src/actions/tweets.js
Original file line number Diff line number Diff line change
@@ -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.")
})
}
}
8 changes: 8 additions & 0 deletions src/actions/users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const RECEIVE_USERS = 'RECEIVE_USERS'

export function receiveUsers(users) {
return {
type: RECEIVE_USERS,
users,
}
}
37 changes: 29 additions & 8 deletions src/components/App.js
Original file line number Diff line number Diff line change
@@ -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 (
<div>
Starter Code
</div>
)
}
componentDidMount() {
this.props.dispatch(handleInitialData())
}
render() {
return (
<div>
<LoadingBar />
{this.props.loading === true
? null
: <TweetPage match={{params: {id: '6h5ims9iks66d4m7kqizmv'}}} />}
</div>
)
}
}

export default App
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)
31 changes: 31 additions & 0 deletions src/components/Dashboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React, { Component } from 'react'
import { connect } from 'react-redux'
import Tweet from './Tweet'

class Dashboard extends Component {
render() {
return(
<div>
<h3 className='center'>Your Timeline</h3>
<ul className= 'dashboard-list'>
{this.props.tweetIds.map((id) => (
<li key={id}>
<Tweet id={id} />
</li>
))}
</ul>
</div>
)
}
}

//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)
63 changes: 63 additions & 0 deletions src/components/NewTweet.js
Original file line number Diff line number Diff line change
@@ -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(
<div>
<h3 className='center' >Compose New Tweet</h3>
<form className='new-tweet'onSubmit={this.handleSubmit} >
<textarea
placeholder="What's happening"
value={text}
onChange={this.handleChange}
className='textarea'
maxLength={280}
/>
{charsLeft <= 100 &&(
<div className='tweet-length' >
{charsLeft}
</div>
)}
<button
className='btn'
type='submit'
disabled={text === ''}
>Submit</button>
</form>
</div>
)
}
}

export default connect()(NewTweet)
Loading