simple style, polling

This commit is contained in:
DieMyst
2019-08-18 00:33:06 +03:00
parent e71e01dde5
commit bf455c416c
11 changed files with 279 additions and 105 deletions

View File

@ -9,7 +9,6 @@
"react-icons": "^3.7.0",
"react-redux": "^7.1.0",
"react-redux-loading": "^1.0.1",
"react-router-dom": "^5.0.1",
"redux": "^4.0.4",
"redux-thunk": "^2.3.0",
"fluence": "^0.3.9"

View File

@ -1,6 +1,4 @@
import { saveMessage } from "../utils/api";
//importing loading bar to show when we submit a tweet
import {getMessages, saveMessage} from "../utils/api";
import { showLoading, hideLoading } from "react-redux-loading";
export const ADD_MESSAGE = "ADD_MESSAGE";
@ -13,9 +11,31 @@ function addMessage(message) {
};
}
//args: message text and the message that the newTweet is replying to, if any
export function fetchPosts(counter) {
return dispatch => {
return getMessages().then((messages) => {
dispatch(receiveMessages(messages, counter));
dispatch(hideLoading());
});
};
}
export function handleInitialData() {
return dispatch => {
//before retrieving info, show loading bar
dispatch(showLoading());
return getMessages().then((messages) => {
dispatch(receiveMessages(messages, 0));
//after everything has loaded, hide loading bar
dispatch(hideLoading());
});
};
}
export function handleAddMessage(text, name) {
//using getState to get the current state of our store
return (dispatch) => {
dispatch(showLoading());
return saveMessage({
@ -28,9 +48,10 @@ export function handleAddMessage(text, name) {
}
//action creator
export function receiveMessages(messages) {
export function receiveMessages(messages, counter) {
return {
type: RECEIVE_MESSAGES,
counter,
messages
};
}

View File

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

@ -1,22 +1,16 @@
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 React, {Component, Fragment} from "react";
import {BrowserRouter as Router} from "react-router-dom";
import {connect} from "react-redux";
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">
@ -33,10 +27,4 @@ class App extends Component {
}
}
function mapStateToProps({ }) {
return {
};
}
export default connect(mapStateToProps)(App);
export default connect()(App);

View File

@ -2,14 +2,53 @@ import React, { Component } from "react";
import { connect } from "react-redux";
import Message from "./Message";
import {handleInitialData, fetchPosts} from "../actions/messages";
class Dashboard extends Component {
constructor(props) {
super(props);
this.state = {counter: 1, lastUpdateCounter: 0};
}
componentDidMount() {
this.pollingMessages = setInterval(
() => this.getMessages(),
2000
);
this.props.dispatch(handleInitialData());
}
componentWillUnmount() {
clearInterval(this.pollingMessages);
}
getMessages() {
this.props.dispatch(fetchPosts(this.state.counter + 1));
this.setState((state) => ({
counter: state.counter + 1
}));
}
shouldComponentUpdate(nextProps) {
return nextProps.updates.counter > this.state.lastUpdateCounter
}
render() {
let updates = this.props.updates;
if (updates.counter) {
this.setState(() => ({
lastUpdateCounter: updates.counter
}));
}
return (
<div>
<h3 className="center">Your Timeline</h3>
<b>Counter: {this.state.counter}</b>
<b>Last update: {this.state.lastUpdateCounter}</b>
<h3 className="center">Feed</h3>
<ul className="dashbord-list">
{this.props.messages.map((m, i) => {
{updates.messages.map((m, i) => {
return (
<li key={i}>
<Message message={m} />

View File

@ -18,7 +18,7 @@ class Message extends Component {
return (
<div className="message-info">
<div>
<span>{name}</span>
<span><b>{name}</b></span>
<p>{text}</p>
</div>
</div>

View File

@ -1,6 +1,6 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import { handleAddMessage } from "../actions/messages";
import React, {Component} from "react";
import {connect} from "react-redux";
import {handleAddMessage} from "../actions/messages";
class NewMessage extends Component {
state = {
@ -45,7 +45,7 @@ class NewMessage extends Component {
return (
<div>
<h3 className="center">Compose new Tweet </h3>
<h3 className="center">Compose new message </h3>
<form className="new-message" onSubmit={this.handleSubmit}>
<textarea
placeholder="Message"
@ -54,7 +54,8 @@ class NewMessage extends Component {
className="textarea"
maxLength={280}
/>
<input type="text" placeholder="Name" value={name} onChange={this.handleChangeName}/>
<input type="text" className="nameinput" placeholder="Name" value={name}
onChange={this.handleChangeName}/>
{/* show how many characters are left */}
{messageLeft <= 100 && <div className="message-length">{messageLeft}</div>}

View File

@ -1,13 +1,171 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
padding: 0;
font-family: sans-serif;
color: #252525;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
a {
text-decoration: none;
color: #252525;
}
.container {
/* border: 1px solid #dad7d7; */
max-width: 1000px;
margin: 0 auto;
padding: 10px;
}
.btn {
text-transform: uppercase;
margin: 20px auto;
padding: 10px;
border: 1px solid rgba(0, 0, 0, 0.29);
cursor: pointer;
background: #fff;
font-size: 16px;
width: 250px;
position: relative;
}
.btn:hover {
border-color: rgba(0, 0, 0, 0.5);
text-decoration: none;
}
.btn:focus {
outline: 0;
font-weight: 700;
border-width: 2px;
}
.center {
text-align: center;
}
.active {
font-weight: bold;
}
.nav ul {
display: flex;
flex-direction: row;
justify-content: flex-start;
text-decoration: none;
}
.nav li:first-child {
padding-left: 0;
}
ul {
padding-left: 0;
}
li {
list-style-type: none;
padding: 6px;
text-decoration: none;
}
.avatar {
height: 50px;
border-radius: 25px;
margin: 10px;
}
.message {
width: 100%;
max-width: 590px;
padding: 10px;
display: flex;
margin: 0 auto;
border: 1px solid #dad7d7;
border-radius: 3px;
cursor: pointer;
}
.message-info {
margin: 5px;
display: flex;
flex-direction: column;
}
/* Hacky but less typing in the video */
.message-info > div > span:first-child {
font-weight: bold;
margin-right: 5px;
}
.message-info > div > span:nth-child(2) {
color: #969696;
font-size: 16px;
}
.message-info > div > div {
color: #969696;
font-size: 15px;
}
.message-info > div > p {
font-size: 18px;
margin: 6px 0;
}
.message-icons {
display: flex;
align-items: center;
}
.message-icons > span {
color: #969696;
margin: 0 15px 0 5px;
font-size: 18px !important;
}
.message-icon {
font-size: 27px;
color: #697784;
}
.message-icon:hover {
color: #00b5d6;
cursor: pointer;
}
.replying-to {
border: none;
background: transparent;
margin: 0;
padding: 0;
color: #969696;
cursor: pointer;
}
.heart-button {
background: transparent;
border: none;
}
.new-message {
width: 100%;
max-width: 590px;
margin: 0 auto;
display: flex;
flex-direction: column;
}
.textarea {
border-radius: 4px;
border: 1px solid #dad7d7;
padding: 10px;
font-size: 15px;
height: 100px;
}
.nameinput {
border-radius: 4px;
border: 1px solid #dad7d7;
padding: 10px;
font-size: 15px;
}
.message-length {
text-align: right;
margin-top: 10px;
font-size: 20px;
color: #c3392a;
}

View File

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

View File

@ -1,16 +1,16 @@
import { RECEIVE_MESSAGES, ADD_MESSAGE } from "../actions/messages";
export default function messages(state = [], action) {
export default function updates(state = {messages: []}, action) {
switch (action.type) {
case RECEIVE_MESSAGES:
return action.messages;
return action;
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);
state.messages.unshift(message);
return state;

View File

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