def regionTable(): h = """<table class='bz-report-table'> <tr> <th>Region</th> <th>Seats</th> </tr> """ totSeats = 0 rs = sorted(region.Region.all(), key=lambda r: r.ix) for r in rs: h += form( """<tr> <td>{a}</td> <td style='text-align:right'>{seats}</td> </tr>""", a=r.a(), seats=r.seats, ) totSeats += r.seats #//for r h += form( """<tr style='font-weight:bold'> <td>TOTAL</td> <td style='text-align:right'>{seats}</td> </tr>""", seats=totSeats, ) h += "</table>" return h
def boolH(b: bool, yesText: str = "yes", noText: str = "no") -> str: """ Return html for a boolean """ if b: h = form("<span class='yes'><i class='fa fa-check'></i> {}</span>", yesText) else: h = form("<span class='no'><i class='fa fa-times'></i> {}</span>", noText) return h
def calcGroupTable(userName: str) -> str: """ caslculate the group table for the current user. Returns html. """ h = """<table class='bz-report-table'> <tr> <th>Group</th> <th>Questions<br>Answered</th> <th>Questions<br>Unanswered</th> <th>Details</th> </tr> """ groups = questionManager.getGroups() for group in groups: dpr("group.id=%r", group.id) numQs = len(group.questions) numAnswered = len(answeredQs(currentUserName(), group.questions)) numUnanswered = numQs - numAnswered if numUnanswered == 0: detailsH = form( "View <a href='/results/{groupId}' class='green'>" "<i class='fa fa-star'></i> " "Your Results</a>", groupId=htmlEsc(group.id)) else: detailsH = ("<i class='fa fa-lock'></i> " "<i>answer all questions to unlock details</i>") h += form( """ <tr> <td><a href="/group/{groupId}">{groupName}</a></td> <td style='text-align:right;'> <a href="/answered/{groupId}">{numAnswered}</a></td> <td style='text-align:right;'> <a href="/ask/{groupId}">{numUnanswered}</a>/{numTotal}</td> <td>{details}</td> </tr> """, groupId=htmlEsc(group.id), numQs=numQs, groupName=htmlEsc(group.title), numAnswered=numAnswered, numUnanswered=numUnanswered, numTotal=numQs, details=detailsH, ) #//for h += "</table>\n" return h
def usersTable(): """ returns an html table of users """ h = """<table class='bz-report-table'> <tr> <th class=debug>(id)</th> <th>User name</th> <th>Email</th> <th>Is Admin?</th> <th>Is Active?</th> </tr> """ for doc in userdb.User.find(sort=[('userName',pymongo.ASCENDING)]): item = form("""<tr> <td>{a}</td> <td>{email}</td> <td>{isAdmin}</td> <td>{isActive}</td> </tr>""", a = doc.a(), userName = doc.asReadableH('userName'), email = doc.asReadableH('email'), isAdmin = doc.asReadableH('isAdmin'), isActive = doc.asReadableH('isActive'), ) h += item #//for h += "</table>\n" return h
def wikiEdit(u: str, pn: str): """ Edit a wiki page @param u = user id @param pn = page name """ npn = mark.normaliseTagWpn(pn) # normalised page name wp = wikidb.getWikiPage(u, npn, create=True) wf = WikiForm(source=wp.source) if request.method == 'POST': wf = wf.populateFromRequest(request) wp.source = wf.source wp.save() return redirect(form("/wiki/{u}/{pn}", u=u, pn=pn)) #//if tem = jinjaEnv.get_template("wikiEdit.html") h = tem.render( userName=htmlEsc(u), pn=htmlEsc(pn), wp=wp, wf=wf, exists=bool(wp), canAlter=True, nav=wikiPageNav(u, npn), ) return h
def popularTagsTable(pag: paginate.Paginator) -> str: """ table of popular tags """ h = """<table class='bz-report-table'> <tr> <th>Tag</th> <th>Popularity</th> <th>Created</th> <th>Last Used</th> </tr> """ tags = models.Tag.find( skip=pag.skip, # skip this number of docs before returning some limit=pag.numShow, # max number of docs to return sort=[('timesUsed',-1),('lastUsed',-1),'_id']) for t in tags: h += form ("""<tr> <td><a href='/tag/{id}'>#{id}</a></td> <td style='text-align:right;'>{timesUsed}</td> <td>{created}</td> <td>{lastUsed}</td> </tr>""", id =t._id, timesUsed = t.asReadableH('timesUsed'), created = t.asReadableH('created'), lastUsed = t.asReadableH('lastUsed'), ) #//for t h += "</table>" return h
def alertsTable(q: dict, pag: paginate.Paginator) -> str: """ html table of alerts @param q = MongoDB query """ h = """<table class='bz-report-table'> <tr> <th>Time</th> <th>Alert Type</th> <th>Message</th> <th>Doer</th> <th>Reply</th> </tr> """ als = models.Alert.find(q, skip=pag.skip, limit=pag.numShow, sort=('created', -1)) for al in als: h += form("""<tr> <td>{created}</td> <td>{alertType}</td> <td>{message}</td> <td><a href='/blog/{doer}'>@{doer}</a></td> <td>{reply}</td> </tr>""", created=al.asReadableH('created'), alertType=al.asReadableH('alertType'), mid=al.message_id, message=al.asReadableH('message_id'), doer=al.doer_id, reply=al.asReadableH('reply_id')) #//for al h += "</table>" return h
def rowcol(colSpec: str)->str: cs = "col-" + colSpec s = form("""<div class="container-fluid"> <div class="row"> <div class="{cs}">""", cs = cs) return s
def mostStarredTable(q: dict, pag: paginate.Paginator) -> str: """ html table of most-starred messages @param q = MongoDB query """ h = """<table class='bz-report-table'> <tr> <th>Message</th> <th>Author</th> <th>Stars</th> <th>Published</th> </tr> """ ms = models.Message.find(q, skip=pag.skip, limit=pag.numShow, sort=[('numStars', -1), 'published']) for m in ms: h += form( """<tr> <td><a href='/mess/{mid}'>{title}</a></td> <td><a href='/blog/{u}'>@{u}</a></td> <td style='text-align:right;'>{numStars}</td> <td>{published}</td> </tr>""", mid=m._id, title=m.asReadableH('title'), u=m.author_id, numStars=m.asReadableH('numStars'), published=m.asReadableH('published'), ) #//for m h += "</table>" return h
def col(colSpec: str)->str: cs = "col-" + colSpec s = form(""" </div> <div class="{cs}">""", cs = cs) return s
def askH(self) -> str: """ return the question as html """ h = form(""" <p class='question'><i class='fa fa-question-circle-o'></i> <tt>[{qid}]</tt> {qtext}</p>""", qid=htmlEsc(self.qid), qtext=htmlEsc(self.qtext)) return h
def wikiPageNav(u: str, npn: str) -> str: """ Return html for navigation for a wiki page """ pageIconFa = "fa-home" if npn == "home" else "fa-file-text-o" pageIcon = form("<i class='fa {fa}'></i>", fa=pageIconFa) h = form("""<span class='nav-instance'> <i class='fa fa-bank'></i> {siteLocation}</span> <span class='nav-user'> <i class='fa fa-user'></i> {u}</span> <span class='nav-wiki'> <i class='fa fa-database'></i> {pageIcon} {pn}</span> """, siteLocation=config.SITE_LOCATION, u=htmlEsc(u), pageIcon=pageIcon, pn=htmlEsc(npn)) return h
def getStarredMessages(q: dict) -> str: """ get starred messages corresponsing to query (q). Include who starred each message """ h = "" als = models.Alert.find(q, sort=[('message_id', -1), ('created', -1)]) starrersByMessage = groupByMessage(als) for mess, starrers in starrersByMessage: dpr("starrers=%r", starrers) starrersH = ", ".join( form("<a href='/blog/{u}'>@{u}</a>", u=u) for u in starrers) dpr("starrersH=%r", starrersH) h += form("<p><br>Starred by {starrers}:</p>\n{m}\n", starrers=starrersH, m=mess.viewH()) dpr("h=%r", h) #//for al return h
def pollTable() -> str: partyCols = "" for p in POLL_PARTIES: pa = party.Party.docs[p] partyCols += form("<th>{partyName}<br>{logo}</th>", partyName = pa.getNameH(), logo = pa.logo()) #//for h = form("""<table class='bz-report-table'> <tr> <th>End<br>Date</th> <th>Days<br>to Poll</th> <th>Polling<br>Org</th> <th>Sample<br>Size</th> {partyCols} </tr> """, partyCols = partyCols) allPolls = sorted(Poll.polls, key=lambda po: po.dateInt) for po in allPolls: partyCells = "" for p in POLL_PARTIES: pa = party.Party.docs[p] partyCells += ("<td style='text-align:right;color:%s'" ">%.1f</td>\n" % (pa.col, po.__dict__[p],)) h += form("""<tr> <td>{date}</td> <td style='text-align:right'>{dateInt}</td> <td>{org}</td> <td style='text-align:right'>{sample}</td> {partyCells} </tr>""", date = htmlEsc(po.date), dateInt = po.dateInt, org = htmlEsc(po.org), sample = htmlEsc(str(po.sample)), partyCells = partyCells) #//for h += "</table>" return h
def formSection(t: str)->str: """ @param t::str containing html = text to go in title @return::str containing html """ r = form("""<tr><td colspan=2 class='form-section'> <div>{}</div> </td></tr>""", t) return r
def paginationBefore(self) -> str: """ Return pagination html that goes before the list of messages. """ if not self.pag: self.setUpPagination() if not self.doPagination: return "" if self.pag.skip <= 0: return "" h = form("<p>Displaying messages {fromIx}-{toIx} of {total}.</p>", fromIx=self.pag.fromIx, toIx=self.pag.toIx, total=self.pag.total) return h
def getArticleBody(art: str): """ given an article name, return the body of the article. @return::(str,str) = title,html """ articlePan = butil.join(ARTICLE_DIR, art + ".md") #prvars() if butil.fileExists(articlePan): src = open(articlePan).read() contents = mark.render(src) return art, contents else: h = form("<p>({art} does not exist)</p>\n", art=art) return (pathName, h)
def paginationAfter(self) -> str: """ Return pagination html that goes after the list of messages. """ if not self.pag: self.setUpPagination() if not self.doPagination: return "" h = form("""<br> <p>Displaying messages {fromIx}-{toIx} of {total}.</p> <div class='right-pagination'>{links}</div>""", fromIx=self.pag.fromIx, toIx=self.pag.toIx, total=self.pag.total, links=self.pag.links) return h
def wikiNav(u: str) -> str: """ Return html for navigation for a wiki """ h = form("""<span class='nav-instance'> <i class='fa fa-bank'></i> {siteLocation}</span> <span class='nav-user'> <i class='fa fa-user'></i> {u}</span> </span> <span class='nav-wiki'> <i class='fa fa-database'></i> </span> """, siteLocation=config.SITE_LOCATION, u=htmlEsc(u)) return h
def getArticles(): articleFns = butil.getFilenames(ARTICLE_DIR, "*.md") dpr("ARTICLE_DIR=%r", ARTICLE_DIR) dpr("articleFns=%r", articleFns) h = "" for afn in articleFns: title = getTitle(butil.join(ARTICLE_DIR, afn)) dpr("afn=%r title=%r", afn, title) h += form( "<p><a href='/article/{art}'>" "<i class='fa fa-file-text-o'></i> {title}</a></p>\n", art=afn[:-3], title=title) #//for return h
def answerH(self, ans) -> str: """ return the querstion as html with the answer selected in (ans). """ userAnswerText = self.answerText(ans) h = form(""" <p class='question'><i class='fa fa-question-circle-o'></i> <tt>[{qid}]</tt> {qtext}</p> <tt>[{ansVal}]</tt> {ansText} <br> """, qid=htmlEsc(self.qid), qtext=htmlEsc(self.qtext), ansVal=htmlEsc(ans), ansText=htmlEsc(userAnswerText)) return h
def autoUpdateJS(self) -> str: """ return some JavaScript for handling automatic updates. These occur when these is a message more recent that the more recent timestamp. Timestamps are in the format e.g. '2011-12-31T23:55:20' and can therefore be sorted by ascii collating sequence. """ autoUpdate = self.fof.au and self.fof.mrf if not autoUpdate: return "" js = form("""\ var updatePollUrl = "{url}"; var mostRecentTimeStamp = "{timeStamp}"; pollForAutoUpdate(updatePollUrl, mostRecentTimeStamp); """, url="/au" + request.full_path, timeStamp=self.mostRecentTimeStamp()) return js
def goodMessageBox(msg: str, escapeForHtml: bool = True) -> str: """ If a message is blank, leave it blank. Otherwise, wrap it up in css that makes it look like a pretty warning message. @param msg = message to be displayed @param escapeForHtml = if True, the msg is deemed to contain a non-html string, which needs to be escaped for HTML (because it might contain chars such as "&" or "<"). Set to False if #msg contains HTML. """ if not msg: return "" if escapeForHtml: msgH = butil.htmlEsc(msg) else: msgH = msg h = form("<div class='message-box'>" "{msg}</div>", msg=msgH) return h
def wikiIndex(u: str): """ display a list of all the pages in a wiki @param u = user id """ wps = wikidb.getWikiPages(u) wikiIndexH = "" for wp in wps: wikiIndexH += form("<br>{a}\n", a=wp.a()) #//for tem = jinjaEnv.get_template("wikiIndex.html") h = tem.render( userName=htmlEsc(u), nav=wikiNav(u), wikiIndexH=wikiIndexH, ) return h
def answerChoiceRB(qid: str, ansClass: str, ansVal: str, ansText: str) -> str: """ return html for a radio button for an answer to a question. qid = question ID ansClass = CSS class for this answer ansVal = value for answer in the database ansText = value for answer to be displayed """ h = form("""\ <input type=radio id="{qid}" name="{qid}" value="{ansVal}"> <span class='answer {ansClass}'> <tt>[{ansVal}]</tt> {ans} </span><br> """, qid=htmlEsc(qid), ansClass=ansClass, ansVal=htmlEsc(ansVal), ans=htmlEsc(ansText)) return h
def getResultTable(th: TheTestForm) -> str: """ return an html table with the contents of (tf) """ h = """<table class='bz-report-table'> <tr> <th colspan=3>Field</th> <th colspan=3>Value</th> </tr> <tr> <th>Py Name</th> <th>Screen Name</th> <th>Type</th> <th>Py Value</th> <th>Screen Value</th> <th>Type</th> </tr> """ for fn in th.fieldNames(): fi = th.getFieldInfo(fn) cn = fi.__class__.__name__ v = th[fn] h += form( """<tr> <td><code>{fn}</code></td> <td><b>{screenName}</b></td> <td><tt>{type}</tt></td> <td><code>{r}</code></td> <td>{s}</td> <td><tt>{vt}</tt></td> <tr>""", screenName=fi.title, fn=fn, type=cn, s=th.asReadableH(fn), r=htmlEsc(repr(v)), vt=htmlEsc(v.__class__.__name__), ) #//for h += "</table>" return h
def userInfoLine(id: str) -> str: """ Return an HTML line (<tr>) for one user. """ ai = models.getAccountInfo(id) numPosts = models.Message.count({'author_id': id}) numHeadPosts = models.Message.count({ 'author_id': id, 'replyTo_id': { '$in': [None, ''] }, }) numFollowing = len(ai.following_ids) numFollowers = models.AccountInfo.count({'following_ids': id}) h = form( """<tr> <td><a href='/blog/{user}'>@{user}</a></td> <td style='text-align:right;'>{numPosts}</td> <td style='text-align:right;'>{numHeadPosts}</td> <td style='text-align:right;'> <a href='/listFollowing/{user}'>{numFollowing}</a> <a href='/followingMess/{user}'><i class='fa fa-eye'></i></a></td> <td style='text-align:right;'> <a href='/listFollowers/{user}'>{numFollowers}</a> <a href='/followerMess/{user}'> <i class='fa fa-arrow-circle-left'></i></a></td> <td>{realName}</td> <td>{title}</td> </tr>""", user=id, numPosts=numPosts, numHeadPosts=numHeadPosts, numFollowing=numFollowing, numFollowers=numFollowers, realName=ai.asReadableH('realName'), title=ai.asReadableH('title'), ) return h
def getPartyLegend(partyStrengths) -> str: """ return HTML to go at the top of the chart showing parties, in order of their trend strength, with percentage and color. """ # sort, largest 1st ps2 = sorted(partyStrengths, key=lambda ps: ps['strength'])[::-1] dpr("ps2=%r", ps2) h = "" for ps in ps2: dpr("ps=%r", ps) name = ps['name'] color = ps['color'] strength = ps['strength'] h += form("""<span style='color:{color}'> {strength:.1f}% {name}</span> """, color = color, strength = strength, name = name) #//for dpr("h=%s", h) return h
def gbPartyTable() -> str: h = """<table class='bz-report-table'> <tr> <th>Abbrev</th> <th>Party<br>Name</th> <th>% Vote,<br>2014</th> <th>Seats,<br>2014</th> <th>Regions</th> <th>Remain<br>in EU?</th> <th>Notes</th> </tr> """ totSeats = 0 ps = sorted(party.Party.all(), key=lambda p: p.ix) for p in ps: h += form( """<tr> <td>{a}</td> <td>{longName}</td> <td style='text-align:right'>{votes14:.1f}</td> <td style='text-align:right'>{seats14}</td> <td>{regs}</td> <td>{isRemain}</td> <td></td> </tr>""", a=p.a(), col=p.col, longName=p.getLongNameH(), votes14=p.votes14, seats14=p.seats14, regs=p.regs, isRemain=boolH(p.isRemain), ) #//for p h += "</table>" return h
def foosTable(pag: paginate.Paginator) -> str: """ a table of foos """ h = """<table class='bz-report-table'> <tr> <th>Id</th> <th>Name</th> <th>Description</th> <th>Favourite<br>Drink</th> <th>Fruits<br>Liked</th> <th>Ticky<br>Box</th> </tr> """ fs = Foo.find( skip=pag.skip, # skip this number of docs before returning some limit=pag.numShow, # max number of docs to return sort='name') for f in fs: h += form( """<tr> <td style='background:#fed'><tt>{id}</tt></td> <td>{name}</td> <td>{description}</td> <td>{favouriteDrink}</td> <td>{fruitsLiked}</td> <td>{tickyBox}</td> </tr>""", id=htmlEsc(f.id()), name=f.a(), description=f.asReadableH('description'), favouriteDrink=f.asReadableH('favouriteDrink'), fruitsLiked=f.asReadableH('fruitsLiked'), tickyBox=f.asReadableH('tickyBox'), ) #//for f h += "</table>" return h