def role_index(): data = [] classes = set() # Collect all models and roles in the default render registry for (cls, __) in html.registry: if not issubclass(cls, Model) or cls in classes: continue classes.add(cls) name = cls.__name__ href = reverse("role-model", kwargs={"model": name.lower()}) data.append((name, span([a(name, href=href), ": " + get_doc(cls)]))) # Now we collect the queryset renderers classes = set() for (cls, __) in register_queryset.registry: classes.add(cls) name = cls.__name__ href = reverse("role-model-queryset", kwargs={"model": name.lower()}) data.append([ name + " (queryset)", span([a(name, href=href), ": " + get_doc(cls)]) ]) return {"data": html_map(data)}
def role_index(): data = [] classes = set() # Collect all models and roles in the default render registry for (cls, __) in render.registry: if not issubclass(cls, Model) or cls in classes: continue classes.add(cls) name = cls.__name__ href = reverse('role-model', kwargs={'model': name.lower()}) data.append((name, span([a(name, href=href), ': ' + cls.__doc__]))) # Now we collect the queryset renderers classes = set() for (cls, __) in register_queryset.registry: classes.add(cls) name = cls.__name__ href = reverse('role-model-queryset', kwargs={'model': name.lower()}) data.append([ name + ' (queryset)', span([a(name, href=href), ': ' + cls.__doc__]), ]) return {'data': html_map(data)}
def _detail_links(request, conversation): if request.user.has_perm("ej.can_edit_conversation", conversation): return [ a(_("Edit groups"), href=conversation.url("cluster:edit")), a(_("Manage personas"), href=conversation.url("cluster:stereotype-votes")), ] else: return []
def conversation_admin_menu_links(conversation, user): """ Return administrative links to the conversation menu. """ menu_links = [] if user.has_perm("ej.can_edit_conversation", conversation): url = conversation.url("conversation:edit") menu_links.append(a(_("Edit"), href=url)) if user.has_perm("ej.can_moderate_conversation", conversation): url = conversation.url("conversation:moderate") menu_links.append(a(_("Moderate"), href=url)) return menu_links
def link(value, href='#', target='.Page-mainContainer', class_=(), action='target', instant=True, button=False, transition='cross-fade', preload=False, scroll=False, prefetch=False, primary=False, args=None): classes = [*class_] if button: classes.append('Button') kwargs = { 'href': href, 'class': classes, 'primary': primary, 'up-instant': instant, 'up-restore-scroll': scroll, 'up-preload': preload, 'up-prefetch': prefetch, } if action: kwargs[f'up-{action}'] = target if transition: kwargs['up-transition'] = transition if args: for arg in args.split(): kwargs[arg] = True return a(kwargs, value)
def conversation_comment_form( conversation, request=None, content=None, user=None, form=None, target=None ): """ Render comment form for conversation. """ # Check user credentials user = user or getattr(request, "user", None) if not user.is_authenticated: conversation_url = conversation.get_absolute_url() login = reverse("auth:login") return { "user": None, "login_anchor": a(_("login"), href=f"{login}?next={conversation_url}"), } # Check if user still have comments left n_comments = rules.compute("ej.remaining_comments", conversation, user) if conversation.author != user and n_comments <= 0: return {"comments_exceeded": True, "user": user} # Everything is ok, proceed ;) return { "user": user, "csrf_input": csrf_input(request), "n_comments": n_comments, "content": content, "target": target or "main", "form": form or forms.CommentForm(request=request, conversation=conversation), }
def index(request, conversation, slug, check=check_promoted): check(conversation, request) user = request.user clusterization = getattr(conversation, 'clusterization', None) if clusterization and clusterization.clusters.count() == 0: clusterization = None if clusterization is None: clusters = () shapes_json = None else: clusters = (clusterization.clusters.annotate( size=Count(F.users)).annotate_attr( separated_comments=lambda c: c.separate_comments()). prefetch_related("stereotypes")) shapes = cluster_shapes(clusterization, clusters, user) shapes_json = json.dumps({"shapes": list(shapes.values())}) can_edit = user.has_perm("ej.can_edit_conversation", conversation) return { "conversation": conversation, "clusters": clusters, "groups": {cluster.name: f"#cluster-{cluster.id}" for cluster in clusters}, "has_edit_perm": can_edit, "edit_link": a(_("here"), href=conversation.url("cluster:edit")), "json_data": shapes_json, }
def comment_card( comment: Comment, request=None, target=None, show_actions=None, **kwargs ): """ Render comment information inside a comment card. """ user = getattr(request, "user", None) is_authenticated = getattr(user, "is_authenticated", False) if is_authenticated: login_anchor = None else: login = reverse("auth:login") login_anchor = a( _("login"), href=f"{login}?next={comment.conversation.get_absolute_url()}" ) buttons = { "disagree": ("fa-times", "text-negative", _("Disagree")), "skip": ("fa-arrow-right", "text-black", _("Skip")), "agree": ("fa-check", "text-positive", _("Agree")), } return { "author": comment.author.username, "comment": comment, "show_actions": is_authenticated, "csrf_input": csrf_input(request), "buttons": buttons, "login_anchor": login_anchor, "target": target, **kwargs, }
def link_tag(self, classes=(), icon_classes=()): """ Render an anchor tag with the link for the social network. >>> print(icon.link_tag(classes=['header-icon'])) # doctest: +SKIP <a href="url"><i class="fa fa-icon header-icon"></i></a> """ return a(href=self.url, class_=classes)[self.icon_tag(icon_classes)]
def anchor(self, name, **kwargs): """ Return an Hyperpython anchor object using url as href. It must pass the anchor contents as the first argument. It also accepts a additional attributes as keyword arguments. """ return a(name, href=self.url, **kwargs)
def role_model_list(request, model, role): cls = get_class(model) kwargs = query_to_kwargs(request) size = kwargs.pop("size", 10) data = [] for idx, obj in enumerate(cls.objects.all()[:size], 1): link = reverse("role-model-instance", kwargs={"model": model, "role": role, "id": obj.id}) key = span([f"{idx}) ", a(str(obj), href=link)]) data.append((key, html(obj, role, **kwargs))) return {"data": html_map(data)}
def role_model(model): links = [] cls = get_class(model) for role in get_roles(cls): href = reverse("role-model-list", kwargs={"model": model, "role": role}) links.append(a(role, href=href)) if not links: raise Http404 else: return {"data": div([h1(_("List of roles")), html_list(links)])}
def role_model_list(request, model, role): cls = get_class(model) kwargs = query_to_kwargs(request) size = kwargs.pop('size', 10) data = [] for idx, obj in enumerate(cls.objects.all()[:size], 1): link = reverse('role-model-instance', kwargs={'model': model, 'role': role, 'id': obj.id}) key = span([f'{idx}) ', a(str(obj), href=link)]) data.append((key, html(obj, role, **kwargs))) return {'data': html_map(data)}
def stereotype_list(conversation): base_href = f'{conversation.get_absolute_url()}stereotypes/' return { 'content_title': _('Stereotypes'), 'conversation': conversation, 'stereotypes': html_list( a(str(stereotype), href=f'{base_href}{stereotype.id}/') for stereotype in conversation.stereotypes.all()), }
def role_model(model): links = [] cls = get_class(model) for role in get_roles(cls): href = reverse('role-model-list', kwargs={'model': model, 'role': role}) links.append(a(role, href=href)) if not links: raise Http404 else: return {'data': div([h1(_('List of roles')), html_list(links)])}
def index(request, conversation, slug, check=check_promoted): check(conversation, request) user = request.user clusterization = getattr(conversation, "clusterization", None) user_group = None if clusterization and clusterization.clusters.count() == 0: clusterization = None if clusterization is None: clusters = () shapes_json = None else: try: clusters = (clusterization.clusters.annotate( size=Count(F.users)).annotate_attr( separated_comments=lambda c: c.separate_comments()). prefetch_related("stereotypes")) shapes = cluster_shapes(clusterization, clusters, user) shapes_json = json.dumps({"shapes": list(shapes.values())}) except Exception as exc: exc_name = exc.__class__.__name__ log.error(f"Error found during clusterization: {exc} ({exc_name})") clusters = () shapes_json = { "shapes": [{ "name": _("Error"), "size": 0, "intersections": [[0.0]] }] } else: names = list( clusterization.clusters.filter(users=user).values_list( "name", flat=True)) print(names) if names: user_group = names[0] can_edit = user.has_perm("ej.can_edit_conversation", conversation) return { "conversation": conversation, "clusters": clusters, "groups": {cluster.name: f"#cluster-{cluster.id}" for cluster in clusters}, "has_edit_perm": can_edit, "edit_link": a(_("here"), href=conversation.url("cluster:edit")), "json_data": shapes_json, "user_group": user_group, }
def button( text, *, href=None, submit=False, reset=False, form=False, outline=False, clear=False, **kwargs, ): """ A styled button element. Args: text (str or HTML element): Text content of the button. href (str): Optional hyperlink target. If given, the button is create as an anchor tag. submit (bool): If True, renders element as an <input type='submit'> element. reset (bool): If True, renders element as an <input type='reset'> element. form (bool): If True, renders element as an <input type='button'> element. outline (bool): If True, paints only the outline. clear: If True, renders a plain-text button with no background color or outline. ``button`` also accepts additional HTML attributes as keyword arguments. """ classes = ["button"] if clear: classes.append("button-clear") if outline: classes.append("button-outline") if href: return hp.a(text, href=href, **kwargs).add_class(classes) elif submit or reset or form: if not isinstance(text, (str, int, float)): raise ValueError("submit inputs do not accept rich element children.") kind = "submit" if submit else "reset" if reset else "button" return hp.input_(value=text, type=kind, **kwargs).add_class(classes) else: return hp.button(text, **kwargs).add_class(classes)
def tabs(items, select=0, js=True, **kwargs): """ Return a tabbed interface. """ items = items.items() if isinstance(items, Mapping) else items children = [] if js: kwargs["is-component"] = True for idx, (k, v) in enumerate(items): args = {"href": v} if isinstance(v, str) else v anchor = a(args, k, is_selected=select == idx) children.append(anchor) return div(children, **kwargs).add_class("tabs", first=True)
def comment_form(conversation, request=None, comment_content=None, **kwargs): """ Render comment form for one conversation. """ user = getattr(request, 'user', None) n_comments = rules.compute('ej_conversations.remaining_comments', conversation, user) conversation_url = conversation.get_absolute_url() login = reverse('auth:login') login_anchor = a(_('login'), href=f'{login}?next={conversation_url}') return { 'can_comment': user.is_authenticated, 'comments_left': n_comments, 'user_is_owner': conversation.author == user, 'csrf_input': csrf_input(request), 'comment_content': comment_content, 'login_anchor': login_anchor, }
def link(value, href='#', target='.Page-mainContainer .Header-topIcon', action='target', instant=True, button=False, transition='cross-fade', preload=False, scroll=False, prefetch=False, primary=False, args=None, query=None, url_args=None, **kwargs): if href.startswith('/'): # raise ValueError(href) warnings.warn( 'Do not use absolute urls in the link function (%s).' 'Prefer using view function names such as auth:login instead of ' '/login/' % href) else: href = reverse(href, kwargs=url_args) if query is not None: query = '&'.join(f'{k}={v}' for k, v in query.items()) href = f'{href}?{query}' kwargs = { 'href': href, 'primary': primary, 'up-instant': instant, 'up-restore-scroll': scroll, 'up-preload': preload, 'up-prefetch': prefetch, **kwargs, } if action: kwargs[f'up-{action}'] = target if transition: kwargs['up-transition'] = transition if args: for arg in args.split(): kwargs[arg] = True elem = a(kwargs, value) return elem.add_class('Button') if button else elem
def detail(request, conversation, owner=None): user = request.user comment = conversation.next_comment(user, None) n_comments = rules.compute('ej_conversations.remaining_comments', conversation, user) favorites = FavoriteConversation.objects.filter(conversation=conversation) ctx = { 'conversation': conversation, 'comment': comment, 'owner': owner, 'edit_perm': user.has_perm('ej_conversations.can_edit_conversation', conversation), 'can_comment': user.has_perm('ej_conversations.can_comment', conversation), 'remaining_comments': n_comments, 'login_link': a(_('login'), href=reverse('auth:login')), 'favorites': favorites, } if comment and request.POST.get('action') == 'vote': vote = request.POST['vote'] if vote not in {'agree', 'skip', 'disagree'}: return HttpResponseServerError('invalid parameter') comment.vote(user, vote) elif request.POST.get('action') == 'comment': comment = request.POST['comment'].strip() # FIXME: do not hardcode this and use a proper form! comment = comment[:210] try: ctx['comment'] = conversation.create_comment(user, comment) except (PermissionError, ValidationError) as ex: ctx['comment_error'] = str(ex) elif request.POST.get('action') == 'favorite': conversation.toggle_favorite(user) return ctx
def cluster_info(cluster): stereotypes = cluster.stereotypes.all() user_data = [(user.username, user.name) for user in cluster.users.all()] return { 'size': cluster.users.count(), 'stereotypes': stereotypes, 'stereotype_links': [ a(str(stereotype), href=reverse('cluster:stereotype-vote', kwargs={ 'conversation': cluster.conversation, 'stereotype': stereotype, })) for stereotype in stereotypes ], 'users': html_table(user_data, columns=[_('Username'), _('Name')]) }
def categories(items, select=0, js=True, **kwargs): """ Similar to tabs, but display several categories for the user to select. """ items = items.items() if isinstance(items, Mapping) else items children = [ icon("chevron-left", class_="categories__left", is_element="leftArrow:click") ] if js: kwargs["is-component"] = True for idx, (k, v) in enumerate(items): args = {"href": v} if isinstance(v, str) else v if select == idx or select == v: args["is-selected"] = True children.append(a(args, k)) children.append( icon("chevron-right", class_="categories_right", is_element="rightArrow:click") ) return div(children, **kwargs).add_class("categories", first=True)
def link(value, href='#', target='.Page-mainContainer .Header-topIcon', action='target', instant=True, button=False, transition='cross-fade', preload=False, scroll=False, prefetch=False, primary=False, args=None, **kwargs): kwargs = { 'href': href, 'primary': primary, 'up-instant': instant, 'up-restore-scroll': scroll, 'up-preload': preload, 'up-prefetch': prefetch, **kwargs, } if action: kwargs[f'up-{action}'] = target if transition: kwargs['up-transition'] = transition if args: for arg in args.split(): kwargs[arg] = True elem = a(kwargs, value) return elem.add_class('Button') if button else elem
def comment_card(comment, request=None, **kwargs): """ Render comment information inside a comment card. """ user = getattr(request, 'user', None) is_authenticated = getattr(user, 'is_authenticated', False) total = comment.conversation.approved_comments.count() remaining = total - comment.conversation.user_votes(user).count() voted = total - remaining + 1 login = reverse('auth:login') comment_url = comment.conversation.get_absolute_url() login_anchor = a(_('login'), href=f'{login}?next={comment_url}') return { 'comment': comment, 'total': total, 'voted': voted, 'show_user_actions': is_authenticated, 'csrf_input': csrf_input(request), 'login_anchor': login_anchor, **kwargs, }
def login_link(content, obj): path = obj.get_absolute_url() return a(content, href=reverse('auth:login') + f'?next={path}')
def _tab_anchors(items, select): items = items.items() if isinstance(items, Mapping) else items for idx, (k, v) in enumerate(items): args = {"href": v} if isinstance(v, str) else v args.update(role="tab", tabindex=0, is_selected=select == idx) yield a(k, **args)
(which can be None) pertaining to that section. Ex.: in a route that configures the user profile, that object can be the profile object for the request user. """ return lambda f: MENU_FUNCTIONS[section].append(f) or f # Storage MENU_FUNCTIONS = defaultdict(list) #: Accessibility menu page_menu.ACCESSIBILITY = thunk(lambda: menu_section( _("Accessibility"), [ a([fa_icon("text-height"), _("Toggle Font Size")], href="#", is_element="toggleFontSize"), a([fa_icon("adjust"), _("Toggle Contrast")], href="#", is_element="toggleContrast"), ], )) #: About menu page_menu._ABOUT = thunk(lambda: menu_section( _("About"), [ link(_("About"), href="about-us"), link(_("Frequently Asked Questions"), href="faq"), link(_("Usage terms"), href="usage"), ],
def a(self): return a(class_='cls', href='url')['click me']
def a(self): return a(class_='cls1 cls2', id='id', href='url')['click me']