Browse Source

add draft feature

pull/1/head
wes 8 years ago
parent
commit
b25f10d506
  1. 13
      blog_test.service
  2. 14
      fabfile.py
  3. 17
      src/posts.py
  4. 2
      src/scripts/about.tag
  5. 36
      src/scripts/app.tag
  6. 15
      src/scripts/browse.tag
  7. 15
      src/scripts/categoryfilter.tag
  8. 17
      src/scripts/editor.tag
  9. 2
      src/scripts/links.tag
  10. 34
      src/styles/riotblog.scss
  11. 3
      src/templates/write.html
  12. 14
      src/website.py

13
blog_test.service

@ -0,0 +1,13 @@
[Unit]
Description=My Blargh
After=network.target
[Service]
User=http
Group=http
WorkingDirectory=/srv/http/riotblog
ExecStart=/usr/bin/uwsgi --single-interpreter --ini /srv/http/riotblog/blog.ini
Environment="RIOTBLOG_SETTINGS=/srv/http/riotblog/riotblog_local.cfg"
[Install]
WantedBy=multi.user.target

14
fabfile.py

@ -38,6 +38,7 @@ def copyFiles():
local("cp ./src/*py ./build/") local("cp ./src/*py ./build/")
local("cp *.cfg ./build/") local("cp *.cfg ./build/")
local("cp ./src/styles/*.css ./build/styles/") local("cp ./src/styles/*.css ./build/styles/")
local("cp ./src/images/*png ./build/images/")
local("uglifycss ./build/styles/*css > ./build/styles/primop.min.css") local("uglifycss ./build/styles/*css > ./build/styles/primop.min.css")
local("cp -r ./src/templates ./build/templates") local("cp -r ./src/templates ./build/templates")
@ -48,8 +49,11 @@ def upload():
@task @task
def serveUp(): def serveUp():
sudo("rm -rf /srv/http/riotblog_static")
sudo("rm -fr /srv/http/riotblog") sudo("rm -fr /srv/http/riotblog")
sudo("cp -r /home/wes/build /srv/http/riotblog") sudo("mkdir -p /srv/http/riotblog_static")
sudo("cp -r /home/wes/build/ /srv/http/riotblog/")
sudo("cp -r /home/wes/build/{styles,scripts,images} /srv/http/riotblog_static")
sudo("cp /home/wes/build/blog.service /etc/systemd/system/blog.service") sudo("cp /home/wes/build/blog.service /etc/systemd/system/blog.service")
sudo("systemctl daemon-reload") sudo("systemctl daemon-reload")
sudo("systemctl enable blog.service") sudo("systemctl enable blog.service")
@ -59,7 +63,7 @@ def serveUp():
@task(default=True) @task(default=True)
def build(): def build():
local("rm -rf ./build") local("rm -rf ./build")
local("mkdir -p build/{scripts,styles}") local("mkdir -p build/{scripts,styles,images}")
buildScss() buildScss()
buildJS() buildJS()
copyFiles() copyFiles()
@ -69,7 +73,7 @@ def build():
@task @task
def update(): def update():
local("mkdir -p build/{scripts,styles}") local("mkdir -p build/{scripts,styles,images}")
buildScss() buildScss()
buildJS() buildJS()
copyFiles() copyFiles()
@ -79,7 +83,7 @@ def update():
@task @task
def locbuild(): def locbuild():
local("rm -rf ./build") local("rm -rf ./build")
local("mkdir -p build/{scripts,styles}") local("mkdir -p build/{scripts,styles,images}")
local("cp requirements.txt ./build/requirements.txt") local("cp requirements.txt ./build/requirements.txt")
buildLocalVenv() buildLocalVenv()
buildScss() buildScss()
@ -88,7 +92,7 @@ def locbuild():
local("sudo rm -fr /srv/http/riotblog") local("sudo rm -fr /srv/http/riotblog")
local("sudo mkdir -p /srv/http/riotblog") local("sudo mkdir -p /srv/http/riotblog")
local("sudo cp -r ./build/* /srv/http/riotblog/") local("sudo cp -r ./build/* /srv/http/riotblog/")
local("sudo cp /home/wes/primop.me/blog.service /etc/systemd/system/blog.service") local("sudo cp /home/wes/primop.me/blog_test.service /etc/systemd/system/blog.service")
local("sudo systemctl daemon-reload") local("sudo systemctl daemon-reload")
local("sudo systemctl enable blog.service") local("sudo systemctl enable blog.service")
local("sudo systemctl restart blog.service") local("sudo systemctl restart blog.service")

17
src/posts.py

