def wrapTestUsers(self): """Present a widget to select a test user for login. !!! caution In production this will do nothing. Only in development mode one can select a test user. """ if not self.isDevel: return E db = self.db testUsers = { record[N.eppn]: record for record in db.user.values() if N.eppn in record and G(record, N.authority) == N.local } return H.join( [ H.div(H.a(u, href=f"/login?eppn={u}", cls="button small")) for u in testUsers ] + [ H.div( H.input( E, placeholder="email", onchange="window.location.href=`/login?email=${this.value}`", ) ) ] )
def tasks(self, table, kind=None): """Present the currently available tasks as buttons on the interface. !!! hint "easy comments" We also include a comment `<!-- task~!taskName:eid --> for the ease of testing. Parameters ---------- table: string We must specify the table for which we want to present the tasks: contrib, assessment, or review. kind: string {`expert`, `final`}, optional `None` Only if we want review attributes Returns ------- string(html) """ uid = self.uid if not uid or table not in USER_TABLES: return E eid = list(self.info(table, N._id, kind=kind))[0] taskParts = [] allowedTasks = sorted((task, taskInfo) for (task, taskInfo) in TASKS.items() if G(taskInfo, N.table) == table) justNow = now() for (task, taskInfo) in allowedTasks: permitted = self.permission(task, kind=kind) if not permitted: continue remaining = type(permitted) is timedelta and permitted taskUntil = E if remaining: remainingRep = datetime.toDisplay(justNow + remaining) taskUntil = H.span(f""" before {remainingRep}""", cls="datex") taskMsg = G(taskInfo, N.msg) taskCls = G(taskInfo, N.cls) taskPart = (H.a( [taskMsg, taskUntil], f"""/api/task/{task}/{eid}""", cls=f"large task {taskCls}", ) + f"""<!-- task!{task}:{eid} -->""") taskParts.append(taskPart) return H.join(taskParts)
def title( self, record=None, eid=None, markup=False, active=None, ): """Generate a title for a rlated record. Parameters ---------- record: dict, optional `None` The record for which to generate a title. eid: ObjectId, optional `None` If `record` is not passed, use this to retrieve the full record. markup: boolean If true, generate the title in HTML markup, otherwise as a plain string. active: ObjectId, optional `None` If passed, is is the id of the currently *active* record, the one that the current user is interacting with. Returns ------- string(html) """ if record is None and eid is None: return (QQ, QQ) if markup else Qq table = self.name if record is None: context = self.context record = context.getItem(table, eid) titleStr = self.titleStr(record) titleHint = self.titleHint(record) if markup: if eid is None: eid = G(record, N._id) inActualCls = self.inActualCls(record) atts = dict(cls=f"tag medium {inActualCls}") if titleHint: atts[N.title] = titleHint href = f"""/{table}/item/{eid}""" titleFormatted = H.a(titleStr, href, target=N._blank, **atts) return (titleStr, titleFormatted) else: return titleStr
def makeEntry(self, label, path, withOptions=False, asTask=False): """Produce an entry. !!! hint "easy comments" We also include a comment `<!-- caption^label --> for the ease of testing. Parameters ---------- label: string The text of the entry path: url The destination after the entry is clicked. withOptions: boolean, optional `False` Whether to include the options widget. asTask: boolean, optional `False` Display the entry as a big workflow task button or as a modest hyperlink. Returns ------- path: url The url that corresponds to this entry string(html) The wrapped entry """ options = self.options active = path == self.path task = "task info" if asTask else "button" navClass = f"{task} small nav" + (" active" if active else E) optionsRep = (AMP.join( f"""{name}={value}""" for (name, value) in options.items()) if withOptions else E) if optionsRep: optionSep = AMP if Q in path else Q optionsRep = optionSep + optionsRep atts = dict(cls=navClass, ) if withOptions: atts[N.hrefbase] = path comment = f"""<!-- caption^{label} -->""" return ( path, comment + H.a(label, path + optionsRep, **atts), )
def insertButton(self): """Present an insert button on the interface. Only if the user has rights to insert new items in this table. """ mayInsert = self.mayInsert if not mayInsert: return E table = self.table itemSingle = self.itemLabels[0] return H.a( f"""New {itemSingle}""", f"""/api/{table}/{N.insert}""", cls="small task info", )
def wrap(self): """Wrap it all up.""" context = self.context auth = context.auth eppn = G(auth.user, N.eppn) if auth.authenticated() else N.public eppnRep = H.span(eppn, cls="mono") (identityRep, accessRep) = auth.credentials() login = (E if auth.authenticated() else ( auth.wrapTestUsers() if auth.isDevel else H. a(G(LOGIN, N.text), G(LOGIN, N.url), cls="button small loginout"))) logout = (H.join([ H.a(G(LOGOUT, N.text), G(LOGOUT, N.url), cls="button small loginout"), H.a( G(SLOGOUT, N.text), G(SLOGOUT, N.url), cls="button small loginout", title=G(SLOGOUT, N.title), ), ]) if auth.authenticated() else E) techdoc = (H.a( G(TECH, N.text), G(TECH, N.url), target=N._blank, cls="button medium help", title=G(TECH, N.title), )) userhelp = (H.a( G(HELP, N.text), G(HELP, N.url), target=N._blank, cls="button medium help", title=G(HELP, N.title), )) return H.div( [ H.div( [ H.icon(N.devel) if auth.isDevel else E, H.details(identityRep, eppnRep, "usereppn", cls="user"), H.div(accessRep, cls="access"), login, logout, ], cls="headlinestart", ), H.div( [ techdoc, userhelp, ], cls="headlineend", ), H.img( G(LOGO, N.src), href=G(LOGO, N.url), target=N._blank, title=G(LOGO, N.text), imgAtts=dict(height=G(LOGO, N.height)), id="logo", ), ], cls="headline", )