Compare commits

..

No commits in common. "138f224fd09d464df629e23591b918b544c7c654" and "617f6b890e12a36e075c90a9b6443ff86bd649c7" have entirely different histories.

16 changed files with 1945 additions and 272 deletions

1907
README.md

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

@ -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",

View File

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

2
run.sh
View File

@ -1,2 +0,0 @@
. env/bin/activate
yarn start

View File

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

View File

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

View File

@ -1,4 +1,3 @@
export * from './addpost';
export * from './listposts';
export * from './showpost';
export * from './headermenu';

View File

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

View File

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

View File

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

View File

@ -33,7 +33,6 @@
"no-bitwise": true,
"no-console": [
true,
"log",
"error",
"debug",
"info",

View File

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