WIP commit. Changed routes to POST/PUT/DELETE on page name endpoint to be more RESTful. Check wiki dir permissions Add comments Add dummy favicon, robots.txt, humans.txt Remove create.html (wasn't being used) Fix version command
This commit is contained in:
parent
b99128e47a
commit
e6bc4928c9
|
@ -210,7 +210,8 @@ assets.register('main.js',
|
||||||
'vendor/datatables/media/js/jquery.dataTables.js',
|
'vendor/datatables/media/js/jquery.dataTables.js',
|
||||||
'vendor/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.js',
|
'vendor/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.js',
|
||||||
'js/hbs-helpers.js',
|
'js/hbs-helpers.js',
|
||||||
'js/mdr.js')
|
'js/mdr.js',
|
||||||
|
'js/main.js')
|
||||||
|
|
||||||
assets.register('main.css',
|
assets.register('main.css',
|
||||||
'vendor/bootswatch-dist/css/bootstrap.css',
|
'vendor/bootswatch-dist/css/bootstrap.css',
|
||||||
|
|
|
@ -330,8 +330,8 @@ def test():
|
||||||
def version():
|
def version():
|
||||||
""" Output version
|
""" Output version
|
||||||
"""
|
"""
|
||||||
with open('VERSION') as f:
|
with open(os.path.join(config.APP_PATH, 'VERSION')) as f:
|
||||||
return f.read().strip()
|
click.echo(f.read().strip())
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from realms import app
|
||||||
|
from realms.modules.wiki.models import Wiki
|
||||||
|
|
||||||
|
# Init Wiki
|
||||||
|
Wiki(app.config['WIKI_PATH'])
|
||||||
|
|
||||||
|
# Check paths
|
||||||
|
for mode in [os.W_OK, os.R_OK]:
|
||||||
|
for dir_ in [app.config['WIKI_PATH'], os.path.join(app.config['WIKI_PATH'], '.git')]:
|
||||||
|
if not os.access(dir_, mode):
|
||||||
|
sys.exit('Read and write access to WIKI_PATH is required (%s)' % dir_)
|
|
@ -14,15 +14,30 @@ from realms.lib.hook import HookMixin
|
||||||
|
|
||||||
|
|
||||||
def cname_to_filename(cname):
|
def cname_to_filename(cname):
|
||||||
|
""" Convert canonical name to filename
|
||||||
|
|
||||||
|
:param cname: Canonical name
|
||||||
|
:return: str -- Filename
|
||||||
|
|
||||||
|
"""
|
||||||
return cname.lower() + ".md"
|
return cname.lower() + ".md"
|
||||||
|
|
||||||
|
|
||||||
def filename_to_cname(filename):
|
def filename_to_cname(filename):
|
||||||
""" It's assumed filename is already cname format
|
"""Convert filename to canonical name.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
It's assumed filename is already canonical format
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return os.path.splitext(filename)[0]
|
return os.path.splitext(filename)[0]
|
||||||
|
|
||||||
|
|
||||||
|
class PageNotFound(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Wiki(HookMixin):
|
class Wiki(HookMixin):
|
||||||
path = None
|
path = None
|
||||||
base_path = '/'
|
base_path = '/'
|
||||||
|
@ -48,56 +63,42 @@ class Wiki(HookMixin):
|
||||||
return "Wiki: %s" % self.path
|
return "Wiki: %s" % self.path
|
||||||
|
|
||||||
def revert_page(self, name, commit_sha, message, username):
|
def revert_page(self, name, commit_sha, message, username):
|
||||||
|
"""Revert page to passed commit sha1
|
||||||
|
|
||||||
|
:param name: Name of page to revert.
|
||||||
|
:param commit_sha: Commit Sha1 to revert to.
|
||||||
|
:param message: Commit message.
|
||||||
|
:param username:
|
||||||
|
:return: Git commit sha1
|
||||||
|
|
||||||
|
"""
|
||||||
page = self.get_page(name, commit_sha)
|
page = self.get_page(name, commit_sha)
|
||||||
if not page:
|
if not page:
|
||||||
# Page not found
|
raise PageNotFound()
|
||||||
return None
|
|
||||||
commit_info = gittle.utils.git.commit_info(self.gittle[commit_sha.encode('latin-1')])
|
if not message:
|
||||||
message = commit_info['message']
|
commit_info = gittle.utils.git.commit_info(self.gittle[commit_sha.encode('latin-1')])
|
||||||
|
message = commit_info['message']
|
||||||
|
|
||||||
return self.write_page(name, page['data'], message=message, username=username)
|
return self.write_page(name, page['data'], message=message, username=username)
|
||||||
|
|
||||||
def write_page(self, name, content, message=None, create=False, username=None, email=None):
|
def write_page(self, name, content, message=None, create=False, username=None, email=None):
|
||||||
|
"""Write page to git repo
|
||||||
|
|
||||||
def escape_repl(m):
|
:param name: Name of page.
|
||||||
if m.group(1):
|
:param content: Content of page.
|
||||||
return "```" + escape(m.group(1)) + "```"
|
:param message: Commit message.
|
||||||
|
:param create: Perform git add operation?
|
||||||
def unescape_repl(m):
|
:param username: Commit Name.
|
||||||
if m.group(1):
|
:param email: Commit Email.
|
||||||
return "```" + unescape(m.group(1)) + "```"
|
:return: Git commit sha1.
|
||||||
|
"""
|
||||||
|
|
||||||
cname = to_canonical(name)
|
cname = to_canonical(name)
|
||||||
|
|
||||||
# prevents p tag from being added, we remove this later
|
|
||||||
content = '<div>' + content + '</div>'
|
|
||||||
content = re.sub(r"```(.*?)```", escape_repl, content, flags=re.DOTALL)
|
|
||||||
|
|
||||||
tree = lxml.html.fromstring(content)
|
|
||||||
|
|
||||||
cleaner = Cleaner(remove_unknown_tags=False,
|
|
||||||
kill_tags=set(['style']),
|
|
||||||
safe_attrs_only=False)
|
|
||||||
tree = cleaner.clean_html(tree)
|
|
||||||
|
|
||||||
content = lxml.html.tostring(tree, encoding='utf-8', method='html')
|
|
||||||
|
|
||||||
# remove added div tags
|
|
||||||
content = content[5:-6]
|
|
||||||
|
|
||||||
# FIXME this is for block quotes, doesn't work for double ">"
|
|
||||||
content = re.sub(r"(\n>)", "\n>", content)
|
|
||||||
content = re.sub(r"(^>)", ">", content)
|
|
||||||
|
|
||||||
# Handlebars partial ">"
|
|
||||||
content = re.sub(r"\{\{>(.*?)\}\}", r'{{>\1}}', content)
|
|
||||||
|
|
||||||
# Handlebars, allow {{}} inside HTML links
|
|
||||||
content = content.replace("%7B", "{")
|
|
||||||
content = content.replace("%7D", "}")
|
|
||||||
|
|
||||||
content = re.sub(r"```(.*?)```", unescape_repl, content, flags=re.DOTALL)
|
|
||||||
|
|
||||||
filename = cname_to_filename(cname)
|
filename = cname_to_filename(cname)
|
||||||
|
|
||||||
|
content = self.clean(content)
|
||||||
|
|
||||||
with open(self.path + "/" + filename, 'w') as f:
|
with open(self.path + "/" + filename, 'w') as f:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
|
|
||||||
|
@ -122,7 +123,60 @@ class Wiki(HookMixin):
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def clean(self, content):
|
||||||
|
"""Clean any HTML, this might not be necessary.
|
||||||
|
|
||||||
|
:param content: Content of page.
|
||||||
|
:return: str
|
||||||
|
|
||||||
|
"""
|
||||||
|
def escape_repl(m):
|
||||||
|
if m.group(1):
|
||||||
|
return "```" + escape(m.group(1)) + "```"
|
||||||
|
|
||||||
|
def unescape_repl(m):
|
||||||
|
if m.group(1):
|
||||||
|
return "```" + unescape(m.group(1)) + "```"
|
||||||
|
|
||||||
|
# prevents p tag from being added, we remove this later
|
||||||
|
content = '<div>' + content + '</div>'
|
||||||
|
content = re.sub(r"```(.*?)```", escape_repl, content, flags=re.DOTALL)
|
||||||
|
|
||||||
|
tree = lxml.html.fromstring(content)
|
||||||
|
|
||||||
|
cleaner = Cleaner(remove_unknown_tags=False,
|
||||||
|
kill_tags={'style'},
|
||||||
|
safe_attrs_only=False)
|
||||||
|
tree = cleaner.clean_html(tree)
|
||||||
|
|
||||||
|
content = lxml.html.tostring(tree, encoding='utf-8', method='html')
|
||||||
|
|
||||||
|
# remove added div tags
|
||||||
|
content = content[5:-6]
|
||||||
|
|
||||||
|
# FIXME this is for block quotes, doesn't work for double ">"
|
||||||
|
content = re.sub(r"(\n>)", "\n>", content)
|
||||||
|
content = re.sub(r"(^>)", ">", content)
|
||||||
|
|
||||||
|
# Handlebars partial ">"
|
||||||
|
content = re.sub(r"\{\{>(.*?)\}\}", r'{{>\1}}', content)
|
||||||
|
|
||||||
|
# Handlebars, allow {{}} inside HTML links
|
||||||
|
content = content.replace("%7B", "{")
|
||||||
|
content = content.replace("%7D", "}")
|
||||||
|
|
||||||
|
content = re.sub(r"```(.*?)```", unescape_repl, content, flags=re.DOTALL)
|
||||||
|
return content
|
||||||
|
|
||||||
def rename_page(self, old_name, new_name, user=None):
|
def rename_page(self, old_name, new_name, user=None):
|
||||||
|
"""Rename page.
|
||||||
|
|
||||||
|
:param old_name: Page that will be renamed.
|
||||||
|
:param new_name: New name of page.
|
||||||
|
:param user: User object if any.
|
||||||
|
:return: str -- Commit sha1
|
||||||
|
|
||||||
|
"""
|
||||||
old_filename, new_filename = map(cname_to_filename, [old_name, new_name])
|
old_filename, new_filename = map(cname_to_filename, [old_name, new_name])
|
||||||
if old_filename not in self.gittle.index:
|
if old_filename not in self.gittle.index:
|
||||||
# old doesn't exist
|
# old doesn't exist
|
||||||
|
@ -137,14 +191,38 @@ class Wiki(HookMixin):
|
||||||
self.gittle.add(new_filename)
|
self.gittle.add(new_filename)
|
||||||
self.gittle.rm(old_filename)
|
self.gittle.rm(old_filename)
|
||||||
|
|
||||||
self.gittle.commit(name=getattr(user, 'username', self.default_committer_name),
|
commit = self.gittle.commit(name=getattr(user, 'username', self.default_committer_name),
|
||||||
email=getattr(user, 'email', self.default_committer_email),
|
email=getattr(user, 'email', self.default_committer_email),
|
||||||
message="Moved %s to %s" % (old_name, new_name),
|
message="Moved %s to %s" % (old_name, new_name),
|
||||||
files=[old_filename, new_filename])
|
files=[old_filename, new_filename])
|
||||||
|
|
||||||
cache.delete_many(old_filename, new_filename)
|
cache.delete_many(old_filename, new_filename)
|
||||||
|
|
||||||
|
return commit
|
||||||
|
|
||||||
|
def delete_page(self, name, user=None):
|
||||||
|
"""Delete page.
|
||||||
|
:param name: Page that will be deleted
|
||||||
|
:param user: User object if any
|
||||||
|
:return: str -- Commit sha1
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.gittle.rm(name)
|
||||||
|
commit = self.gittle.commit(name=getattr(user, 'username', self.default_committer_name),
|
||||||
|
email=getattr(user, 'email', self.default_committer_email),
|
||||||
|
message="Deleted %s" % name,
|
||||||
|
files=[name])
|
||||||
|
cache.delete_many(name)
|
||||||
|
return commit
|
||||||
|
|
||||||
def get_page(self, name, sha='HEAD'):
|
def get_page(self, name, sha='HEAD'):
|
||||||
|
"""Get page data, partials, commit info.
|
||||||
|
|
||||||
|
:param name: Name of page.
|
||||||
|
:param sha: Commit sha.
|
||||||
|
:return: dict
|
||||||
|
|
||||||
|
"""
|
||||||
cached = cache.get(name)
|
cached = cache.get(name)
|
||||||
if cached:
|
if cached:
|
||||||
return cached
|
return cached
|
||||||
|
@ -172,22 +250,46 @@ class Wiki(HookMixin):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_meta(self, content):
|
def get_meta(self, content):
|
||||||
|
"""Get metadata from page if any.
|
||||||
|
|
||||||
|
:param content: Page content
|
||||||
|
:return: dict
|
||||||
|
|
||||||
|
"""
|
||||||
if not content.startswith("---"):
|
if not content.startswith("---"):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
meta_end = re.search("\n(\.{3}|\-{3})", content)
|
meta_end = re.search("\n(\.{3}|\-{3})", content)
|
||||||
|
|
||||||
if not meta_end:
|
if not meta_end:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return yaml.safe_load(content[0:meta_end.start()])
|
return yaml.safe_load(content[0:meta_end.start()])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return {'error': e.message}
|
return {'error': e.message}
|
||||||
|
|
||||||
def compare(self, name, old_sha, new_sha):
|
def compare(self, name, old_sha, new_sha):
|
||||||
|
"""Compare two revisions of the same page.
|
||||||
|
|
||||||
|
:param name: Name of page.
|
||||||
|
:param old_sha: Older sha.
|
||||||
|
:param new_sha: Newer sha.
|
||||||
|
:return: str - Raw markup with styles
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# TODO: This could be effectively done in the browser
|
||||||
old = self.get_page(name, sha=old_sha)
|
old = self.get_page(name, sha=old_sha)
|
||||||
new = self.get_page(name, sha=new_sha)
|
new = self.get_page(name, sha=new_sha)
|
||||||
return ghdiff.diff(old['data'], new['data'])
|
return ghdiff.diff(old['data'], new['data'])
|
||||||
|
|
||||||
def get_index(self):
|
def get_index(self):
|
||||||
|
"""Get repo index of head.
|
||||||
|
|
||||||
|
:return: list -- List of dicts
|
||||||
|
|
||||||
|
"""
|
||||||
rv = []
|
rv = []
|
||||||
index = self.repo.open_index()
|
index = self.repo.open_index()
|
||||||
for name in index:
|
for name in index:
|
||||||
|
@ -201,8 +303,20 @@ class Wiki(HookMixin):
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
def get_history(self, name, limit=100):
|
def get_history(self, name, limit=100):
|
||||||
|
"""Get page history.
|
||||||
|
|
||||||
|
:param name: Name of page.
|
||||||
|
:param limit: Limit history size.
|
||||||
|
:return: list -- List of dicts
|
||||||
|
|
||||||
|
"""
|
||||||
|
if not len(self.repo.open_index()):
|
||||||
|
# Index is empty, no commits
|
||||||
|
return []
|
||||||
|
|
||||||
file_path = cname_to_filename(name)
|
file_path = cname_to_filename(name)
|
||||||
versions = []
|
versions = []
|
||||||
|
|
||||||
walker = self.repo.get_walker(paths=[file_path], max_entries=limit)
|
walker = self.repo.get_walker(paths=[file_path], max_entries=limit)
|
||||||
for entry in walker:
|
for entry in walker:
|
||||||
change_type = None
|
change_type = None
|
||||||
|
@ -220,4 +334,3 @@ class Wiki(HookMixin):
|
||||||
type=change_type))
|
type=change_type))
|
||||||
|
|
||||||
return versions
|
return versions
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from flask import g, render_template, request, redirect, Blueprint, flash, url_for, current_app
|
from flask import abort, g, render_template, request, redirect, Blueprint, flash, url_for, current_app
|
||||||
from flask.ext.login import login_required
|
from flask.ext.login import login_required
|
||||||
from realms.lib.util import to_canonical, remove_ext
|
from realms.lib.util import to_canonical, remove_ext
|
||||||
from realms.modules.wiki.models import Wiki
|
from realms.modules.wiki.models import Wiki
|
||||||
|
@ -17,10 +17,11 @@ def commit(name, sha):
|
||||||
cname = to_canonical(name)
|
cname = to_canonical(name)
|
||||||
|
|
||||||
data = g.current_wiki.get_page(cname, sha=sha)
|
data = g.current_wiki.get_page(cname, sha=sha)
|
||||||
if data:
|
|
||||||
return render_template('wiki/page.html', name=name, page=data, commit=sha)
|
if not data:
|
||||||
else:
|
abort(404)
|
||||||
return redirect(url_for('wiki.create', name=cname))
|
|
||||||
|
return render_template('wiki/page.html', name=name, page=data, commit=sha)
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route("/_compare/<name>/<regex('[^.]+'):fsha><regex('\.{2,3}'):dots><regex('.+'):lsha>")
|
@blueprint.route("/_compare/<name>/<regex('[^.]+'):fsha><regex('\.{2,3}'):dots><regex('.+'):lsha>")
|
||||||
|
@ -35,15 +36,17 @@ def revert():
|
||||||
name = request.form.get('name')
|
name = request.form.get('name')
|
||||||
commit = request.form.get('commit')
|
commit = request.form.get('commit')
|
||||||
cname = to_canonical(name)
|
cname = to_canonical(name)
|
||||||
|
message = request.form.get('message', "Reverting %s" % cname)
|
||||||
|
|
||||||
if cname in app.config.WIKI_LOCKED_PAGES:
|
if cname in app.config.get('WIKI_LOCKED_PAGES'):
|
||||||
flash("Page is locked")
|
return dict(error=True, message="Page is locked")
|
||||||
return redirect(url_for(app.config['ROOT_ENDPOINT']))
|
|
||||||
|
|
||||||
g.current_wiki.revert_page(name, commit, message="Reverting %s" % cname,
|
sha = g.current_wiki.revert_page(name, commit, message=message,
|
||||||
username=current_user.username)
|
username=current_user.username)
|
||||||
flash('Page reverted', 'success')
|
if sha:
|
||||||
return redirect(url_for('wiki.page', name=cname))
|
flash("Page reverted")
|
||||||
|
|
||||||
|
return dict(sha=sha)
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route("/_history/<name>")
|
@blueprint.route("/_history/<name>")
|
||||||
|
@ -51,74 +54,40 @@ def history(name):
|
||||||
return render_template('wiki/history.html', name=name, history=g.current_wiki.get_history(name))
|
return render_template('wiki/history.html', name=name, history=g.current_wiki.get_history(name))
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route("/_edit/<name>", methods=['GET', 'POST'])
|
@blueprint.route("/_edit/<name>")
|
||||||
@login_required
|
@login_required
|
||||||
def edit(name):
|
def edit(name):
|
||||||
data = g.current_wiki.get_page(name)
|
|
||||||
cname = to_canonical(name)
|
cname = to_canonical(name)
|
||||||
if request.method == 'POST':
|
page = g.current_wiki.get_page(name)
|
||||||
edit_cname = to_canonical(request.form['name'])
|
|
||||||
|
|
||||||
if edit_cname in app.config['WIKI_LOCKED_PAGES']:
|
if not page:
|
||||||
return redirect(url_for(app.config['ROOT_ENDPOINT']))
|
# Page doesn't exist
|
||||||
|
return redirect(url_for('wiki.create', name=cname))
|
||||||
|
|
||||||
if edit_cname != cname.lower():
|
name = remove_ext(page['name'])
|
||||||
g.current_wiki.rename_page(cname, edit_cname)
|
g.assets['js'].append('editor.js')
|
||||||
|
return render_template('wiki/edit.html',
|
||||||
g.current_wiki.write_page(edit_cname,
|
name=name,
|
||||||
request.form['content'],
|
content=page.get('data'),
|
||||||
message=request.form['message'],
|
info=page.get('info'),
|
||||||
username=current_user.username)
|
sha=page.get('sha'),
|
||||||
else:
|
partials=page.get('partials'))
|
||||||
if data:
|
|
||||||
name = remove_ext(data['name'])
|
|
||||||
content = data.get('data')
|
|
||||||
g.assets['js'].append('editor.js')
|
|
||||||
return render_template('wiki/edit.html',
|
|
||||||
name=name,
|
|
||||||
content=content,
|
|
||||||
info=data.get('info'),
|
|
||||||
sha=data.get('sha'),
|
|
||||||
partials=data.get('partials'))
|
|
||||||
else:
|
|
||||||
return redirect(url_for('wiki.create', name=cname))
|
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route("/_delete/<name>", methods=['POST'])
|
@blueprint.route("/_create/", defaults={'name': None})
|
||||||
@login_required
|
@blueprint.route("/_create/<name>")
|
||||||
def delete(name):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route("/_create/", defaults={'name': None}, methods=['GET', 'POST'])
|
|
||||||
@blueprint.route("/_create/<name>", methods=['GET', 'POST'])
|
|
||||||
@login_required
|
@login_required
|
||||||
def create(name):
|
def create(name):
|
||||||
if request.method == 'POST':
|
cname = to_canonical(name) if name else ""
|
||||||
cname = to_canonical(request.form['name'])
|
if cname and g.current_wiki.get_page(cname):
|
||||||
|
# Page exists, edit instead
|
||||||
|
return redirect(url_for('wiki.edit', name=cname))
|
||||||
|
|
||||||
if cname in app.config['WIKI_LOCKED_PAGES']:
|
g.assets['js'].append('editor.js')
|
||||||
return redirect(url_for("wiki.create"))
|
return render_template('wiki/edit.html',
|
||||||
|
name=cname,
|
||||||
if not cname:
|
content="",
|
||||||
return redirect(url_for("wiki.create"))
|
info={})
|
||||||
|
|
||||||
g.current_wiki.write_page(request.form['name'],
|
|
||||||
request.form['content'],
|
|
||||||
message=request.form['message'],
|
|
||||||
create=True,
|
|
||||||
username=current_user.username)
|
|
||||||
else:
|
|
||||||
cname = to_canonical(name) if name else ""
|
|
||||||
if cname and g.current_wiki.get_page(cname):
|
|
||||||
# Page exists, edit instead
|
|
||||||
return redirect(url_for('wiki.edit', name=cname))
|
|
||||||
|
|
||||||
g.assets['js'].append('editor.js')
|
|
||||||
return render_template('wiki/edit.html',
|
|
||||||
name=cname,
|
|
||||||
content="",
|
|
||||||
info={})
|
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route("/_index")
|
@blueprint.route("/_index")
|
||||||
|
@ -126,6 +95,48 @@ def index():
|
||||||
return render_template('wiki/index.html', index=g.current_wiki.get_index())
|
return render_template('wiki/index.html', index=g.current_wiki.get_index())
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route("/<name>", methods=['POST', 'PUT', 'DELETE'])
|
||||||
|
@login_required
|
||||||
|
def page_write(name):
|
||||||
|
cname = to_canonical(name)
|
||||||
|
|
||||||
|
if not cname:
|
||||||
|
return dict(error=True, message="Invalid name")
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
# Create
|
||||||
|
if cname in app.config.get('WIKI_LOCKED_PAGES'):
|
||||||
|
return dict(error=True, message="Page is locked")
|
||||||
|
|
||||||
|
sha = g.current_wiki.write_page(cname,
|
||||||
|
request.form['content'],
|
||||||
|
message=request.form['message'],
|
||||||
|
create=True,
|
||||||
|
username=current_user.username)
|
||||||
|
|
||||||
|
elif request.method == 'PUT':
|
||||||
|
edit_cname = to_canonical(request.form['name'])
|
||||||
|
|
||||||
|
if edit_cname in app.config.get('WIKI_LOCKED_PAGES'):
|
||||||
|
return dict(error=True, message="Page is locked")
|
||||||
|
|
||||||
|
if edit_cname != cname.lower():
|
||||||
|
g.current_wiki.rename_page(cname, edit_cname)
|
||||||
|
|
||||||
|
sha = g.current_wiki.write_page(edit_cname,
|
||||||
|
request.form['content'],
|
||||||
|
message=request.form['message'],
|
||||||
|
username=current_user.username)
|
||||||
|
|
||||||
|
return dict(sha=sha)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# DELETE
|
||||||
|
sha = g.current_wiki.delete_page(name, user=current_user)
|
||||||
|
|
||||||
|
return dict(sha=sha)
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route("/", defaults={'name': 'home'})
|
@blueprint.route("/", defaults={'name': 'home'})
|
||||||
@blueprint.route("/<name>")
|
@blueprint.route("/<name>")
|
||||||
def page(name):
|
def page(name):
|
||||||
|
@ -134,6 +145,7 @@ def page(name):
|
||||||
return redirect(url_for('wiki.page', name=cname))
|
return redirect(url_for('wiki.page', name=cname))
|
||||||
|
|
||||||
data = g.current_wiki.get_page(cname)
|
data = g.current_wiki.get_page(cname)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
return render_template('wiki/page.html', name=cname, page=data, partials=data.get('partials'))
|
return render_template('wiki/page.html', name=cname, page=data, partials=data.get('partials'))
|
||||||
else:
|
else:
|
||||||
|
|
0
realms/static/humans.txt
Normal file
0
realms/static/humans.txt
Normal file
BIN
realms/static/img/favicon.ico
Normal file
BIN
realms/static/img/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
|
@ -2,6 +2,8 @@ var $entry_markdown_header = $("#entry-markdown-header");
|
||||||
var $entry_preview_header = $("#entry-preview-header");
|
var $entry_preview_header = $("#entry-preview-header");
|
||||||
var $entry_markdown = $(".entry-markdown");
|
var $entry_markdown = $(".entry-markdown");
|
||||||
var $entry_preview = $(".entry-preview");
|
var $entry_preview = $(".entry-preview");
|
||||||
|
var $page_name = $("#page-name");
|
||||||
|
var $page_message = $("#page-message");
|
||||||
|
|
||||||
// Tabs
|
// Tabs
|
||||||
$entry_markdown_header.click(function(){
|
$entry_markdown_header.click(function(){
|
||||||
|
@ -66,12 +68,26 @@ var aced = new Aced({
|
||||||
info: Commit.info,
|
info: Commit.info,
|
||||||
submit: function(content) {
|
submit: function(content) {
|
||||||
var data = {
|
var data = {
|
||||||
name: $("#page-name").val(),
|
name: $page_name.val(),
|
||||||
message: $("#page-message").val(),
|
message: $page_message.val(),
|
||||||
content: content
|
content: content
|
||||||
};
|
};
|
||||||
$.post(window.location, data, function() {
|
|
||||||
location.href = Config['RELATIVE_PATH'] + '/' + data['name'];
|
var path = Config['RELATIVE_PATH'] + '/' + data['name'];
|
||||||
|
var type = (Commit.info['sha']) ? "PUT" : "POST";
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
type: type,
|
||||||
|
url: path,
|
||||||
|
data: data,
|
||||||
|
dataType: 'json'
|
||||||
|
}).always(function(data, status, error) {
|
||||||
|
if (data && data['error']) {
|
||||||
|
$page_name.addClass('parsley-error');
|
||||||
|
bootbox.alert("<h3>" + data['message'] + "</h3>");
|
||||||
|
} else {
|
||||||
|
location.href = path;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
40
realms/static/js/main.js
Normal file
40
realms/static/js/main.js
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
$(function(){
|
||||||
|
$(".ajax-form").submit(function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var submitting = 'submitting';
|
||||||
|
|
||||||
|
if ($(this).data(submitting)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$(this).data(submitting, 1);
|
||||||
|
|
||||||
|
var action = $(this).attr('action');
|
||||||
|
var method = $(this).attr('method');
|
||||||
|
var redirect = $(this).data('redirect');
|
||||||
|
var data = $(this).serialize();
|
||||||
|
|
||||||
|
var req = $.ajax({
|
||||||
|
type: method,
|
||||||
|
url: action,
|
||||||
|
data: data,
|
||||||
|
dataType: 'json'
|
||||||
|
});
|
||||||
|
|
||||||
|
req.done(function() {
|
||||||
|
if (redirect) {
|
||||||
|
location.href = redirect;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
req.fail(function(data, status, error) {
|
||||||
|
console.log(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
req.always(function() {
|
||||||
|
$(this).removeData(submitting);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
0
realms/static/robots.txt
Normal file
0
realms/static/robots.txt
Normal file
|
@ -1,18 +0,0 @@
|
||||||
{% extends 'layout.html' %}
|
|
||||||
{% block body %}
|
|
||||||
|
|
||||||
<form role="form" method="post">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="name"></label>
|
|
||||||
<input id="name" type="text" class="form-control" name="name" placeholder="Page Name" value="{{- name -}}" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="content"></label>
|
|
||||||
<textarea name="content" id="content" class="form-control" placeholder="Content"></textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<input type="submit" class="btn btn-primary" value="Save" />
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
|
@ -9,7 +9,7 @@
|
||||||
{% block body %}
|
{% block body %}
|
||||||
{% if commit %}
|
{% if commit %}
|
||||||
<div id="page-action-bar">
|
<div id="page-action-bar">
|
||||||
<form method="POST" action="{{ url_for('wiki.revert') }}">
|
<form method="POST" action="{{ url_for('wiki.revert') }}" class="ajax-form" data-redirect="{{ url_for('wiki.page', name=name) }}">
|
||||||
<input type="hidden" value="{{ name }}" name="name" />
|
<input type="hidden" value="{{ name }}" name="name" />
|
||||||
<input type="hidden" value="{{ commit }}" name="commit" />
|
<input type="hidden" value="{{ commit }}" name="commit" />
|
||||||
<input type="submit" class="btn btn-danger btn-sm" title="Revert back to this revision" value="Revert" />
|
<input type="submit" class="btn btn-danger btn-sm" title="Revert back to this revision" value="Revert" />
|
||||||
|
|
Loading…
Reference in a new issue