Ivan Asmer 6 年之前
父節點
當前提交
333003f59b
共有 3 個文件被更改,包括 160 次插入16 次删除
  1. 1 0
      src/1/1.js
  2. 15 0
      src/App.css
  3. 144 16
      src/App.js

+ 1 - 0
src/1/1.js

@@ -0,0 +1 @@
+import '../2/App.css'

+ 15 - 0
src/App.css

@@ -41,3 +41,18 @@
     padding: 10px;
     background-color: #CCC;
 }
+
+.commentList {
+    border-radius: 10px;
+    margin: 10px;
+    padding: 10px;
+    background-color: #EEE;
+}
+
+
+.commentList div{
+    background-color: #FFF;
+    border-radius: 5px;
+    margin: 5px;
+    padding: 5px;
+}

+ 144 - 16
src/App.js

@@ -1,6 +1,6 @@
 import React, { Component } from 'react';
 import logo from './logo.svg';
-import './App.css';
+import './1/1.js';
 
 import {Router, Route, Link, Switch} from "react-router-dom";
 import createHistory from "history/createBrowserHistory";
@@ -12,28 +12,45 @@ import { GraphQLClient } from 'graphql-request'
 
 const gql = new GraphQLClient("http://localhost:4000/graphql", { headers: {} })
 
-gql.request(`query getPosts {
-  posts {
-    id
-    title
-    text
-    timestamp
-    tagz
-  }
-}`).then(data => store.dispatch({type: "DATA", data}))
+
+function getFeed() {
+    store.dispatch({type: 'EMPTY'})
+    gql.request(`query getPosts {
+      posts {
+        id
+        title
+        text
+        timestamp
+        tagz
+      }
+    }`).then(data => store.dispatch({type: "DATA", data}))
+}
 
 function postsReducer(state, action)
 {
+    if (state === undefined || action.type == 'EMPTY'){
+        return {data: [], status: 'EMPTY'}
+    }
     if (action.type === 'DATA'){
-        console.log(action.data)
         return {data: action.data.posts, status: 'DATA'}
     }
-    return {data: [], status: 'EMPTY'}
+    return state
+}
+
+function postReducer(state, action){
+    if (state === undefined){
+        return {data: {}, status: 'EMPTY'}
+    }
+    if (action.type === 'POST'){
+        return {data: action.data.post, status: 'DATA'}
+    }
+    return state;
 }
 
 
 const reducers = combineReducers({
     posts: postsReducer,
+    post:  postReducer,
 })
 
 var store = createStore(reducers);
@@ -44,9 +61,16 @@ var store = createStore(reducers);
 
 class TagList extends Component {
     render() {
+        if (this.props.tags){
+            return (
+                <div className="tagList">
+                    {this.props.tags.map(tag => <span>{tag}</span>)}
+                </div>
+            )
+        }
         return (
             <div className="tagList">
-                {this.props.tags.map(tag => <span>{tag}</span>)}
+                Loading...
             </div>
         )
     }
@@ -88,24 +112,127 @@ class Feed extends Component {
 const mapStateToProps = function(store) {
   return {
     posts: store.posts,
+    post: store.post,
   };
 }
 
 Feed = connect(mapStateToProps)(Feed)
 
-let FeedPage = (props) => <Feed />
+class FeedPage extends Component {
+    render (){
+        getFeed();
+        return (
+            <div>
+              <Link to='/addPost'>Add post...</Link>
+              <Feed />
+            </div>
+        )
+    }
+}
+
+class Comment extends Component {
+    render (){
+        return (
+            <div>
+              {this.props.comment.text}
+            </div>
+        )
+    }
+}
+
+class CommentList extends Component {
+    render (){
+        if (this.props.comments){
+            return (
+                <div className='commentList'>
+                    {this.props.comments.map( comment => <Comment comment={comment} key={comment.id}/>)}
+                </div>
+            )
+        }
+        return (
+            <div className='commentList'>
+                Loading...
+            </div>
+        )
+    }
+}
 
 class Post extends Component {
     render(){
+        console.log(this.props.post.data)
+        if (this.props.post.data.status === 'EMPTY'){
+            return (
+                <div className='post'>
+                    Loading...
+                </div>
+            )
+        }
+        return (
+            <div className='post'>
+                <h1>{this.props.post.data.title}</h1>
+                <div>{this.props.post.data.text}</div>
+                <div>{(new Date(this.props.post.data.timestamp *1000)).toLocaleString()}</div>
+                <TagList tags={this.props.post.data.tagz} />
+                <CommentList comments={this.props.post.data.comments} />
+            </div>
+        )
+    }
+}
+
+Post = connect(mapStateToProps)(Post)
+
+
+class PostPage extends Component {
+    render(){
+        gql.request(`query getPostWithComments($postID: Int!){
+                          post(id:$postID){
+                            id
+                            title
+                            text
+                            timestamp
+                            tagz
+                            comments {
+                              id
+                              text
+                              age
+                            }
+                          }
+                        }`, {postID: this.props.match.params.id})
+            .then(data => store.dispatch({type: 'POST', data}))
+        return (
+            <Post id={this.props.match.params.id}/>
+        );
+    }
+}
+
+class AddPostPage extends Component {
+
+    save(){
+        gql.request(
+            `mutation createPost($title: String!, $text:String!) {
+              createPost(title: $title, text: $text) {
+                 title
+                 text
+              }
+            }`,
+            {title: this.title.value,
+             text: this.text.value}
+        )
+    }
+
+
+    render (){
         return (
             <div>
-                one post with id = {this.props.id}
+              <textarea ref={c => this.text = c}>
+              </textarea>
+              <input ref={c => this.title = c} />
+              <button onClick={this.save.bind(this)}>Save</button>
             </div>
         )
     }
 }
 
-let PostPage = (props) => <Post id={props.match.params.id}/>
 
 class App extends Component {
   render() {
@@ -115,6 +242,7 @@ class App extends Component {
                 <Switch>
                     <Route path='/' component={FeedPage} exact />
                     <Route path='/post/:id' component={PostPage} />
+                    <Route path='/addPost' component={AddPostPage} exact />
                 </Switch>
             </Router>
         </Provider>