Compare commits
No commits in common. "138f224fd09d464df629e23591b918b544c7c654" and "617f6b890e12a36e075c90a9b6443ff86bd649c7" have entirely different histories.
138f224fd0
...
617f6b890e
|
|
@ -24,8 +24,7 @@ class ProductionConfig(Config):
|
|||
DATABASE_URI = 'mysql://user@localhost/foo'
|
||||
|
||||
class DevelopmentConfig(Config):
|
||||
# SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'
|
||||
SQLALCHEMY_DATABASE_URI = 'sqlite:////tmp/typeset.db'
|
||||
SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'
|
||||
DEBUG = True
|
||||
|
||||
class TestingConfig(Config):
|
||||
|
|
|
|||
|
|
@ -5,20 +5,18 @@ Licence: GPLv3
|
|||
"""
|
||||
|
||||
from app import db
|
||||
from uuid import uuid4
|
||||
from datetime import datetime
|
||||
|
||||
class Post(db.Model):
|
||||
id = db.Column(db.String(32), primary_key=True)
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
title = db.Column(db.String(80))
|
||||
pub_date = db.Column(db.DateTime)
|
||||
|
||||
def __init__(self, title, pub_date=None):
|
||||
def __init__(self, title,paragraphs, pub_date=None):
|
||||
self.title = title
|
||||
if pub_date is None:
|
||||
pub_date = datetime.utcnow()
|
||||
self.pub_date = pub_date
|
||||
self.id = uuid4().hex
|
||||
self.paragraphs = paragraphs
|
||||
|
||||
def __repr__(self):
|
||||
return '<Post %r>' % self.title
|
||||
|
|
@ -26,8 +24,8 @@ class Post(db.Model):
|
|||
class Paragraph(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
body = db.Column(db.Text)
|
||||
post_id = db.Column(db.String(32), db.ForeignKey('post.id'))
|
||||
post = db.relationship('Post',backref=db.backref('paragraphs', lazy='dynamic'))
|
||||
post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
|
||||
db.relationship('Post',backref=db.backref('paragraphs', lazy='dynamic'))
|
||||
|
||||
def __init__(self, body,post_id):
|
||||
self.body = body
|
||||
|
|
@ -41,18 +39,12 @@ class Comment(db.Model):
|
|||
name = db.Column(db.String(50))
|
||||
message = db.Column(db.String(140))
|
||||
paragraph_id = db.Column(db.Integer, db.ForeignKey('paragraph.id'))
|
||||
post_id = db.Column(db.String(32), db.ForeignKey('post.id'))
|
||||
# pub_date = db.Column(db.DateTime)
|
||||
paragraph = db.relationship('Paragraph',backref=db.backref('comments', lazy='dynamic'))
|
||||
post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
|
||||
db.relationship('Paragraph',backref=db.backref('comments', lazy='dynamic'))
|
||||
|
||||
def __init__(self, name,message,paragraph_id,post_id, pub_date=None):
|
||||
def __init__(self, name,message):
|
||||
self.name = name
|
||||
self.message = message
|
||||
self.post_id = post_id
|
||||
self.paragraph_id = paragraph_id
|
||||
if pub_date is None:
|
||||
pub_date = datetime.utcnow()
|
||||
# self.pub_date = pub_date
|
||||
|
||||
def __repr__(self):
|
||||
return '<Comment %r>' % self.name
|
||||
|
|
|
|||
36
app/views.py
36
app/views.py
|
|
@ -6,8 +6,7 @@ Licence: GPLv3
|
|||
|
||||
from flask import request
|
||||
from flask_restless import APIManager
|
||||
from flask_restplus import Resource,Api
|
||||
import json
|
||||
from flask_restful import Resource,Api
|
||||
from app import app,db
|
||||
from models import Post,Paragraph,Comment
|
||||
|
||||
|
|
@ -15,9 +14,8 @@ from models import Post,Paragraph,Comment
|
|||
manager = APIManager(app, flask_sqlalchemy_db=db)
|
||||
# Create API endpoints, which will be available at /api/<tablename> by
|
||||
# default. Allowed HTTP methods can be specified as well.
|
||||
manager.create_api(Post, methods=['GET'],exclude_columns=['paragraphs'],results_per_page=5)
|
||||
manager.create_api(Post, methods=['GET'],results_per_page=None,collection_name='post_para')
|
||||
manager.create_api(Paragraph, methods=['GET'],results_per_page=None)
|
||||
manager.create_api(Post, methods=['GET'])
|
||||
manager.create_api(Paragraph, methods=['GET'])
|
||||
manager.create_api(Comment, methods=['GET','POST'])
|
||||
|
||||
restapi = Api(app)
|
||||
|
|
@ -27,32 +25,22 @@ restapi = Api(app)
|
|||
def index():
|
||||
return app.send_static_file('index.html')
|
||||
|
||||
@restapi.route('/api/post_misc')
|
||||
class PostMisc(Resource):
|
||||
class CreatePost(Resource):
|
||||
def post(self):
|
||||
try:
|
||||
post_data = json.loads(request.data)
|
||||
post_data = json.parse(request.data)
|
||||
title = post_data['title']
|
||||
content = post_data['content']
|
||||
p_e = Post(title)
|
||||
db.session.add(p_e)
|
||||
pgs = content.split('\n\n')
|
||||
for pg in pgs:
|
||||
pg_e = Paragraph(body=pg,post_id=p_e.id)
|
||||
db.session.add(pg_e)
|
||||
db.session.commit()
|
||||
return {'post_id':p_e.id}
|
||||
p = Post(title)
|
||||
pgs = content.split('\n')
|
||||
db.session.add(p)
|
||||
db.session.add(p)
|
||||
return {'post_id':'title'}
|
||||
except Exception as e:
|
||||
return restapi.abort(400,'Invalid data')
|
||||
return {'error':'invalid_post'}
|
||||
|
||||
# @app.route('/api/post_misc')
|
||||
# def get_post():
|
||||
# post_id = request.args.get('post_id')
|
||||
# print(post_id)
|
||||
# p_e = Post.query.get(post_id)
|
||||
# return {'paragraphs':p_e.paragraphs}
|
||||
|
||||
# restapi.add_resource(PostMisc,'/api/post_misc')
|
||||
restapi.add_resource(CreatePost,'/api/create_post')
|
||||
# @app.route('/api/create_post',methods=['POST'])
|
||||
# def create_post():
|
||||
# title = request.form.get('title',None);
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@
|
|||
## gcc, make, Python 2.5+, python-pip, virtualenv
|
||||
|
||||
## Instalation
|
||||
## Create a virtualenv, and activate this:
|
||||
## Create a virtualenv, and activate this:
|
||||
|
||||
virtualenv --python python2 env
|
||||
virtualenv env
|
||||
source env/bin/activate
|
||||
pip install -r requirements.txt
|
||||
yarn install
|
||||
python run.py
|
||||
|
||||
|
|
@ -9,7 +9,6 @@
|
|||
"@types/react-dom": "^15.5.2",
|
||||
"@types/react-router": "^4.0.14",
|
||||
"@types/react-router-dom": "^4.0.7",
|
||||
"lodash": "^4.17.4",
|
||||
"react": "^15.6.1",
|
||||
"react-dom": "^15.6.1",
|
||||
"react-router": "^4.1.2",
|
||||
|
|
@ -20,7 +19,6 @@
|
|||
"yarn": "^0.27.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash": "^4.14.72",
|
||||
"app-root-path": "^2.0.1",
|
||||
"autoprefixer": "7.1.0",
|
||||
"case-sensitive-paths-webpack-plugin": "2.0.0",
|
||||
|
|
|
|||
|
|
@ -1,20 +1,15 @@
|
|||
aniso8601==1.2.1
|
||||
click==6.7
|
||||
Flask==0.12.2
|
||||
Flask-FlatPages==0.6
|
||||
Flask-Restless==0.17.0
|
||||
flask-restplus==0.10.1
|
||||
Flask-SQLAlchemy==2.2
|
||||
functools32==3.2.3.post2
|
||||
itsdangerous==0.24
|
||||
Jinja2==2.9.6
|
||||
jsonschema==2.6.0
|
||||
Markdown==2.6.8
|
||||
MarkupSafe==1.0
|
||||
mimerender==0.6.0
|
||||
python-dateutil==2.6.1
|
||||
python-mimeparse==1.6.0
|
||||
pytz==2017.2
|
||||
PyYAML==3.12
|
||||
six==1.10.0
|
||||
SQLAlchemy==1.1.13
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ export class AddPost extends React.Component<any, any> {
|
|||
public render() {
|
||||
let submitHandler = (e: any, d: any) => {
|
||||
let postContent = JSON.stringify(this.state);
|
||||
// console.log('posting : ', postContent);
|
||||
fetch('/api/post_misc', {
|
||||
console.log('posting : ', postContent);
|
||||
fetch('/api/create_post', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
|
|
@ -20,12 +20,12 @@ export class AddPost extends React.Component<any, any> {
|
|||
body: postContent,
|
||||
})
|
||||
.then((response) => {
|
||||
// if (response.status === 200) {
|
||||
// // console.log('submitted successfully');
|
||||
// }
|
||||
if (response.status === 200) {
|
||||
console.log('submitted successfully');
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
// console.log('some error occurred');
|
||||
console.log('some error occurred');
|
||||
});
|
||||
};
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@ import { Link } from 'react-router-dom';
|
|||
export class HeaderMenu extends React.Component<any, any> {
|
||||
state = { activeItem: 'listpost' };
|
||||
|
||||
handleItemClick = (e: any, d: any) => {
|
||||
this.setState({ activeItem: d.name });
|
||||
}
|
||||
handleItemClick = (e: any, d: any) => this.setState({ activeItem: d.name });
|
||||
|
||||
render() {
|
||||
let { activeItem } = this.state;
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
export * from './addpost';
|
||||
export * from './listposts';
|
||||
export * from './showpost';
|
||||
export * from './headermenu';
|
||||
|
|
|
|||
|
|
@ -1,70 +1,10 @@
|
|||
import * as React from 'react';
|
||||
import { Menu, List } from 'semantic-ui-react';
|
||||
import { HeaderMenu } from './headermenu';
|
||||
import { Link } from 'react-router-dom';
|
||||
import * as _ from 'lodash';
|
||||
// import { Comment } from 'semantic-ui-react';
|
||||
|
||||
export const PostLinks: React.StatelessComponent<any> = (props) => {
|
||||
let postItems = props.posts.map((o: any, i: number) => (
|
||||
<List.Item key={i}>
|
||||
<List.Icon name="book" size="large" verticalAlign="middle" />
|
||||
<List.Content>
|
||||
<List.Header as={Link} to={`/showpost/${o.id}`}>{o.title}</List.Header>
|
||||
<List.Description as={Link} to={`/showpost/${o.id}`}>published at {o.pub_date}</List.Description>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
));
|
||||
return (
|
||||
<List divided={true} relaxed={true}>
|
||||
{postItems}
|
||||
</List>
|
||||
);
|
||||
};
|
||||
|
||||
export class ListPosts extends React.Component<any, any> {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
let pageContent = { objects: [], page: 1, total_pages: 1 };
|
||||
this.state = { pageNo: 1, pageContent };
|
||||
}
|
||||
componentDidMount() {
|
||||
this.getPage(1);
|
||||
}
|
||||
public render() {
|
||||
let handleItemClick = (e: any, d: any) => {
|
||||
this.getPage(_.toInteger(d.name));
|
||||
};
|
||||
let { page, total_pages } = this.state.pageContent;
|
||||
let items = _.times(total_pages, (n: number) => {
|
||||
return (
|
||||
<Menu.Item
|
||||
key={n}
|
||||
name={(n + 1).toString()}
|
||||
active={page === n + 1}
|
||||
onClick={handleItemClick}
|
||||
/>
|
||||
);
|
||||
});
|
||||
let { objects } = this.state.pageContent;
|
||||
export class ListPost extends React.Component<any, any> {
|
||||
render() {
|
||||
return (
|
||||
<HeaderMenu>
|
||||
<PostLinks posts={objects} />
|
||||
<Menu pagination={true}>
|
||||
{items}
|
||||
</Menu>
|
||||
</HeaderMenu>
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
getPage(pageNo: number) {
|
||||
fetch('/api/post?page=' + pageNo.toString())
|
||||
.then((response) => response.text())
|
||||
.then((responseText) => {
|
||||
let pageContent = JSON.parse(responseText);
|
||||
this.setState({ pageContent });
|
||||
})
|
||||
.catch((err) => {
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,127 +0,0 @@
|
|||
import * as React from 'react';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { Segment, Header, Comment, Form, Button, Container, Icon } from 'semantic-ui-react';
|
||||
import { HeaderMenu } from './headermenu';
|
||||
|
||||
export class ShowPara extends React.Component<any, any> {
|
||||
state = { commentName: '', commentMessage: '', comments: [] };
|
||||
// constructor(props:any){
|
||||
// super(props);
|
||||
// }
|
||||
componentDidMount() {
|
||||
this.getComments();
|
||||
}
|
||||
public render() {
|
||||
let cont = this.props.para.body;
|
||||
let handleComment = () => {
|
||||
let name = this.state.commentName;
|
||||
let message = this.state.commentMessage;
|
||||
let pgId = this.props.para.id;
|
||||
let pId = this.props.para.post_id;
|
||||
let pc = { name, message, paragraph_id: pgId, post_id: pId };
|
||||
let postContent = JSON.stringify(pc);
|
||||
fetch(`/api/comment`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: postContent,
|
||||
})
|
||||
.then((response) => {
|
||||
this.getComments();
|
||||
})
|
||||
.catch((err) => {
|
||||
// console.log('some error occurred');
|
||||
});
|
||||
};
|
||||
let handleMessage = (name: boolean) => {
|
||||
let field = name ? 'commentName' : 'commentMessage';
|
||||
return (e: any, d: any) => {
|
||||
this.setState({ [field]: d.value });
|
||||
};
|
||||
};
|
||||
let comments = this.state.comments.map((c: any, i: number) => (
|
||||
<Comment key={i}>
|
||||
<Icon name="user" />
|
||||
<Comment.Content>
|
||||
<Comment.Author>{c.name}</Comment.Author>
|
||||
<Comment.Text>{c.name}</Comment.Text>
|
||||
</Comment.Content>
|
||||
</Comment>
|
||||
));
|
||||
return (
|
||||
<Container>
|
||||
<Segment>{cont}</Segment>
|
||||
<Comment.Group size="mini">
|
||||
{comments}
|
||||
<Form reply={true} onSubmit={handleComment}>
|
||||
<Form.Group inline={true}>
|
||||
<Form.Input width={2} placeholder="Name" onChange={handleMessage(true)} />
|
||||
<Form.Input width={10} placeholder="Message" onChange={handleMessage(false)} />
|
||||
<Button
|
||||
size="mini"
|
||||
width={2}
|
||||
content="Add Comment"
|
||||
labelPosition="left"
|
||||
icon="edit"
|
||||
primary={true}
|
||||
/>
|
||||
</Form.Group>
|
||||
</Form>
|
||||
</Comment.Group>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
getComments() {
|
||||
fetch(`/api/paragraph/${this.props.para.id}`)
|
||||
.then((response) => response.text())
|
||||
.then((txt) => {
|
||||
let { comments } = JSON.parse(txt);
|
||||
this.setState({ comments });
|
||||
})
|
||||
.catch((err) => {
|
||||
// console.log('some error occurred');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class ShowPostR extends React.Component<any, any> {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
let postId = props.match.params.postId;
|
||||
let emptyPost = { paragraphs: [], title: '' };
|
||||
this.state = { postId, postData: emptyPost };
|
||||
}
|
||||
componentDidMount() {
|
||||
this.getParagraphs();
|
||||
}
|
||||
public render() {
|
||||
let pd = this.state.postData;
|
||||
let paraList = pd.paragraphs;
|
||||
let paraL = (o: any, i: number) => (
|
||||
<ShowPara key={i} para={o} />
|
||||
);
|
||||
let paras = paraList.map(paraL);
|
||||
return (
|
||||
<HeaderMenu>
|
||||
<Header size="medium">{pd.title}</Header>
|
||||
{paras}
|
||||
</HeaderMenu>
|
||||
);
|
||||
}
|
||||
getParagraphs() {
|
||||
fetch(`/api/post_para/${this.state.postId}`)
|
||||
.then((response) => response.text())
|
||||
.then((txt) => {
|
||||
let postData = JSON.parse(txt);
|
||||
this.setState({ postData });
|
||||
})
|
||||
.catch((err) => {
|
||||
// console.log('some error occurred');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const ShowPost = withRouter(ShowPostR);
|
||||
|
|
@ -1,16 +1,15 @@
|
|||
import * as React from 'react';
|
||||
import { Route, HashRouter } from 'react-router-dom';
|
||||
// import { App } from './app';
|
||||
import { AddPost, ListPosts, ShowPost } from './components';
|
||||
import { App } from './app';
|
||||
import { AddPost } from './components';
|
||||
|
||||
export const AppRouter: React.StatelessComponent<{}> = () => {
|
||||
return (
|
||||
<HashRouter hashType="slash">
|
||||
<HashRouter>
|
||||
<div >
|
||||
<Route exact={true} path="/" component={ListPosts} />
|
||||
<Route exact={true} path="/" component={App} />
|
||||
<Route path="/addpost" component={AddPost} />
|
||||
<Route path="/listposts" component={ListPosts} />
|
||||
<Route path="/showpost/:postId" component={ShowPost} />
|
||||
<Route path="/listposts" component={AddPost} />
|
||||
</div>
|
||||
</HashRouter>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
"no-bitwise": true,
|
||||
"no-console": [
|
||||
true,
|
||||
"log",
|
||||
"error",
|
||||
"debug",
|
||||
"info",
|
||||
|
|
|
|||
|
|
@ -17,10 +17,6 @@
|
|||
version "20.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-20.0.6.tgz#7e0ba76ddfacb42ee9bb0d8833e5208cf0680431"
|
||||
|
||||
"@types/lodash@^4.14.72":
|
||||
version "4.14.72"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.72.tgz#f090cf6eb1fee1647a0efa1ebe18b0b78ed551c6"
|
||||
|
||||
"@types/node@*", "@types/node@^8.0.20":
|
||||
version "8.0.20"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.20.tgz#65c7375255c24b184c215a5d0b63247c32f01c91"
|
||||
|
|
@ -3072,7 +3068,7 @@ lodash.uniq@^4.5.0:
|
|||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
|
||||
"lodash@>=3.5 <5", lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0:
|
||||
"lodash@>=3.5 <5", lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.2.0, lodash@^4.3.0:
|
||||
version "4.17.4"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue