init frontend

This commit is contained in:
DieMyst
2019-08-16 17:20:50 +03:00
parent 92af937fc7
commit 6b061dde92
12 changed files with 367 additions and 0 deletions

View File

@ -0,0 +1,36 @@
import { saveMessage } from "../utils/api";
//importing loading bar to show when we submit a tweet
import { showLoading, hideLoading } from "react-redux-loading";
export const ADD_MESSAGE = "ADD_MESSAGE";
export const RECEIVE_MESSAGES = "RECEIVE_MESSAGES";
function addMessage(message) {
return {
type: ADD_MESSAGE,
message
};
}
//args: message text and the message that the newTweet is replying to, if any
export function handleAddMessage(text, name) {
//using getState to get the current state of our store
return (dispatch) => {
dispatch(showLoading());
return saveMessage({
text: text,
name: name
})
.then(message => dispatch(addMessage(message)))
.then(() => dispatch(hideLoading()));
};
}
//action creator
export function receiveMessages(messages) {
return {
type: RECEIVE_MESSAGES,
messages
};
}

View File

@ -0,0 +1,21 @@
import { getMessages } from "../utils/api";
//importing action creators
import { receiveMessages } from "./messages";
//importing action creators of loading bar
import { showLoading, hideLoading } from "react-redux-loading";
export function handleInitialData() {
return dispatch => {
//before retrieving info, show loading bar
dispatch(showLoading());
return getMessages().then((messages) => {
dispatch(receiveMessages(messages));
//after everything has loaded, hide loading bar
dispatch(hideLoading());
});
};
}

View File

@ -0,0 +1,42 @@
import React, { Component, Fragment } from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import { connect } from "react-redux";
import { handleInitialData } from "../actions/shared";
import LoadingBar from "react-redux-loading"; //importing the loading bar given by react-redux-loading
import Dashboard from "./Dashboard";
import NewMessage from "./NewMessage";
class App extends Component {
componentDidMount() {
this.props.dispatch(handleInitialData());
}
render() {
return (
<Router>
{/* using a fragment so we don't add another element (div) to the DOM */}
<Fragment>
<LoadingBar />
<div className="container">
{this.props.loading === true ? null : (
<div>
<NewMessage />
<Dashboard />
</div>
)}
</div>
</Fragment>
</Router>
);
}
}
function mapStateToProps({ }) {
return {
};
}
export default connect(mapStateToProps)(App);

View File

@ -0,0 +1,30 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import Message from "./Message";
class Dashboard extends Component {
render() {
return (
<div>
<h3 className="center">Your Timeline</h3>
<ul className="dashbord-list">
{this.props.messages.map((m, i) => {
return (
<li key={i}>
<Message message={m} />
</li>
)
})}
</ul>
</div>
);
}
}
//destructuring messages from state
function mapStateToProps(state) {
return state;
}
export default connect(mapStateToProps)(Dashboard);

View File

@ -0,0 +1,34 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import { withRouter } from "react-router-dom";
class Message extends Component {
render() {
const { message } = this.props;
if (message === null) {
return <p>This message doesn't exist</p>;
}
const {
name,
text
} = message;
return (
<div className="message-info">
<div>
<span>{name}</span>
<p>{text}</p>
</div>
</div>
);
}
}
function mapStateToProps(message) {
return message;
}
//using withRouter because this component is not being rendered by react router, so to have access to history props, we need to use withRouter
export default withRouter(connect(mapStateToProps)(Message));

View File