@ -19,7 +19,7 @@ def get_mistune():
markdown = LocalProxy(get_mistune) markdown = LocalProxy(get_mistune)
class Posts: class Posts:
def __init__(self, user, password, host=None, port=None): def __init__(self, user, password, name, host=None, port=None):
if host is None: if host is None:
host = "localhost" host = "localhost"
if port is None: if port is None:
@ -29,11 +29,11 @@ class Posts:
self.client.credentials = (user, password) self.client.credentials = (user, password)
self.db = self.client["blog"] self.db = self.client[name]
self.iterpost = self.postIterator("blogPosts/blog-posts") self.iterpost = self.postIterator("blogPosts/blog-posts")
def savepost(self, title="", content="", author="", categories=[], _id=False): def savepost(self, title="", content="", author="", categories=[], _id=False, draft=True):
if _id: if _id:
doc = self.db[_id] doc = self.db[_id]
doc["title"] = title doc["title"] = title
@ -41,20 +41,25 @@ class Posts:
doc["author"] = author doc["author"] = author
doc["categories"] = categories doc["categories"] = categories
doc["_id"] = _id doc["_id"] = _id
doc["draft"] = draft
else: else:
doc = { doc = {
"title" : title, "title" : title,
"content" : content, "content" : content,
"author" : author, "author" : author,
"categories" : categories, "categories" : categories,
"type" : "post" "type" : "post",
"draft" : draft
} }
print("post was saved %s" % doc) print("post was saved %s" % doc)
return jsonify(self.db.save(doc)) return jsonify(self.db.save(doc))
def getpost(self, _id, json=True, convert=True): def getpost(self, _id, json=True, convert=True, unpublished=False):
if unpublished:
results = self.db.iterview("blogPosts/unpublished", 1, include_docs=True, startkey=_id)
else:
results = self.db.iterview("blogPosts/blog-posts", 1, include_docs=True, startkey=_id) results = self.db.iterview("blogPosts/blog-posts", 1, include_docs=True, startkey=_id)
post = [result.doc for result in results][0] post = [result.doc for result in results][0]
@ -105,7 +110,7 @@ class Posts:
return inner return inner
def allposts(self): def allposts(self):
result = self.db.iterview("blogPosts/blog-posts", 10, include_docs=True) result = self.db.iterview("blogPosts/unpublished", 10, include_docs=True)
posts = [] posts = []
for item in result: for item in result:

2
src/scripts/about.tag

@ -7,7 +7,7 @@
I'm a full stack application developer who builds web and mobile apps. I am a huge fan of functional programming, compilers, and solving problems creatively and efficiently. I enjoy helping other people learn more, and I am constantly learning as well. This blog covers my thoughts on everything from computer science, psychology, philosophy, economics, and anything else I'm currently interested in. I'm a full stack application developer who builds web and mobile apps. I am a huge fan of functional programming, compilers, and solving problems creatively and efficiently. I enjoy helping other people learn more, and I am constantly learning as well. This blog covers my thoughts on everything from computer science, psychology, philosophy, economics, and anything else I'm currently interested in.
</p> </p>
<p class="post-content"> <p class="post-content">
Feel free to shoot me an <a href="mailto:wjak56@gmail.com">email</a> if you want to chat or check out my <a target="_blank" href="https://stackoverflow.com/story/weskerfoot">resume</a> Feel free to shoot me an <a href="mailto:wjak56@gmail.com">email</a> if you want to chat or check out my <a target="_blank" href="https://stackoverflow.com/users/903589/wes">profile on stack overflow</a>
</p> </p>
</div> </div>
<script> <script>

36
src/scripts/app.tag

