Cleanup code and make tweets work
This commit is contained in:
Родитель
f058739c8b
Коммит
accf89773b
4
.babelrc
4
.babelrc
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
|
||||
"presets": [
|
||||
"@babel/preset-env", "@babel/preset-react"
|
||||
"@babel/preset-env", "@babel/preset-react",
|
||||
],
|
||||
// "presets": [
|
||||
// [
|
||||
|
@ -13,6 +13,6 @@
|
|||
// ]
|
||||
// ],
|
||||
"plugins": [
|
||||
"transform-class-properties"
|
||||
"transform-class-properties", "@babel/transform-runtime"
|
||||
]
|
||||
}
|
|
@ -1,76 +1,34 @@
|
|||
import React, { Component } from 'react';
|
||||
import ReactDOM from "react-dom";
|
||||
import DataProvider from "./DataProvider";
|
||||
import Feed from "./Feed";
|
||||
import Tweets from "./Tweets";
|
||||
import "./TweeterBody.css";
|
||||
import "./App.css";
|
||||
|
||||
|
||||
|
||||
|
||||
class Tweets extends Component {
|
||||
|
||||
class App extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
tweetBeingTyped: '',
|
||||
tweetsAdded : []
|
||||
addTweetText: '',
|
||||
tweets : []
|
||||
}
|
||||
}
|
||||
|
||||
addATweetToState() {
|
||||
const tweetsAdded = Object.assign({}, this.state.tweetsAdded);
|
||||
tweetsAdded.push(this.state.tweetBeingTyped);
|
||||
this.setState({
|
||||
tweetsAdded,
|
||||
tweetBeingTyped: ''
|
||||
});
|
||||
fetch("api/tweets/", {
|
||||
method: "POST",
|
||||
headers: headers,
|
||||
body: JSON.stringify(tweetsAdded)
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
})
|
||||
.then(function (tweetsAdded) {
|
||||
console.log("your tweet was posted...here it is:", tweetsAdded)
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
typingTweet(e){
|
||||
console.log("THE EVENT IS :", e);
|
||||
this.setState({tweetBeingTyped: e.target.value})
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
return (<div className="container">
|
||||
<div className="tweet-container">
|
||||
<input onChange={this.typingTweet.bind(this)} placeholder="Say something . . ." type="text" className="tweet" style={{'width':'1000px'}}/>
|
||||
<button type = "button" onClick={this.addATweetToState.bind(this)} className="btn-tweet" id="tweet"> Tweet</button>
|
||||
</div>
|
||||
|
||||
<DataProvider
|
||||
endpoint="api/tweets/"
|
||||
tweetStateFromParent={this.state.tweetsAdded}
|
||||
render= {data => {
|
||||
console.log(data)
|
||||
return (
|
||||
<div>
|
||||
<Feed data={data} className = "Feed" />
|
||||
</div>
|
||||
|
||||
)
|
||||
|
||||
}}
|
||||
/>
|
||||
</div>)
|
||||
|
||||
return (
|
||||
<DataProvider
|
||||
endpoint="api/tweets/"
|
||||
render= {tweets => {
|
||||
return (
|
||||
<div>
|
||||
<Tweets tweets={tweets}/>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<Tweets />, document.getElementById("app"));
|
||||
ReactDOM.render(<App />, document.getElementById("app"));
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ class DataProvider extends Component {
|
|||
static propTypes = {
|
||||
endpoint: PropTypes.string.isRequired,
|
||||
render: PropTypes.func.isRequired,
|
||||
tweetStateFromParent: PropTypes.object
|
||||
tweets: PropTypes.object
|
||||
};
|
||||
|
||||
state = {
|
||||
|
@ -15,17 +15,15 @@ class DataProvider extends Component {
|
|||
placeholder: "Loading..."
|
||||
};
|
||||
|
||||
|
||||
componentWillReceiveProps(nextProps){
|
||||
if(nextProps.tweetStateFromParent!==this.props.tweetStateFromParent){
|
||||
if(nextProps.tweets!==this.props.tweets){
|
||||
|
||||
const last = nextProps.tweetStateFromParent[nextProps.tweetStateFromParent.length - 1];
|
||||
const last = nextProps.tweets[nextProps.tweets.length - 1];
|
||||
console.log("OK THE TWEET TO SEND DJANGO IS ", last);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
componentDidMount() {
|
||||
fetch(this.props.endpoint)
|
||||
.then(response => {
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from "prop-types";
|
||||
import "./TweeterBody.css"
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
class Tweets extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
addTweetText: '',
|
||||
tweets : props.tweets
|
||||
}
|
||||
}
|
||||
|
||||
// Posts tweet text to /api/tweets and adds the response to the list of tweets
|
||||
async addTweet() {
|
||||
const response = await fetch("api/tweets/", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': Cookies.get('csrftoken')
|
||||
},
|
||||
body: JSON.stringify({
|
||||
text: this.state.addTweetText
|
||||
})
|
||||
})
|
||||
const data = await response.json();
|
||||
const newTweets = Object.assign([], this.state.tweets);
|
||||
newTweets.unshift(data)
|
||||
console.log(newTweets)
|
||||
this.setState({tweets: newTweets, addTweetText: ''})
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="tweet-container">
|
||||
<input
|
||||
onChange={event => this.setState({addTweetText: event.target.value})}
|
||||
value={this.state.addTweetText}
|
||||
onKeyUp={event => {
|
||||
if (event.key == "Enter") {
|
||||
this.addTweet()
|
||||
}
|
||||
}}
|
||||
placeholder="Say something . . ."
|
||||
type="text" className="tweet" style={{'width':'1000px'}}/>
|
||||
<button type = "button" onClick={this.addTweet.bind(this)} className="btn-tweet" id="tweet"> Tweet</button>
|
||||
</div>
|
||||
|
||||
<div className="Feed">
|
||||
{this.state.tweets.length == 0 && <p>Nothing to show</p>}
|
||||
<ul>
|
||||
{this.state.tweets.map(tweet => (
|
||||
<li key={tweet.id}>
|
||||
<div className="avatar">
|
||||
<img src="https://i2.wp.com/www.mnleadership.org/wp-content/uploads/2017/02/Anonymous-Avatar.png?ssl=1" />
|
||||
<div className="hover">
|
||||
<div className="icon-twitter"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bubble-container">
|
||||
<div className="bubble">
|
||||
<h3>@{tweet.user}</h3><br />
|
||||
{tweet.text}
|
||||
<div className="over-bubble">
|
||||
<div className="icon-mail-reply action"></div>
|
||||
<div className="icon-retweet action"></div>
|
||||
<div className="icon-star"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="arrow"></div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>)
|
||||
}
|
||||
}
|
||||
|
||||
Tweets.propTypes = {
|
||||
tweets: PropTypes.array.isRequired
|
||||
};
|
||||
|
||||
export default Tweets;
|
|
@ -1,52 +0,0 @@
|
|||
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import "./TweeterBody.css"
|
||||
|
||||
const Feed = ({ data }) =>
|
||||
!data.length ? (
|
||||
<p>Nothing to show</p>
|
||||
) : (
|
||||
|
||||
<div className="Feed">
|
||||
|
||||
<ul>
|
||||
{data.map(el => (
|
||||
|
||||
|
||||
<li key={el.id}>
|
||||
<div className="avatar">
|
||||
<img src="https://i2.wp.com/www.mnleadership.org/wp-content/uploads/2017/02/Anonymous-Avatar.png?ssl=1" />
|
||||
<div className="hover">
|
||||
<div className="icon-twitter"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bubble-container">
|
||||
<div className="bubble">
|
||||
<h3>@{el.user}</h3><br />
|
||||
{el.text}
|
||||
<div className="over-bubble">
|
||||
<div className="icon-mail-reply action"></div>
|
||||
<div className="icon-retweet action"></div>
|
||||
<div className="icon-star"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="arrow"></div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
))}
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
);
|
||||
|
||||
Feed.propTypes = {
|
||||
data: PropTypes.array.isRequired
|
||||
};
|
||||
|
||||
|
||||
export default Feed;
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -714,6 +714,18 @@
|
|||
"@babel/helper-plugin-utils": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/plugin-transform-runtime": {
|
||||
"version": "7.4.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.4.4.tgz",
|
||||
"integrity": "sha512-aMVojEjPszvau3NRg+TIH14ynZLvPewH4xhlCW1w6A3rkxTS1m4uwzRclYR9oS+rl/dr+kT+pzbfHuAWP/lc7Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-module-imports": "^7.0.0",
|
||||
"@babel/helper-plugin-utils": "^7.0.0",
|
||||
"resolve": "^1.8.1",
|
||||
"semver": "^5.5.1"
|
||||
}
|
||||
},
|
||||
"@babel/plugin-transform-shorthand-properties": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz",
|
||||
|
@ -841,6 +853,21 @@
|
|||
"@babel/plugin-transform-react-jsx-source": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/runtime": {
|
||||
"version": "7.4.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.4.tgz",
|
||||
"integrity": "sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.2",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz",
|
||||
"integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/template": {
|
||||
"version": "7.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.0.tgz",
|
||||
|
@ -3786,8 +3813,7 @@
|
|||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
|
@ -3808,14 +3834,12 @@
|
|||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
@ -3830,20 +3854,17 @@
|
|||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
@ -3960,8 +3981,7 @@
|
|||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
@ -3973,7 +3993,6 @@
|
|||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
@ -3988,7 +4007,6 @@
|
|||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
@ -3996,14 +4014,12 @@
|
|||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
|
@ -4022,7 +4038,6 @@
|
|||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
|
@ -4103,8 +4118,7 @@
|
|||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
@ -4116,7 +4130,6 @@
|
|||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
@ -4202,8 +4215,7 @@
|
|||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
|
@ -4239,7 +4251,6 @@
|
|||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
@ -4259,7 +4270,6 @@
|
|||
"version": "3.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
|
@ -4303,14 +4313,12 @@
|
|||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -5030,6 +5038,11 @@
|
|||
"whatwg-fetch": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"js-cookie": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.0.tgz",
|
||||
"integrity": "sha1-Gywnmm7s44ChIWi5JIUmWzWx7/s="
|
||||
},
|
||||
"js-levenshtein": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
"homepage": "https://github.com/qubitron/tweeterapp#readme",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.4.3",
|
||||
"@babel/plugin-transform-runtime": "^7.4.4",
|
||||
"@babel/preset-env": "^7.4.3",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"antd": "^3.16.5",
|
||||
|
@ -39,7 +40,9 @@
|
|||
"webpack-dev-server": "^3.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"js-cookie": "^2.2.0",
|
||||
"react-hot-loader": "^4.8.4",
|
||||
"style-loader": "^0.23.1"
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ class TweetSerializer(serializers.ModelSerializer):
|
|||
|
||||
class Meta:
|
||||
model = Tweet
|
||||
fields = ('user', 'text', 'timestamp')
|
||||
fields = ('id', 'user', 'text', 'timestamp')
|
||||
|
||||
def validate_text(self, value):
|
||||
if len(value) < 5:
|
||||
|
|
Загрузка…
Ссылка в новой задаче