@ -0,0 +1,71 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import { handleAddMessage } from "../actions/messages";
class NewMessage extends Component {
state = {
text: "",
name: ""
};
handleChangeText = e => {
const text = e.target.value;
this.setState(() => ({
text
}));
};
handleChangeName = e => {
const name = e.target.value;
this.setState(() => ({
name
}));
};
handleSubmit = e => {
e.preventDefault();
const { text, name } = this.state;
const { dispatch } = this.props;
dispatch(handleAddMessage(text, name));
//reset state to default
this.setState(() => ({
text: "",
name: ""
}));
};
render() {
const { text, name } = this.state;
const messageLeft = 280 - text.length;
return (
<div>
<h3 className="center">Compose new Tweet </h3>
<form className="new-message" onSubmit={this.handleSubmit}>
<textarea
placeholder="Message"
value={text}
onChange={this.handleChangeText}
className="textarea"
maxLength={280}
/>
<input type="text" placeholder="Name" value={name} onChange={this.handleChangeName}/>
{/* show how many characters are left */}
{messageLeft <= 100 && <div className="message-length">{messageLeft}</div>}
{/* button is disabled if it's an empty string */}
<button className="btn" type="submit" disabled={text === ""}>
Submit
</button>
</form>
</div>
);
}
}
export default connect()(NewMessage);

View File

@ -0,0 +1,6 @@
import thunk from "redux-thunk";
import logger from "./logger";
import { applyMiddleware } from "redux";
export default applyMiddleware(thunk, logger);

View File

@ -0,0 +1,11 @@
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;

View File

@ -0,0 +1,10 @@
import { combineReducers } from "redux";
import messages from "./messages";
import { loadingBarReducer } from "react-redux-loading";
export default combineReducers({
messages,
loadingBar: loadingBarReducer
});

View File

@ -0,0 +1,20 @@
import { RECEIVE_MESSAGES, ADD_MESSAGE } from "../actions/messages";
export default function messages(state = [], action) {
switch (action.type) {
case RECEIVE_MESSAGES:
return action.messages;
case ADD_MESSAGE:
console.log("reducer message");
console.log(state);
console.log(action);
const { message } = action; //getting the newly added message from action
state.push(message);
return state;
default:
return state;
}
}

View File

@ -0,0 +1,48 @@
let messages = [
{
text: "Shoutout to all the speakers I know for whom English is not a first language, but can STILL explain a concept well. It's hard enough to give a good talk in your mother tongue!",
name: "sarah_edo"
},
{
text: "I hope one day the propTypes pendulum swings back. Such a simple yet effective API. Was one of my favorite parts of React.",
name: "tylermcginnis"
},
{
text: "Want to work at Facebook/Google/:BigCompany? Start contributing code long before you ever interview there.",
name: "tylermcginnis"
},
{
text: "Puppies 101: buy a hamper with a lid on it.",
name: "sarah_edo"
},
{
text: "Is there a metric like code coverage, but that shows lines that, if changed (in a syntactically correct way), wouldnt cause tests to fail?",
name: "dan_abramov",
},
{
text: "React came out 'rethinking best practices'. It has since accumulated 'best practices' of its own. Lets see if we can do better.",
name: "dan_abramov",
},
{
text: "I think I realized I like dogs so much because I can really relate to being motivated by snacks",
name: "sarah_edo",
},
{
text: "Maybe the real benefit of open source was the friendships we made along the way?",
name: "tylermcginnis",
}
];
export function _getMessages() {
return new Promise((res, rej) => {
setTimeout(() => res(messages), 1000)
})
}
export function _saveMessage(message) {
return new Promise((res, rej) => {
setTimeout(() => {
res(message)
}, 1000)
})
}

38
frontend/src/utils/api.js Normal file
View File

@ -0,0 +1,38 @@
import {
_getMessages,
_saveMessage,
} from './_DATA.js'
import * as fluence from "fluence";
let session = fluence.directConnect("localhost", 30000, 1);
export function getMessages () {
let request = {
action: "Fetch"
};
return session.request(JSON.stringify(request))
.then((r) => r.asString())
.then((r) => {
let posts = JSON.parse(r);
console.log("posts");
console.log(posts);
return {
messages: posts.map((p) => {
return {
text: p.msg,
name: p.username
}
})
}
});
}
export function saveMessage(message) {
let request = {
action: "Post",
msg: message.text,
username: message.name
};
return session.requestAsync(request).then(() => message);
}