Cleanup code and make tweets work

This commit is contained in:
root 2019-04-27 21:41:46 +00:00
Родитель f058739c8b
Коммит accf89773b
9 изменённых файлов: 303 добавлений и 164 удалений

Просмотреть файл

@ -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;

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

73
package-lock.json сгенерированный
Просмотреть файл

@ -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: