Permalink
Browse files

Pretty much everything works now, see TODO

  • Loading branch information...
1 parent ee641ba commit 9c776fb027ccb1ec78ca7118f6aa44ffb5930540 @pflarr committed Oct 2, 2011
View
8 TODO
@@ -0,0 +1,8 @@
+Add edit history page.
+Fix internal links
+Add a basic theme.css
+Add a default logo
+Add a default site.css
+Enforce user permissions
+
+Make it pretty.
View
@@ -31,18 +31,21 @@ def main(global_config, **settings):
config.add_view('basic_site.views.home',
route_name='home',
renderer='basic_site:templates/main.mako')
- config.add_route('post','post/{id:\d+}')
+ config.add_route('post',r'post/{id:\d+(\.\d+)?}')
config.add_view('basic_site.views.post', route_name='post',
renderer='basic_site:templates/post.mako')
- config.add_route('page', 'page/{name}')
+ config.add_route('page',r'page/{name:[a-z0-9_ -]+(\.\d+)?}')
config.add_view('basic_site.views.page', route_name='page',
renderer='basic_site:templates/page.mako')
- config.add_route('add', '{mode:add}/{ptype:(page|post)}')
- config.add_route('edit', '{mode:edit}/{ptype:(page|post)}/{id}')
+ config.add_route('add', 'add/{ptype:(page|post)}')
+ config.add_route('edit', 'edit/{ptype:(page|post)}/{id}')
config.add_view('basic_site.views.edit', route_name='add',
renderer='basic_site:templates/edit.mako')
config.add_view('basic_site.views.edit', route_name='edit',
renderer='basic_site:templates/edit.mako')
+ config.add_route('restore', 'restore/{ptype:(page|post)}/'
+ '{id:[a-z0-9_ -]+)/{skip:\d+}')
+ config.add_view('basic_site.views.restore', route_name='restore')
config.add_route('users', 'users')
config.add_view('basic_site.views.users', route_name='users',
renderer='basic_site:templates/users.mako')
View
@@ -87,20 +87,23 @@ def __init__(self, creator, title, content, sticky=False, created=None):
self.title = title[:30]
self.content = content
- def edit(self, title, content, sticky, user):
- """Edit this post, and record the change in the history."""
- session = DBSession()
+ def edit(self, user, title, content, sticky, created=None):
+ """Edit this post, and return the history row (will need to be
+ added to a session.)"""
hist = Post_History(user, self)
self.title = title[:30]
self.content = content
self.sticky = sticky
- session.add(hist)
+ if created is None:
+ self.created = datetime.datetime.utcnow()
+ else:
+ self.created = created
+ return hist
def render(self):
doc = Parser(self.content).parse()
return BS_Emitter(doc).emit()
-
class Post_History(Base):
__tablename__ = 'post_history'
hist_id = Column(Integer(), primary_key=True)
@@ -114,24 +117,29 @@ class Post_History(Base):
content = Column(String(), nullable=False)
def __init__(self, editor_uid, post):
- for col in post.__table__.c:
- self.__table__[col] = post.__table__.c[col]
+ self.id = post.id
+ self.title = post.title
+ self.created = post.created
+ self.creator = post.creator
+ self.sticky = post.sticky
+ self.content = post.content
self.changed_by = editor_uid
self.changed_on = datetime.datetime.utcnow()
def restore(self, user):
- """Restore this history item's content."""
- session = DBSession()
- try:
- post = session.query(Post)\
- .filter(Post.id == self.id)\
- .one()
- post.edit(user, self.title, self.content)
- except sqlalchemy.orm.exc.NoResultFound:
- # Recreate it if it doesn't still exist
- post = Post(user, self.title, self.content, self.created)
- session.add(page)
- session.flush()
+ """Restore this history item's content. Returns an item to add to
+ the db/session."""
+ if current:
+ return current.edit(user, self.title, self.content, self.sticky,
+ created=self.created)
+ else:
+ return Post(user, self.title, self.content, self.sticky,
+ self.created)
+
+ def render(self):
+ doc = Parser(self.content).parse()
+ return BS_Emitter(doc).emit()
+
class Page(Base):
__tablename__ = 'pages'
@@ -153,14 +161,17 @@ def __init__(self, creator, name, content, created=None):
self.creator = creator
self.content = content
- def edit(self, name, content, user):
- """Edit this post, and record the change in the history."""
- session = DBSession()
+ def edit(self, user, name, content, created=None):
+ """Edit this page, and return the history table entry."""
hist = Page_History(user, self)
self.name = name
self.content = content
- session.add(hist)
-
+ if created:
+ self.created = datetime.datetime.utcnow()
+ else:
+ self.created = created
+ return hist
+
def render(self):
doc = Parser(self.content).parse()
return BS_Emitter(doc).emit()
@@ -177,24 +188,26 @@ class Page_History(Base):
content = Column(String(), nullable=False)
def __init__(self, editor_uid, page):
- for col in page.__table__.c:
- self.__table__[col] = page.__table__.c[col]
+ self.id = page.id
+ self.name = page.name
+ self.created = page.created
+ self.creator = page.creator
+ self.content = page.content
self.changed_by = editor_uid
self.changed_on = datetime.datetime.utcnow()
- def restore(self, user):
- """Restore this history item's content."""
- session = DBSession()
- try:
- page = session.query(Page)\
- .filter(Page.id == self.id)\
- .one()
- page.edit(self.content, user)
- except sqlalchemy.orm.exc.NoResultFound:
- # Recreate it if it doesn't still exist
- page = Page(user, self.name, self.content, self.created)
- session.add(page)
- session.flush()
+ def restore(self, user, current):
+ """Restore this history item's content, returns a list of rows to
+ add to the session."""
+
+ if current:
+ return current.edit(user, self.name, self.content, self.created)
+ else:
+ return Page(user, self.name, self.content, self.created)
+
+ def render(self):
+ doc = Parser(self.content).parse()
+ return BS_Emitter(doc).emit()
class File(Base):
__tablename__ = 'files';
@@ -208,3 +221,14 @@ def __init__(self, name, submitter):
self.name = name
self.submitter = submitter
self.changed = datetime.datetime.now()
+
+if __name__ == '__main__':
+ from sqlalchemy import engine_from_config
+ from ConfigParser import SafeConfigParser
+ import sys
+ p = SafeConfigParser()
+ assert p.read(sys.argv[1]), "Bad path to config (arg1): %s" % sys.argv[1]
+
+ engine = engine_from_config(p._sections['app:basic_site'])
+ initialize_sql(engine)
+ engine = engine_from_config
@@ -19,6 +19,7 @@ div.login button {
}
div.head div.message {
+ font-weight: bold;
float: right;
clear: right;
}
@@ -51,9 +52,13 @@ div.main {
}
div.content {
- position: relative;
- left: 210px;
+ margin-left: 210px;
padding: 10px;
border: 1px solid red;
}
+div.post {
+ margin-bottom: 5px;
+ border: 1px solid blue;
+}
+
Binary file not shown.
Deleted file not rendered
Deleted file not rendered
@@ -1,8 +0,0 @@
-* html img,
-* html .png{position:relative;behavior:expression((this.runtimeStyle.behavior="none")&&(this.pngSet?this.pngSet=true:(this.nodeName == "IMG" && this.src.toLowerCase().indexOf('.png')>-1?(this.runtimeStyle.backgroundImage = "none",
-this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.src + "',sizingMethod='image')",
-this.src = "static/transparent.gif"):(this.origBg = this.origBg? this.origBg :this.currentStyle.backgroundImage.toString().replace('url("','').replace('")',''),
-this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.origBg + "',sizingMethod='crop')",
-this.runtimeStyle.backgroundImage = "none")),this.pngSet=true)
-);}
-#wrap{display:table;height:100%}
Deleted file not rendered
@@ -1,65 +0,0 @@
-html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;/* 16px */
-vertical-align:baseline;background:transparent;}
-body{line-height:1;}
-ol,ul{list-style:none;}
-blockquote,q{quotes:none;}
-blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
-:focus{outline:0;}
-ins{text-decoration:none;}
-del{text-decoration:line-through;}
-table{border-collapse:collapse;border-spacing:0;}
-sub{vertical-align:sub;font-size:smaller;line-height:normal;}
-sup{vertical-align:super;font-size:smaller;line-height:normal;}
-ul,menu,dir{display:block;list-style-type:disc;margin:1em 0;padding-left:40px;}
-ol{display:block;list-style-type:decimal-leading-zero;margin:1em 0;padding-left:40px;}
-li{display:list-item;}
-ul ul,ul ol,ul dir,ul menu,ul dl,ol ul,ol ol,ol dir,ol menu,ol dl,dir ul,dir ol,dir dir,dir menu,dir dl,menu ul,menu ol,menu dir,menu menu,menu dl,dl ul,dl ol,dl dir,dl menu,dl dl{margin-top:0;margin-bottom:0;}
-ol ul,ul ul,menu ul,dir ul,ol menu,ul menu,menu menu,dir menu,ol dir,ul dir,menu dir,dir dir{list-style-type:circle;}
-ol ol ul,ol ul ul,ol menu ul,ol dir ul,ol ol menu,ol ul menu,ol menu menu,ol dir menu,ol ol dir,ol ul dir,ol menu dir,ol dir dir,ul ol ul,ul ul ul,ul menu ul,ul dir ul,ul ol menu,ul ul menu,ul menu menu,ul dir menu,ul ol dir,ul ul dir,ul menu dir,ul dir dir,menu ol ul,menu ul ul,menu menu ul,menu dir ul,menu ol menu,menu ul menu,menu menu menu,menu dir menu,menu ol dir,menu ul dir,menu menu dir,menu dir dir,dir ol ul,dir ul ul,dir menu ul,dir dir ul,dir ol menu,dir ul menu,dir menu menu,dir dir menu,dir ol dir,dir ul dir,dir menu dir,dir dir dir{list-style-type:square;}
-.hidden{display:none;}
-p{line-height:1.5em;}
-h1{font-size:1.75em;line-height:1.7em;font-family:helvetica,verdana;}
-h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;}
-h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;}
-h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;}
-html,body{width:100%;height:100%;}
-body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "Nobile","Lucida Grande",Lucida,Verdana,sans-serif;}
-a{color:#1b61d6;text-decoration:none;}
-a:hover{color:#e88f00;text-decoration:underline;}
-body h1,
-body h2,
-body h3,
-body h4,
-body h5,
-body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;}
-#wrap{min-height:100%;}
-#header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;}
-#header{background:#000000;top:0;font-size:14px;}
-#footer{bottom:0;background:#000000 url(footerbg.png) repeat-x 0 top;position:relative;margin-top:-40px;clear:both;}
-.header,.footer{width:750px;margin-right:auto;margin-left:auto;}
-.wrapper{width:100%}
-#top,#top-small,#bottom{width:100%;}
-#top{color:#000000;height:230px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
-#top-small{color:#000000;height:60px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
-#bottom{color:#222;background-color:#ffffff;}
-.top,.top-small,.middle,.bottom{width:750px;margin-right:auto;margin-left:auto;}
-.top{padding-top:40px;}
-.top-small{padding-top:10px;}
-#middle{width:100%;height:100px;background:url(middlebg.png) repeat-x;border-top:2px solid #ffffff;border-bottom:2px solid #b2b2b2;}
-.app-welcome{margin-top:25px;}
-.app-name{color:#000000;font-weight:bold;}
-.bottom{padding-top:50px;}
-#left{width:350px;float:left;padding-right:25px;}
-#right{width:350px;float:right;padding-left:25px;}
-.align-left{text-align:left;}
-.align-right{text-align:right;}
-.align-center{text-align:center;}
-ul.links{margin:0;padding:0;}
-ul.links li{list-style-type:none;font-size:14px;}
-form{border-style:none;}
-fieldset{border-style:none;}
-input{color:#222;border:1px solid #ccc;font-family:sans-serif;font-size:12px;line-height:16px;}
-input[type=text],input[type=password]{width:205px;}
-input[type=submit]{background-color:#ddd;font-weight:bold;}
-/*Opera Fix*/
-body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
Deleted file not rendered
Deleted file not rendered
Deleted file not rendered
@@ -1,57 +1,44 @@
<%include file="head.mako" />
-<%
-if mode == 'edit':
- content = data.content
-else:
- content = ''
-%>
-
-<DIV class="content">
- % if data:
- <DIV class="post">
- % if ptype=="post":
- <H2 class="preview">Preview: ${data.title}</H2>
- % elif ptype=="page":
- <H2 class="preview">Preview: ${data.name}</H2>
- % endif
- ${data.render()|n}
- <DIV class="post_footer">
- <SPAN class="creator">${data.creator|h}</SPAN>
- <SPAN class="created">${data.created|h}</SPAN>
- </DIV>
- </DIV>
+% if data:
+ <DIV class="post">
+ % if ptype=="post":
+ <H2 class="preview">Preview: ${data.title}</H2>
+ % elif ptype=="page":
+ <H2 class="preview">Preview: ${data.name}</H2>
% endif
- <DIV id="instructions">
-
+ ${data.render()|n}
+ <DIV class="post_footer">
+ <SPAN class="creator">${data.creator|h}</SPAN>
+ <SPAN class="created">${data.created|h}</SPAN>
+ </DIV>
</DIV>
-
- <h1>${ptype}</h1>
-
- <FORM action="${request.route_url(mode,mode=mode,ptype=ptype,id=id)}"
- method="post">
- % if ptype == 'post':
- <LABEL for="title">Post Title:</LABEL>
- <INPUT name="title" type="text" size="30" maxlength="30"
- value="${data.title if data else ''|h}"><BR/>
- % elif ptype == 'page':
- <LABEL for="name">Page Name:</LABEL>
- <INPUT name="name" type="text" size="15" maxlength="15"
- value="${data.name if data else ''}"><BR/>
- % endif
- % if (mode,ptype) == ('edit','page'):
- <INPUT name="old_name" type="hidden" value="${data.name}">
- % endif
- <LABEL for="content">${ptype.capitalize()} content:</LABEL><BR/>
- <%
- content = data.content if data else ''
- %>
- <TEXTAREA name="content" rows="20" cols="80">${content}</TEXTAREA>
- <INPUT name="mode" type="hidden" value="${mode}">
- <INPUT name="ptype" type="hidden" value="${ptype}"><BR/>
- <BUTTON type="submit" name="action" value="submit">Submit</BUTTON>
- <BUTTON type="submit" name="action" value="preview">Preview</BUTTON>
- </FORM>
+% endif
+<DIV id="instructions">
+
</DIV>
+
+<FORM action="${request.route_url(mode,ptype=ptype,id=id)}"
+ method="post">
+% if ptype == 'post':
+ <LABEL for="title">Post Title:</LABEL>
+ <INPUT name="title" type="text" size="30" maxlength="30"
+ value="${data.title if data else ''|h}"><BR/>
+% elif ptype == 'page':
+ <LABEL for="name">Page Name:</LABEL>
+ <INPUT name="name" type="text" size="15" maxlength="15"
+ value="${data.name if data else ''}"><BR/>
+% endif
+% if (mode,ptype) == ('edit','page'):
+ <INPUT name="old_name" type="hidden" value="${data.name}">
+% endif
+ <LABEL for="content">${ptype.capitalize()} content:</LABEL><BR/>
+<%
+ content = data.content if data else ''
+%>
+ <TEXTAREA name="content" rows="20" cols="80">${content}</TEXTAREA><BR>
+ <BUTTON type="submit" name="action" value="submit">Submit</BUTTON>
+ <BUTTON type="submit" name="action" value="preview">Preview</BUTTON>
+</FORM>
<%include file="foot.mako" />
Oops, something went wrong.

0 comments on commit 9c776fb

Please sign in to comment.