def edit(ID): if not allowed_knowl_id.match(ID): flask.flash("""Oops, knowl id '%s' is not allowed. It must consist of lowercase characters, no spaces, numbers or '.', '_' and '-'.""" % ID, "error") return flask.redirect(url_for(".index")) knowl = Knowl(ID) from knowl import is_locked, set_locked lock = False if request.args.get("lock", "") != 'ignore': lock = is_locked(knowl.id) # lock, if either lock is false or (lock is active), current user is editing again author_edits = lock and lock['who'] == current_user.get_id() logger.debug(author_edits) if not lock or author_edits: set_locked(knowl, current_user.get_id()) if author_edits: lock = False b = get_bread([("Edit '%s'" % ID, url_for('.edit', ID=ID))]) return render_template("knowl-edit.html", title="Edit Knowl '%s'" % ID, k=knowl, bread=b, lock=lock)
def edit(ID): from psycopg2 import DatabaseError if not allowed_knowl_id.match(ID): flask.flash("""Oops, knowl id '%s' is not allowed. It must consist of lowercase characters, no spaces, numbers or '.', '_' and '-'.""" % ID, "error") return flask.redirect(url_for(".index")) knowl = Knowl(ID) lock = None if request.args.get("lock", "") != 'ignore': try: lock = knowldb.is_locked(knowl.id) except DatabaseError as e: logger.info("Oops, failed to get the lock. Error: %s" %e) author_edits = lock and lock['who'] == current_user.get_id() logger.debug(author_edits) if author_edits: lock = None if not lock: try: knowldb.set_locked(knowl, current_user.get_id()) except DatabaseError as e: logger.info("Oops, failed to set the lock. Error: %s" %e) b = get_bread([("Edit '%s'" % ID, url_for('.edit', ID=ID))]) return render_template("knowl-edit.html", title="Edit Knowl '%s'" % ID, k=knowl, bread=b, lock=lock)
def edit(ID): from psycopg2 import DatabaseError if not allowed_knowl_id.match(ID): flask.flash( """Oops, knowl id '%s' is not allowed. It must consist of lowercase characters, no spaces, numbers or '.', '_' and '-'.""" % ID, "error") return flask.redirect(url_for(".index")) knowl = Knowl(ID) lock = None if request.args.get("lock", "") != 'ignore': try: lock = knowldb.is_locked(knowl.id) except DatabaseError as e: logger.info("Oops, failed to get the lock. Error: %s" % e) author_edits = lock and lock['who'] == current_user.get_id() logger.debug(author_edits) if author_edits: lock = None if not lock: try: knowldb.set_locked(knowl, current_user.get_id()) except DatabaseError as e: logger.info("Oops, failed to set the lock. Error: %s" % e) b = get_bread([("Edit '%s'" % ID, url_for('.edit', ID=ID))]) return render_template("knowl-edit.html", title="Edit Knowl '%s'" % ID, k=knowl, bread=b, lock=lock)
def edit(ID): from psycopg2 import DatabaseError if not allowed_id(ID): return redirect(url_for(".index")) knowl = Knowl(ID, editing=True) for elt in knowl.edit_history: # We will be printing these within a javascript ` ` string # so need to escape backticks elt['content'] = json.dumps(elt['content']) author = knowl._last_author # Existing comments can only be edited by admins and the author if knowl.type == -2 and author and not (current_user.is_admin() or current_user.get_id() == author): flash_error("You can only edit your own comments") return redirect(url_for(".show", ID=knowl.source)) lock = None if request.args.get("lock", "") != 'ignore': try: lock = knowldb.is_locked(knowl.id) except DatabaseError as e: logger.info("Oops, failed to get the lock. Error: %s" % e) author_edits = lock and lock['username'] == current_user.get_id() logger.debug(author_edits) if author_edits: lock = None if not lock: try: knowldb.set_locked(knowl, current_user.get_id()) except DatabaseError as e: logger.info("Oops, failed to set the lock. Error: %s" % e) b = get_bread([("Edit '%s'" % ID, url_for('.edit', ID=ID))]) if knowl.type == -2: title = "Comment on '%s'" % knowl.source elif knowl.type == 0: title = "Edit Knowl '%s'" % ID elif knowl.type == 2: pieces = ID.split(".") title = f"Edit column information for '{pieces[2]}' in '{pieces[1]}'" knowl.title = f"Column {pieces[2]} of table {pieces[1]}" from lmfdb import db if pieces[1] in db.tablenames: knowl.coltype = db[pieces[1]].col_type.get(pieces[2], "DEFUNCT") else: knowl.coltype = "DEFUNCT" else: ann_type = 'Top' if knowl.type == 1 else 'Bottom' title = 'Edit %s Knowl for <a href="/%s">%s</a>' % ( ann_type, knowl.source, knowl.source_name) return render_template("knowl-edit.html", title=title, k=knowl, bread=b, lock=lock)
def edit(ID): from psycopg2 import DatabaseError if not allowed_id(ID): return redirect(url_for(".index")) knowl = Knowl(ID, editing=True) for elt in knowl.edit_history: # We will be printing these within a javascript ` ` string # so need to escape backticks elt['content'] = json.dumps(elt['content']) author = knowl._last_author # Existing comments can only be edited by admins and the author if knowl.type == -2 and author and not (current_user.is_admin() or current_user.get_id() == author): flash("You can only edit your own comments", "error") return redirect(url_for(".show", ID=knowl.source)) lock = None if request.args.get("lock", "") != 'ignore': try: lock = knowldb.is_locked(knowl.id) except DatabaseError as e: logger.info("Oops, failed to get the lock. Error: %s" %e) author_edits = lock and lock['username'] == current_user.get_id() logger.debug(author_edits) if author_edits: lock = None if not lock: try: knowldb.set_locked(knowl, current_user.get_id()) except DatabaseError as e: logger.info("Oops, failed to set the lock. Error: %s" %e) b = get_bread([("Edit '%s'" % ID, url_for('.edit', ID=ID))]) if knowl.type == -2: title = "Comment on '%s'" % knowl.source elif knowl.type == 0: title = "Edit Knowl '%s'" % ID else: ann_type = 'Top' if knowl.type == 1 else 'Bottom' title = 'Edit %s Knowl for <a href="/%s">%s</a>' % (ann_type, knowl.source, knowl.source_name) return render_template("knowl-edit.html", title=title, k=knowl, bread=b, lock=lock)
def render_knowl(ID, footer=None, kwargs=None, raw=False, k=None, allow_deleted=False, timestamp=None): """ this method renders the given Knowl (ID) to insert it dynamically in a website. It is intended to be used by an AJAX call, but should do a similar job server-side only, too. Note, that the used knowl-render.html template is *not* based on any globally defined website and just creates a small and simple html snippet! the keyword 'raw' is used in knowledge.show and knowl_inc to include *just* the string and not the response object. """ # logger.debug("kwargs: %s", request.args) kwargs = kwargs or dict(((k, v) for k, v in request.args.items())) # logger.debug("kwargs: %s" , kwargs) if timestamp is None: # fetch and convert the ms timestamp to datetime try: timestamp = timestamp_in_ms_to_datetime(int(kwargs['timestamp'])) except KeyError: pass if k is None: try: k = Knowl(ID, allow_deleted=allow_deleted, timestamp=timestamp) except Exception: logger.critical("Failed to render knowl %s" % ID) errmsg = "Sorry, the knowledge database is currently unavailable." return errmsg if raw else make_response(errmsg) # If we are rendering a reviewed knowl on nonbeta, # we always include the timestamp if timestamp is None and k.status == 1 and not is_beta(): kwargs['timestamp'] = k.ms_timestamp # kw_params is inserted *verbatim* into the url_for(...) function inside the template # the idea is to pass the keyword arguments of the knowl further along the chain # of links, in this case the title and the permalink! # so, this kw_params should be plain python, e.g. "a=1, b='xyz'" kw_params = ', '.join(('%s="%s"' % (k, v) for k, v in kwargs.items())) logger.debug("kw_params: %s" % kw_params) # this is a very simple template based on no other template to render one single Knowl # for inserting into a website via AJAX or for server-side operations. if request.method == "POST": con = request.form['content'] foot = footer or request.form['footer'] elif request.method == "GET": con = request.args.get("content", k.content) foot = footer or request.args.get("footer", "1") # authors = [] # for a in k.author_links(): # authors.append("<a href='%s'>%s</a>" % # (url_for('users.profile', userid=a['_id']), a['full_name'] or a['_id'] )) # authors = ', '.join(authors) render_me = u"""\ {%% include "knowl-defs.html" %%} {%% from "knowl-defs.html" import KNOWL with context %%} {%% from "knowl-defs.html" import KNOWL_LINK with context %%} {%% from "knowl-defs.html" import KNOWL_INC with context %%} {%% from "knowl-defs.html" import TEXT_DATA with context %%} <div class="knowl">""" if foot == "1": render_me += """\ <div class="knowl-header"> <a href="{{ url_for('.show', ID='%(ID)s', %(kw_params)s ) }}">%(title)s</a> </div>""" % { 'ID': k.id, 'title': (k.title or k.id), 'kw_params': kw_params } render_me += """<div><div class="knowl-content">%(content)s</div></div>""" review_status = "" if foot == "1": render_me += """\ <div class="knowl-footer"> <a href="{{ url_for('.show', ID='%(ID)s', %(kw_params)s) }}">permalink</a> {%% if user_is_authenticated %%} · <a href="{{ url_for('.edit', ID='%(ID)s') }}">edit</a> {%% endif %%} %(review_status)s </div>""" # """ · Authors: %(authors)s """ if k.status == 0 and k.type != -2: review_status = """· (awaiting review)""" render_me += "</div>" # render_me = render_me % {'content' : con, 'ID' : k.id } con = md_preprocess(con) # markdown enabled render_me = render_me % { 'content': md.convert(con), 'ID': k.id, 'review_status': review_status, 'kw_params': kw_params } #, 'authors' : authors } # Pass the text on to markdown. Note, backslashes need to be escaped for # this, but not for the javascript markdown parser # logger.debug("rendering template string:\n%s" % render_me) # TODO improve the error message # so that the user has a clue. Most likely, the {{ KNOWL('...') }} has the wrong syntax! try: data = render_template_string(render_me, k=k, **kwargs) if raw: # note, this is just internally for the .show method, raw rendering # doesn't exist right now and will wrap this into a make_reponse! return data resp = make_response(data) # cache if it is a usual GET if request.method == 'GET': resp.headers['Cache-Control'] = 'max-age=%d, public' % ( _cache_time, ) resp.headers['Access-Control-Allow-Origin'] = '*' return resp except Exception as e: return "ERROR in the template: %s. Please edit it to resolve the problem." % e
def index(): # bypassing the Knowl objects to speed things up from knowl import get_knowls # See issue #1169 # try: # get_knowls().ensure_index('_keywords') # get_knowls().ensure_index('cat') # except pymongo.errors.OperationFailure: # pass cur_cat = request.args.get("category", "") qualities = [] defaults = "filter" not in request.args filtermode = "filter" in request.args searchmode = "search" in request.args categorymode = "category" in request.args from knowl import knowl_qualities # TODO wrap this into a loop: reviewed = request.args.get("reviewed", "") == "on" or defaults ok = request.args.get("ok", "") == "on" or defaults beta = request.args.get("beta", "") == "on" or defaults if reviewed: qualities.append("reviewed") if ok: qualities.append("ok") if beta: qualities.append("beta") s_query = {} if filtermode: quality_q = {'$in': qualities} s_query['quality'] = quality_q keyword = request.args.get("search", "").lower() if searchmode and keyword: keywords = filter(lambda _: len(_) >= 3, keyword.split(" ")) # logger.debug("keywords: %s" % keywords) keyword_q = {'_keywords': {"$all": keywords}} s_query.update(keyword_q) if categorymode: s_query.update({'cat': cur_cat}) # { "$regex" : r"^%s\..+" % cur_cat } logger.debug("search query: %s" % s_query) knowls = get_knowls().find(s_query, ['title']) def first_char(k): t = k['title'] if len(t) == 0: return "?" if t[0] not in string.ascii_letters: return "?" return t[0].upper() # way to additionally narrow down the search # def incl(knwl): # if keyword in knwl['_id'].lower(): return True # if keyword in knwl['title'].lower(): return True # return False # if keyword: knowls = filter(incl, knowls) from knowl import get_categories cats = get_categories() def knowl_sort_key(knowl): '''sort knowls, special chars at the end''' title = knowl['title'] if title and title[0] in string.ascii_letters: return (0, title.lower()) else: return (1, title.lower()) knowls = sorted(knowls, key=knowl_sort_key) from itertools import groupby knowls = groupby(knowls, first_char) return render_template("knowl-index.html", title="Knowledge Database", bread=get_bread(), knowls=knowls, search=keyword, searchbox=searchbox(request.args.get("search", ""), searchmode), knowl_qualities=knowl_qualities, searchmode=searchmode, filters=(beta, ok, reviewed), categories=cats, cur_cat=cur_cat, categorymode=categorymode)
def render_knowl(ID, footer=None, kwargs=None, raw=False, k=None, allow_deleted=False, timestamp=None): """ this method renders the given Knowl (ID) to insert it dynamically in a website. It is intended to be used by an AJAX call, but should do a similar job server-side only, too. Note, that the used knowl-render.html template is *not* based on any globally defined website and just creates a small and simple html snippet! the keyword 'raw' is used in knowledge.show and knowl_inc to include *just* the string and not the response object. """ # logger.debug("kwargs: %s", request.args) kwargs = kwargs or dict(((k, v) for k, v in request.args.iteritems())) # logger.debug("kwargs: %s" , kwargs) if timestamp is None: # fetch and convert the ms timestamp to datetime try: timestamp = timestamp_in_ms_to_datetime(int(kwargs['timestamp'])) except KeyError: pass if k is None: try: k = Knowl(ID, allow_deleted=allow_deleted, timestamp=timestamp) except Exception: logger.critical("Failed to render knowl %s"%ID) errmsg = "Sorry, the knowledge database is currently unavailable." return errmsg if raw else make_response(errmsg) # If we are rendering a reviewed knowl on nonbeta, # we always include the timestamp if timestamp is None and k.status == 1 and not is_beta(): kwargs['timestamp'] = k.ms_timestamp; # kw_params is inserted *verbatim* into the url_for(...) function inside the template # the idea is to pass the keyword arguments of the knowl further along the chain # of links, in this case the title and the permalink! # so, this kw_params should be plain python, e.g. "a=1, b='xyz'" kw_params = ', '.join(('%s="%s"' % (k, v) for k, v in kwargs.iteritems())) logger.debug("kw_params: %s" % kw_params) # this is a very simple template based on no other template to render one single Knowl # for inserting into a website via AJAX or for server-side operations. if request.method == "POST": con = request.form['content'] foot = footer or request.form['footer'] elif request.method == "GET": con = request.args.get("content", k.content) foot = footer or request.args.get("footer", "1") # authors = [] # for a in k.author_links(): # authors.append("<a href='%s'>%s</a>" % # (url_for('users.profile', userid=a['_id']), a['full_name'] or a['_id'] )) # authors = ', '.join(authors) render_me = u"""\ {%% include "knowl-defs.html" %%} {%% from "knowl-defs.html" import KNOWL with context %%} {%% from "knowl-defs.html" import KNOWL_LINK with context %%} {%% from "knowl-defs.html" import KNOWL_INC with context %%} {%% from "knowl-defs.html" import TEXT_DATA with context %%} <div class="knowl">""" if foot == "1": render_me += """\ <div class="knowl-header"> <a href="{{ url_for('.show', ID='%(ID)s', %(kw_params)s ) }}">%(title)s</a> </div>""" % {'ID': k.id, 'title': (k.title or k.id), 'kw_params': kw_params} render_me += """<div><div class="knowl-content">%(content)s</div></div>""" review_status = "" if foot == "1": render_me += """\ <div class="knowl-footer"> <a href="{{ url_for('.show', ID='%(ID)s', %(kw_params)s) }}">permalink</a> {%% if user_is_authenticated %%} · <a href="{{ url_for('.edit', ID='%(ID)s') }}">edit</a> {%% endif %%} %(review_status)s </div>""" # """ · Authors: %(authors)s """ if k.status == 0 and k.type != -2: review_status = """· (awaiting review)""" render_me += "</div>" # render_me = render_me % {'content' : con, 'ID' : k.id } con = md_preprocess(con) # markdown enabled render_me = render_me % {'content': md.convert(con), 'ID': k.id, 'review_status': review_status, 'kw_params': kw_params} #, 'authors' : authors } # Pass the text on to markdown. Note, backslashes need to be escaped for # this, but not for the javascript markdown parser # logger.debug("rendering template string:\n%s" % render_me) # TODO improve the error message # so that the user has a clue. Most likely, the {{ KNOWL('...') }} has the wrong syntax! try: data = render_template_string(render_me, k=k, **kwargs) if raw: # note, this is just internally for the .show method, raw rendering # doesn't exist right now and will wrap this into a make_reponse! return data resp = make_response(data) # cache if it is a usual GET if request.method == 'GET': resp.headers['Cache-Control'] = 'max-age=%d, public' % (_cache_time,) resp.headers['Access-Control-Allow-Origin'] = '*' return resp except Exception, e: return "ERROR in the template: %s. Please edit it to resolve the problem." % e
def index(): # bypassing the Knowl objects to speed things up from knowl import get_knowls try: get_knowls().ensure_index('_keywords') get_knowls().ensure_index('cat') except pymongo.errors.OperationFailure: pass cur_cat = request.args.get("category", "") qualities = [] defaults = "filter" not in request.args filtermode = "filter" in request.args searchmode = "search" in request.args categorymode = "category" in request.args from knowl import knowl_qualities # TODO wrap this into a loop: reviewed = request.args.get("reviewed", "") == "on" or defaults ok = request.args.get("ok", "") == "on" or defaults beta = request.args.get("beta", "") == "on" or defaults if reviewed: qualities.append("reviewed") if ok: qualities.append("ok") if beta: qualities.append("beta") s_query = {} if filtermode: quality_q = {'$in': qualities} s_query['quality'] = quality_q keyword = request.args.get("search", "").lower() if searchmode and keyword: keywords = filter(lambda _: len(_) >= 3, keyword.split(" ")) # logger.debug("keywords: %s" % keywords) keyword_q = {'_keywords': {"$all": keywords}} s_query.update(keyword_q) if categorymode: s_query.update({'cat': cur_cat}) # { "$regex" : r"^%s\..+" % cur_cat } logger.debug("search query: %s" % s_query) knowls = get_knowls().find(s_query, ['title']) def first_char(k): t = k['title'] if len(t) == 0: return "?" if t[0] not in string.ascii_letters: return "?" return t[0].upper() # way to additionally narrow down the search # def incl(knwl): # if keyword in knwl['_id'].lower(): return True # if keyword in knwl['title'].lower(): return True # return False # if keyword: knowls = filter(incl, knowls) from knowl import get_categories cats = get_categories() def knowl_sort_key(knowl): '''sort knowls, special chars at the end''' title = knowl['title'] if title and title[0] in string.ascii_letters: return (0, title.lower()) else: return (1, title.lower()) knowls = sorted(knowls, key=knowl_sort_key) from itertools import groupby knowls = groupby(knowls, first_char) return render_template("knowl-index.html", title="Knowledge Database", bread=get_bread(), knowls=knowls, search=keyword, searchbox=searchbox(request.args.get("search", ""), searchmode), knowl_qualities=knowl_qualities, searchmode=searchmode, filters=(beta, ok, reviewed), categories = cats, cur_cat = cur_cat, categorymode = categorymode)
def render(ID, footer=None, kwargs=None, raw=False): """ this method renders the given Knowl (ID) to insert it dynamically in a website. It is intended to be used by an AJAX call, but should do a similar job server-side only, too. Note, that the used knowl-render.html template is *not* based on any globally defined website and just creates a small and simple html snippet! the keyword 'raw' is used in knowledge.show and knowl_inc to include *just* the string and not the response object. """ k = Knowl(ID) # logger.debug("kwargs: %s", request.args) kwargs = kwargs or dict(((k, v) for k, v in request.args.iteritems())) # logger.debug("kwargs: %s" , kwargs) # kw_params is inserted *verbatim* into the url_for(...) function inside the template # the idea is to pass the keyword arguments of the knowl further along the chain # of links, in this case the title and the permalink! # so, this kw_params should be plain python, e.g. "a=1, b='xyz'" kw_params = ", ".join(('%s="%s"' % (k, v) for k, v in kwargs.iteritems())) logger.debug("kw_params: %s" % kw_params) # this is a very simple template based on no other template to render one single Knowl # for inserting into a website via AJAX or for server-side operations. if request.method == "POST": con = request.form["content"] foot = footer or request.form["footer"] elif request.method == "GET": con = request.args.get("content", k.content) foot = footer or request.args.get("footer", "1") # authors = [] # for a in k.author_links(): # authors.append("<a href='%s'>%s</a>" % # (url_for('users.profile', userid=a['_id']), a['full_name'] or a['_id'] )) # authors = ', '.join(authors) render_me = u"""\ {%% include "knowl-defs.html" %%} {%% from "knowl-defs.html" import KNOWL with context %%} {%% from "knowl-defs.html" import KNOWL_LINK with context %%} {%% from "knowl-defs.html" import KNOWL_INC with context %%} {%% from "knowl-defs.html" import TEXT_DATA with context %%} <div class="knowl">""" if foot == "1": render_me += """\ <div class="knowl-header"> <a href="{{ url_for('.show', ID='%(ID)s', %(kw_params)s ) }}">%(title)s</a> </div>""" % { "ID": k.id, "title": (k.title or k.id), "kw_params": kw_params, } render_me += """<div><div class="knowl-content">%(content)s</div></div>""" if foot == "1": render_me += """\ <div class="knowl-footer"> <a href="{{ url_for('.show', ID='%(ID)s', %(kw_params)s) }}">permalink</a> {%% if user_is_authenticated %%} · <a href="{{ url_for('.edit', ID='%(ID)s') }}">edit</a> {%% endif %%} </div>""" # """ · Authors: %(authors)s """ render_me += "</div>" # render_me = render_me % {'content' : con, 'ID' : k.id } # markdown enabled render_me = render_me % {"content": md.convert(con), "ID": k.id, "kw_params": kw_params} # , 'authors' : authors } # Pass the text on to markdown. Note, backslashes need to be escaped for # this, but not for the javascript markdown parser # logger.debug("rendering template string:\n%s" % render_me) # TODO improve the error message # so that the user has a clue. Most likely, the {{ KNOWL('...') }} has the wrong syntax! try: data = render_template_string(render_me, k=k, **kwargs) if raw: return data resp = make_response(data) # cache 10 minutes if it is a usual GET if request.method == "GET": resp.headers["Cache-Control"] = "max-age=%s, public" % (10 * 60) return resp except Exception, e: return "ERROR in the template: %s. Please edit it to resolve the problem." % e