@ -32,7 +32,9 @@
style={{"margin-top" : page !== "posts" ? "15px" : "5px"}} style={{"margin-top" : page !== "posts" ? "15px" : "5px"}}
class="text-center nav navbar centered navbar-section" class="text-center nav navbar centered navbar-section"
> >
<h3 class="blog-title">{ currentPage }</h3> <h3 class="blog-title">
{ currentPage }
</h3>
</section> </section>
</div> </div>
<div class="col-2"> <div class="col-2">
@ -125,6 +127,36 @@
> >
</browse> </browse>
</div> </div>
<div
class="footer"
if={false}
>
<div class="container">
<div class="columns">
<div class="col-2">
<a
class="mailme"
href="mailto:wjak56@gmail.com"
>
<i class="fa fa-envelope-o" aria-hidden="true"></i>
</a>
</div>
<div class="col-8">
<div class="license">
Content Licensed under CC
<a target="_blank" href="https://creativecommons.org/licenses/by-nc-nd/4.0/">
<img
class="cc-license"
src="/images/88x31.png"
>
</img>
</a>
</div>
</div>
<div class="col-2"></div>
</div>
</div>
</div>
</div> </div>
<script> <script>
import './sidebar.tag'; import './sidebar.tag';
@ -209,7 +241,7 @@ menuOff(ev) {
} }
self.titles = { self.titles = {
"browse" : "Wes Kerfoot", "browse" : "Wes's Blog",
"projects" : "Software", "projects" : "Software",
"links" : "Links", "links" : "Links",
"about" : "About Me" "about" : "About Me"

15
src/scripts/browse.tag

@ -34,7 +34,8 @@
<div class="col-4"></div> <div class="col-4"></div>
</div> </div>
<div class="columns"> <div class="columns">
<div class="col-12"> <div class="col-12"
>
<div <div
data-is="categorymodal" data-is="categorymodal"
> >
@ -49,13 +50,15 @@
</div> </div>
</div> </div>
</div> </div>
<div class="columns"> <div
class="columns"
>
<div <div
style={sidebarStyle} style={sidebarStyle}
class="column hide-xs hide-sm hide-md col-2" class="column hide-xs hide-sm hide-md col-2 shadow"
> >
<categoryfilter <categoryfilter
name="Post Categories" name="Categories"
category={opts.state.category_filter} category={opts.state.category_filter}
items={opts.state.categories} items={opts.state.categories}
onfilter={filterCategories} onfilter={filterCategories}
@ -140,7 +143,9 @@ self.navStyle = {
}; };
self.sidebarStyle = { self.sidebarStyle = {
"margin-right" : "-40px" "margin-right" : "-40px",
"min-height": "500px",
"max-height" : "500px"
}; };
self.filterCategories = (category) => { self.filterCategories = (category) => {

15
src/scripts/categoryfilter.tag

@ -1,6 +1,17 @@
<categoryfilter> <categoryfilter>
<div class="categorybar"> <div
<h4 if={opts.name}> class="categorybar"
style={
{
"min-height": "500px",
"max-height" : "500px"
}
}
>
<h4
if={opts.name}
style={{"text-align" : "center"}}
>
{ opts.name } { opts.name }
</h4> </h4>

17
src/scripts/editor.tag

@ -36,6 +36,17 @@
<span>tags</span><input ref="tags"></input> <span>tags</span><input ref="tags"></input>
<span>Editing post {!this.isNewPost ? this._id : ""}</span> <span>Editing post {!this.isNewPost ? this._id : ""}</span>
<p> <p>
<div class="form-group">
<label class="form-switch">
<input
type="checkbox"
ref="draft"
name="draft"
value="true"
/>
<i class="form-icon"></i> Draft
</label>
</div>
<button <button
class="btn btn-primary branded" class="btn btn-primary branded"
onclick={deletePost(!this.isNewPost ? this._id : false)} onclick={deletePost(!this.isNewPost ? this._id : false)}
@ -170,12 +181,14 @@ self.newPost = () => {
self.submit = () => { self.submit = () => {
self.update({"loading" : true}); self.update({"loading" : true});
console.log(this.refs.draft.checked);
var post = { var post = {
"title" : this.refs.title.value, "title" : this.refs.title.value,
"author" : this.refs.author.value, "author" : this.refs.author.value,
"content" : this.refs.textarea.value, "content" : this.refs.textarea.value,
"tags" : this.refs.tags.value, "tags" : this.refs.tags.value,
"csrf_token" : this.opts.csrf_token "csrf_token" : this.opts.csrf_token,
"draft" : this.refs.draft.checked ? "true" : "false"
}; };
if (this._id) { if (this._id) {
@ -227,11 +240,13 @@ self.loadPost = (_id) => {
self.update({"loading" : true}); self.update({"loading" : true});
axios.get(`/blog/getrawpost/${_id.slice(-8)}`) axios.get(`/blog/getrawpost/${_id.slice(-8)}`)
.then(function(resp) { .then(function(resp) {
console.log(resp);
self.update({"loading" : false}); self.update({"loading" : false});
self.refs.textarea.value = resp.data.content; self.refs.textarea.value = resp.data.content;
self.refs.title.value = resp.data.title; self.refs.title.value = resp.data.title;
self.refs.author.value = resp.data.author; self.refs.author.value = resp.data.author;
self.refs.tags.value = resp.data.categories; self.refs.tags.value = resp.data.categories;
self.refs.draft.checked = resp.data.draft
self._id = resp.data._id; self._id = resp.data._id;
self.focused = true; self.focused = true;
self.isNewPost = false; self.isNewPost = false;

2
src/scripts/links.tag

@ -3,7 +3,7 @@
<div class="columns"> <div class="columns">
<div class="column col-12"> <div class="column col-12">
<h4 class="text-center"> <h4 class="text-center">
Interesting Links Stuff I Find Interesting
</h4> </h4>
</div> </div>
</div> </div>

34
src/styles/riotblog.scss

@ -16,6 +16,22 @@ $navbarHeight: 100px;
box-shadow: 1px 4px 20px -8px rgba(0,0,0,0.2); box-shadow: 1px 4px 20px -8px rgba(0,0,0,0.2);
} }
.license {
margin: auto;
}
.mailme {
float: left;
}
.cc-license {
height: 20px;
width: 70px;
padding-left: 10px;
padding-right: 10px;
margin-bottom: -5px;
}
.gradient { .gradient {
-webkit-background-size: cover !important; -webkit-background-size: cover !important;
-moz-background-size: cover !important; -moz-background-size: cover !important;
@ -50,10 +66,10 @@ html {
font-weight: 400; font-weight: 400;
color: black; color: black;
@media (max-width: 600px) { @media (max-width: 600px) {
font-size: 1.8em; font-size: 1.6em;
} }
@media (max-width: 530px) { @media (max-width: 530px) {
font-size: 1.5em; font-size: 1.3em;
} }
} }
@ -70,6 +86,17 @@ html {
margin: auto; margin: auto;
} }
.footer {
@extend .shadow;
position: absolute;
right: 0;
bottom: 0;
left: 0;
padding: 1rem;
background-color: #efefef;
text-align: center;
}
.twitter-share-button-rendered { .twitter-share-button-rendered {
font-size: 1.5em; font-size: 1.5em;
} }
@ -129,8 +156,7 @@ html {
.categorybar { .categorybar {
max-width: 350px; max-width: 350px;
float: right; margin: auto;
margin-right: 0px !important;
padding: 0px 0px 0px 0px !important; padding: 0px 0px 0px 0px !important;
} }

3
src/templates/write.html

@ -15,9 +15,6 @@
{% endblock %} {% endblock %}
<footer class="footer">
</footer>
{% block styles %} {% block styles %}
<link rel="stylesheet" href="/styles/spectre.min.css"> <link rel="stylesheet" href="/styles/spectre.min.css">

14
src/website.py

@ -27,7 +27,7 @@ page_titles = {
"about" : "About Me", "about" : "About Me",
"projects" : "Software", "projects" : "Software",
"links" : "Links", "links" : "Links",
"browse" : "Wes Kerfoot" "browse" : "Wes's Blog"
} }
def cacheit(key, thunk): def cacheit(key, thunk):
@ -47,7 +47,8 @@ def get_posts():
posts = getattr(g, "posts", None) posts = getattr(g, "posts", None)
if posts is None: if posts is None:
posts = g._posts = Posts(app.config["COUCHDB_USER"], posts = g._posts = Posts(app.config["COUCHDB_USER"],
app.config["COUCHDB_PASSWORD"]) app.config["COUCHDB_PASSWORD"],
app.config["COUCHDB_NAME"])
return posts return posts
def get_initial(): def get_initial():
@ -188,10 +189,11 @@ def NeverWhere(configfile=None):
def getpost(_id): def getpost(_id):
return posts.getpost(_id) return posts.getpost(_id)
# XXX should use unpublished
@cache.cached(timeout=50) @cache.cached(timeout=50)
@app.route("/blog/getrawpost/<_id>") @app.route("/blog/getrawpost/<_id>")
def getrawpost(_id): def getrawpost(_id):
return posts.getpost(_id, convert=False) return posts.getpost(_id, convert=False, unpublished=True)
# get the first post of a given category # get the first post of a given category
@cache.cached(timeout=50) @cache.cached(timeout=50)
@ -199,7 +201,7 @@ def NeverWhere(configfile=None):
def bycategory(category): def bycategory(category):
return posts.getbycategory(category) return posts.getbycategory(category)
# get the id of every post # XXX get the id of every post
@app.route("/blog/allposts") @app.route("/blog/allposts")
def allposts(): def allposts():
return posts.allposts() return posts.allposts()
@ -230,6 +232,7 @@ def NeverWhere(configfile=None):
author = request.form.get("author", "no author") author = request.form.get("author", "no author")
title = request.form.get("title", "no title") title = request.form.get("title", "no title")
content = request.form.get("content", "no content") content = request.form.get("content", "no content")
draft = loads(request.form.get("draft", "false"))
tags = [t for t in request.form.get("tags", "programming").split(",") if t] tags = [t for t in request.form.get("tags", "programming").split(",") if t]
postid = request.form.get("_id", False) postid = request.form.get("_id", False)
@ -238,7 +241,8 @@ def NeverWhere(configfile=None):
"title" : title, "title" : title,
"content" : content, "content" : content,
"categories" : tags, "categories" : tags,
"_id" : postid "_id" : postid,
"draft" : draft
} }
memcache.clear() memcache.clear()

Loading…
Cancel
Save