def _make_taglist(self): """Build a list of selected widget options to be displayed as a list of 'tags' below the widget.""" try: db = current.db classes = "taglist" if self.sortable: classes += " sortable" taglist = UL(_class=classes) if self.value: for v in self.value: the_row = db(db[self.linktable].id == v).select().first() fmt = db[self.linktable]._format format_string = fmt(the_row) if callable(fmt) else fmt % the_row listitem = LI(SPAN(format_string, _id=v, _class="label label-info"), _id=v, _class="tag") listitem.append( A( SPAN(_class="glyphicon glyphicon-remove"), _href="#", _class="tag tag_remover " "label label-warning", ) ) taglist.append(listitem) else: pass except Exception: print traceback.format_exc(5) return taglist
def _make_taglist(self): """Build a list of selected widget options to be displayed as a list of 'tags' below the widget.""" try: db = current.db classes = 'taglist' if self.sortable: classes += ' sortable' taglist = UL(_class=classes) if self.value: for v in self.value: the_row = db(db[self.linktable].id == v).select().first() fmt = db[self.linktable]._format format_string = fmt(the_row) if callable(fmt) \ else fmt % the_row listitem = LI(SPAN(format_string, _id=v, _class='label label-info'), _id=v, _class='tag') listitem.append( A(SPAN(_class='glyphicon glyphicon-remove'), _href='#', _class='tag tag_remover label label-warning')) taglist.append(listitem) else: pass except Exception: print(traceback.format_exc(5)) return taglist
def xml(self): from gluon import current pages, rem = divmod(self.records, self.items_per_page) li = [] if rem: pages += 1 if self.page > 0: li.append( LI( A(XML('<i class="glyphicon glyphicon-fast-backward"></i>'), _href=URL(args=current.request.args, vars=dict(page=0))))) else: li.append( LI(A(XML('<i class="glyphicon glyphicon-fast-backward"></i>'), _href="#"), _class="disabled")) if self.page >= 1: li.append( LI( A(XML('<i class="glyphicon glyphicon-backward"></i>'), _href=URL(args=current.request.args, vars=dict(page=self.page - 1))))) else: li.append( LI(A(XML('<i class="glyphicon glyphicon-backward"></i>'), _href="#"), _class="disabled")) li.append( LI(A( XML('<i class="glyphicon glyphicon-file"></i>Página %s de %s' % (self.page + 1, int(self.records / self.items_per_page) + 1))), _class="disabled")) if self.page <= pages - 2: li.append( LI(A(XML('<i class="glyphicon glyphicon-forward"></i>'), _href=URL(args=current.request.args, vars=dict(page=self.page + 1))), _class="next")) else: li.append( LI(A(XML('<i class="glyphicon glyphicon-forward"></i>'), _href="#"), _class="disabled")) if self.page < pages - 1: li.append( LI( A(XML('<i class="glyphicon glyphicon-fast-forward"></i>'), _href=URL(args=current.request.args, vars=dict(page=pages - 1))))) else: li.append( LI(A(XML('<i class="glyphicon glyphicon-fast-forward"></i>'), _href="#"), _class="disabled")) div = DIV(UL(li, _class="pagination pagination-sm")) return DIV.xml(div)
def pager(db): """ Return a row DIV for a pager. """ from gluon import current # Previous/current/next page. if current.request.args(0): current_page = int(current.request.args(0)) else: current_page = 1 prev_page = current_page - 1 next_page = current_page + 1 # List of LI. pages = [] # Previous/left. li_class = '' href = URL('poems', 'page', args=[str(prev_page)]) if prev_page < 1: li_class = 'disabled' href = '#' elif prev_page == 1: href = URL('poems', 'index') span = SPAN(xmlescape(u'\u4e0a'), **{'_aria-hidden': 'true'}) anchor = A(span, _href=href, **{'_aria-label': 'Previous'}) pages.append(LI(anchor, _class=li_class, _title='Previous Page')) # Chapter range links. for page in range(1, 10): li_class = '' href = URL('poems', 'page', args=[str(page)]) page_range = ['%d-%d' % (((page - 1) * 9) + 1, page * 9)] if page == 1: href = URL('poems', 'index') if page == current_page: li_class = 'active' page_range.append(SPAN('(current)', _class='sr-only')) anchor = A(page_range, _href=href) pages.append(LI(anchor, _class=li_class)) # Next/right. li_class = '' href = URL('poems', 'page', args=[str(next_page)]) if next_page > 9: li_class = 'disabled' href = '#' span = SPAN(xmlescape(u'\u4e0b'), **{'_aria-hidden': 'true'}) anchor = A(span, _href=href, **{'_aria-label': 'Next'}) pages.append(LI(anchor, _class=li_class, _title='Next Page')) # Together. return UL(pages, _class='pagination')
def related_articles(self): from helpers.article import related_articles related_articles = related_articles(self.db, self.context.article.tags, self.context.article.category_id, self.context.article.id) if related_articles: self.context.related_articles = UL( *[ LI( DIV( IMG(_src=self.get_image( related.thumbnail, related.content_type_id.identifier), _width=120)), A(related.title, _href=self.CURL('article', 'show', args=[related.id, related.slug])), **{ '_data-url': self.CURL('article', 'show', args=[related.id, related.slug]) }) for related in related_articles ], **dict(_class="related-articles")) else: self.context.related_articles = False
def render_list(self, value, labels, show_link=True): """ Helper method to render list-type representations from bulk()-results. @param value: the list @param labels: the labels as returned from bulk() @param show_link: render references as links, should be the same as used with bulk() """ show_link = show_link and self.show_link values = [v for v in value if v is not None] if not len(values): return "" if show_link: labels_ = (labels[v] if v in labels else self.default for v in values) else: labels_ = sorted( s3_str(labels[v]) if v in labels else self.default for v in values) if current.auth.permission.format == "xls": return ", ".join(labels_) html = UL(_class="service-list") for label in labels_: html.append(LI(label)) return html
def layout(item): """ Layout Method (Item Renderer) """ if item.parent is not None: return LI(_class="divider hide-for-small") else: return None
def layout(item): if item.parent is None: items = item.render_components() return DIV(UL(items), _class='breadcrumbs') else: if item.is_last(): _class = "highlight" else: _class = "ancestor" return LI(A(item.label, _href=item.url(), _class=_class))
def _make_linklist(self): """ Build a list of selected widget options to be displayed as a list of 'tags' below the widget. """ db = current.db xclasses = " sortable" if self.sortable else "" ll = UL(_class="taglist editlist {}".format(xclasses)) # append the currently selected items to the list if self.value: for v in listcheck(self.value): myrow = db(db[self.linktable].id == v).select().first() if myrow is None: continue try: fmt = db[self.linktable]._format formatted = fmt(myrow) if callable(fmt) else fmt % myrow except TypeError: formatted = myrow[1] linkargs = self.uargs[:] # new obj so vals don't pile up linkargs.append(v) ln = LI(SPAN(formatted, _class="badge badge-info"), _id=v, _class="editlink tag") myargs = self.uargs[:] myargs.append(v) elink = MODAL( SPAN(_class="glyphicon glyphicon-edit"), "Edit {} item {}".format(self.linktable, v), LOAD("plugin_ajaxselect", "linked_edit_form.load", args=myargs, vars=self.uvars, ajax=True), trigger_classes="linklist_edit_trigger badge badge-warning ", trigger_type="link", modal_classes="plugin_ajaxselect modal_linklist_edit", id="{}_{}".format(self.linktable, v), ) ln.append(elink) ln.append( A(SPAN(_class="glyphicon glyphicon-remove"), _class="tag tag_remover " "label label-important") ) ll.append(ln) return ll
def serialize(self, data, level=0): if level == 0: ul = UL(**self.attributes) else: ul = UL(_class=self['ul_class']) for item in data: if isinstance(item, LI): ul.append(item) else: (name, active, link) = item[:3] if isinstance(link, DIV): li = LI(link) elif 'no_link_url' in self.attributes and self['no_link_url'] == link: li = LI(DIV(name)) elif isinstance(link, dict): li = LI(A(name, **link)) elif link: li = LI(A(name, _href=link)) elif not link and isinstance(name, A): li = LI(name) else: li = LI(A(name, _href='#', _onclick='javascript:void(0);return false;')) if level == 0 and item == data[0]: li['_class'] = self['li_first'] elif level == 0 and item == data[-1]: li['_class'] = self['li_last'] if len(item) > 3 and item[3]: li['_class'] = self['li_class'] li.append(self.serialize(item[3], level + 1)) if active or ('active_url' in self.attributes and self['active_url'] == link): if li['_class']: li['_class'] = li['_class'] + ' ' + self['li_active'] else: li['_class'] = self['li_active'] if len(item) <= 4: ul.append(li) else: if item[4] is False: li['_class'] = 'disabled' ul.append(li) return ul
def layout(item): if item.parent is None: # The menu items = item.render_components() if items: return UL(items, _class = "menu align-right", # https://get.foundation/sites/docs/menu.html ) else: return "" # menu is empty else: # A menu item if item.enabled and item.authorized: return LI(A(item.label, _href = item.url(), )) else: return None
def serialize(self, data, level=0): if level == 0: ul = UL(**self.attributes) else: ul = UL(_class=self['ul_class']) for item in data: if isinstance(item,LI): ul.append(item) else: (name, active, link) = item[:3] if isinstance(link, DIV): li = LI(link) elif 'no_link_url' in self.attributes and self['no_link_url'] == link: li = LI(DIV(name)) elif isinstance(link,dict): li = LI(A(name, **link)) elif link: li = LI(A(name, _href=link)) elif not link and isinstance(name, A): li = LI(name) else: li = LI(A(XML(" ".join(map(lambda s: "%s" %s,name)) ), B(_class="arrow fa fa-angle-down"), _href='#', _class=self['a_submenu_class'],)) if level == 0 and item == data[0]: li['_class'] = self['li_first'] elif level == 0 and item == data[-1]: li['_class'] = self['li_last'] if len(item) > 3 and item[3]: li['_class'] = self['li_class'] li.append(self.serialize(item[3], level + 1)) if active or ('active_url' in self.attributes and self['active_url'] == link): if li['_class']: li['_class'] = li['_class'] + ' ' + self['li_active'] else: li['_class'] = self['li_active'] if len(item) <= 4 or item[4] == True: ul.append(li) return ul
def TABS(tablist): ''' Returns a bootstrap 2.3.2 tabs widget in a web2py DIV() helper object. This function expects a single argument, a list of tuples. Each tuple represents a single tab in the tab set. The items in each tuple should contain: [0] (required) the tab label text (str) [1] (required) the id to be assigned to the tab content div (str) [2] (required) the content to be revealed by the tab (str or web2py html helper object). If a LOAD helper is the value provided here the content of the tab will be loaded via ajax at page load. [3] (optional) extra classes to be assigned to the content div (str). If a tab is to be selected by default when the page loads, this tab should be passed a string in this position that includes the class 'active'. There is currently no support for pill or pull-down styles of tabs. To make one tab the default, include 'active' in its class_string. ''' tabs = DIV(_class='tabbable') tabnav = UL(_class='nav nav-tabs') tabcontent = DIV(_class='tab-content') for tab in tablist: label = tab[0] div_id = tab[1] content = tab[2] class_string = tab[3] if len(tab) > 3 else ' ' # use dict because of hyphen in data-toggle a_args = {'_href': '#{}'.format(div_id), '_data-toggle': 'tab'} tabnav.append(LI(A(label, **a_args), _class=class_string)) wrapper = DIV(_id=div_id, _class="tab-pane {}".format(class_string)) wrapper.append(content) tabcontent.append(wrapper) tabs.append(tabnav) tabs.append(tabcontent) return tabs
def checkbox_item(item): """ Render special active items """ name = item.label link = item.url() _id = name["id"] if "name" in name: _name = name["name"] else: _name = "" if "value" in name: _value = name["value"] else: _value = False if "request_type" in name: _request_type = name["request_type"] else: _request_type = "ajax" if link: if _request_type == "ajax": _onchange='''var val=$('#%s:checked').length;$.getS3('%s'+'?val='+val,null,false,null,false,false)''' % \ (_id, link) else: # Just load the page. Use this if the changed menu # item should alter the contents of the page, and # it's simpler just to load it. _onchange = "location.href='%s'" % link else: _onchange = None return LI( A( INPUT( _type="checkbox", _id=_id, _onchange=_onchange, value=_value, ), "%s" % _name, _nowrap="nowrap", ), _class="menu-toggle", )
def make_linklist(self): """ Build a list of selected widget options to be displayed as a list of 'tags' below the widget. """ db = current.db xclasses = ' sortable' if self.sortable else '' ll = UL(_class='taglist editlist {}'.format(xclasses)) #append the currently selected items to the list if self.value: for v in listcheck(self.value): myrow = db(db[self.linktable].id == v).select().first() if myrow is None: continue try: fmt = db[self.linktable]._format formatted = fmt(myrow) if callable(fmt) else fmt % myrow except TypeError: formatted = myrow[1] linkargs = self.uargs[:] # new obj so vals don't pile up linkargs.append(v) ln = LI(SPAN(formatted, _class='badge badge-info'), _id=v, _class='editlink tag') myargs = self.uargs[:] print 'making linklist: self.uargs is', self.uargs myargs.append(v) print 'making linklist: myargs is ', myargs elink = MODAL( u'\u200B', 'Edit {} item {}'.format(self.linktable, v), LOAD('plugin_ajaxselect', 'linked_edit_form.load', args=myargs, vars=self.uvars, ajax=True), trigger_classes= 'linklist_edit_trigger badge badge-warning icon-edit', trigger_type='link', modal_classes='plugin_ajaxselect modal_linklist_edit', id='{}_{}'.format(self.linktable, v)) ln.append(elink) ln.append( A(u'\u200B', _class='tag tag_remover icon-remove ' 'label label-important')) ll.append(ln) return ll
def layout(item): if item.parent is None: # The menu items = item.render_components() if items: return UL( items, _class="menu about-menu", ) else: return "" # menu is empty else: # A menu item if item.enabled and item.authorized: return LI(A( item.label, _href=item.url(), )) else: return None
def cms_post_list_layout(list_id, item_id, resource, rfields, record): """ dataList item renderer for Posts on the Bulletin Board. @param list_id: the HTML ID of the list @param item_id: the HTML ID of the item @param resource: the S3Resource to render @param rfields: the S3ResourceFields to render @param record: the record as dict """ record_id = record["cms_post.id"] #item_class = "thumbnail" T = current.T db = current.db s3db = current.s3db settings = current.deployment_settings permit = current.auth.s3_has_permission raw = record._row date = record["cms_post.date"] title = record["cms_post.title"] body = record["cms_post.body"] #series_id = raw["cms_post.series_id"] # Allow records to be truncated # (not yet working for HTML) body = DIV( body, _class="s3-truncate", ) #if series_id: # series = record["cms_post.series_id"] # translate = settings.get_L10n_translate_cms_series() # if translate: # series_title = T(series) # else: # series_title = series #else: # series_title = series = "" #status = record["cms_post.status_id"] author_id = raw["cms_post.created_by"] person = record["cms_post.created_by"] # @ToDo: Bulk lookup ltable = s3db.pr_person_user ptable = db.pr_person query = (ltable.user_id == author_id) & \ (ltable.pe_id == ptable.pe_id) row = db(query).select(ptable.id, limitby=(0, 1)).first() if row: person_id = row.id else: person_id = None if person: if person_id: # @ToDo: deployment_setting for controller to use? person_url = URL(c="hrm", f="person", args=[person_id]) else: person_url = "#" person = A( person, _href=person_url, ) table = db.cms_post # Toolbar if permit("update", table, record_id=record_id): edit_btn = A( ICON("edit"), SPAN( "edit", _class="show-for-sr", ), _href=URL(c="cms", f="post", args=[record_id, "update.popup"], vars={ "refresh": list_id, "record": record_id }), _class="s3_modal", #_title=T("Edit %(type)s") % dict(type=series_title), _title=T("Edit"), ) else: edit_btn = "" if permit("delete", table, record_id=record_id): delete_btn = A( ICON("delete"), SPAN( "delete", _class="show-for-sr", ), _class="dl-item-delete", _title=T("Delete"), ) else: delete_btn = "" # Bookmarks auth = current.auth user = auth.user if user: #and settings.get_cms_bookmarks(): # @ToDo: Bulk lookup (via list_fields?) ltable = s3db.cms_post_user query = (ltable.post_id == record_id) & \ (ltable.user_id == user.id) exists = db(query).select(ltable.id, limitby=(0, 1)).first() if exists: bookmark = A( ICON("bookmark"), SPAN( "remove bookmark", _class="show-for-sr", ), _class="bookmark", _title=T("Remove Bookmark"), ) else: bookmark = A( ICON("bookmark-empty"), SPAN( "bookmark", _class="show-for-sr", ), _class="bookmark", _title=T("Add Bookmark"), ) bookmark["_data-c"] = "cms" bookmark["_data-f"] = "post" bookmark["_data-i"] = record_id else: bookmark = "" # Dropdown of available documents documents = raw["doc_document.file"] if documents: if not isinstance(documents, list): documents = (documents, ) doc_list = UL( _class="dropdown-menu", _role="menu", ) retrieve = db.doc_document.file.retrieve for doc in documents: try: doc_name = retrieve(doc)[0] except (IOError, TypeError): doc_name = current.messages["NONE"] doc_url = URL(c="default", f="download", args=[doc]) doc_item = LI( A( ICON("file"), " ", doc_name, _href=doc_url, ), _role="menuitem", ) doc_list.append(doc_item) docs = DIV( A(ICON("paper-clip"), SPAN(_class="caret"), _class="btn dropdown-toggle", _href="#", **{"_data-toggle": "dropdown"}), doc_list, _class="btn-group attachments dropdown pull-right", ) else: docs = "" #divider = LI("|") #divider["_aria-hidden"] = "true" toolbar = UL( #LI(share_btn, # _class="item", # ), #LI(A(ICON("flag"), # @ToDo: Use flag-alt if not flagged & flag if already flagged (like for bookmarks) # SPAN("flag this", # _class = "show-for-sr", # ), # _href="#", # _title=T("Flag"), # ), # _class="item", # ), LI( bookmark, _class="item", ), #LI(A(I(_class="fa fa-users", # ), # SPAN("make public", # _class = "show-for-sr", # ), # _href="#", # _title=T("Make Public"), # ), # _class="item", # ), LI( edit_btn, _class="item", ), LI( delete_btn, _class="item", ), _class="controls", ) # Tags #if settings.get_cms_show_tags(): tag_list = UL(_class="left inline-list s3-tags", ) tag_list["_data-post_id"] = record_id tags = raw["cms_tag.name"] if tags: if not isinstance(tags, list): tags = [tags] for tag in tags: tag_list.append(LI(A( tag, _href="#", ), )) # Comments comment_list = UL(_class="card-post-comments") cappend = comment_list.append #if settings.get_cms_comments(): # Add existing comments (oldest 1st) # - should sort by default by ID which is equivalent to oldest first, # however they seem to come in in a random order (even if orderby set on the component) so need to be sorted manually here comments = raw["cms_comment.json_dump"] ncomments = 0 if comments: if not isinstance(comments, list): comments = [comments] comments = [json.loads(comment) for comment in comments] comments.sort(key=lambda c: c["created_on"]) for comment in comments: author = s3_auth_user_represent(comment["created_by"]) cdate = dateutil.parser.parse(comment["created_on"]) ctime = cdate.time().strftime("%H:%M") cdate = cdate.date().strftime("%b %d, %Y") comment = LI(TAG["ASIDE"](P(T("Updated %(date)s @ %(time)s by %(author)s") % \ dict(date = cdate, time = ctime, author = author, ), _class="meta", ), DIV(comment["body"], _class="desc", ), # @ToDo: Show this if more than x chars? #TAG["FOOTER"](P(A(T("More Info"), # _class="more", # ) # ), # _class="footer", # ), _class="card-post-comment", )) cappend(comment) ncomments += 1 if ncomments == 1: num_comments = "1 Comment" else: num_comments = T("%(num)s Comments") % dict(num=ncomments) if user: add_comment = A( T("Add Comment"), _class="add-comment", ) add_comment["_data-l"] = list_id add_comment["_data-i"] = record_id add_comment = P(add_comment) comment_input = LI( TAG["ASIDE"]( TEXTAREA( _class="desc", _placeholder=T("comment here"), ), TAG["FOOTER"](P(A( "Submit Comment", _class="submit", ), ), ), _class="card-post-comment", ), _class="comment-form hide", ) cappend(comment_input) else: add_comment = "" item = TAG["ASIDE"]( TAG["HEADER"]( UL( # post priority icon LI(_class="item icon", ), # post type title #LI(series_title, # _class="item primary", # ), # post status #LI(status, # _class="item secondary border status", # ), # post visibility # @ToDo: Read the visibility #LI(T("Public"), # _class="item secondary border visibility", # ), _class="status-bar-left"), toolbar, _class="status-bar", ), DIV( DIV( SPAN( "Updated ", # @ToDo: i18n TAG["TIME"](date), " by ", person, _class="meta-update", ), SPAN( num_comments, _class="meta-comments", ), _class="meta", ), H4( title, _class="title", ), DIV( body, _class="desc", ), _class="body", ), docs, TAG["FOOTER"]( DIV( tag_list, _class= "tags clearfix", # @ToDo: remove clearfix and style via CSS ), comment_list, add_comment, _class="footer", ), _class="card-post", _id=item_id, ) return item
def layout(item): """ Layout Method (Item Renderer) """ # Manage flags: hide any disabled/unauthorized items if not item.authorized: enabled = False visible = False elif item.enabled is None or item.enabled: enabled = True visible = True if enabled and visible: if item.parent is not None: if item.enabled and item.authorized: attr = {"_id": item.attr._id} if item.attr._onclick: attr["_onclick"] = item.attr._onclick else: attr["_href"] = item.url() #if item.components: # # Submenu # items = item.render_components() # # Hide submenus which have no active links # if not items and not item.link: # return None # _class = "" # if item.parent.parent is None and item.selected: # _class = "active" # section = [LI(A(ICON(item.opts.icon), # " ", # SPAN(item.label), # **attr # ), # _class = "heading %s" % _class, # ), # ] # if items: # section.append(UL(items, # _class = "menu vertical nested", # https://get.foundation/sites/docs/menu.html # )) # return section #else: # Submenu item #if item.parent.parent is None: # _class = "heading" if item.selected: _class = "active" else: _class = "" return LI( A(ICON(item.opts.icon), " ", SPAN(item.label), **attr), _class=_class, ) else: # Main menu items = item.render_components() return NAV( UL( items, _id="main-sub-menu", _class= "menu vertical icons icon-top", # https://get.foundation/sites/docs/menu.html ), ) else: return None
def layout(item): """ Layout Method (Item Renderer) """ # Manage flags: hide any disabled/unauthorized items if not item.authorized and not item.opts.always_display: item.enabled = False item.visible = False elif item.enabled is None or item.enabled: item.enabled = True item.visible = True if item.enabled and item.visible: items = item.render_components() if item.parent is not None: if item.attr._class: classes = item.attr._class.split(" ") else: classes = [] if item.parent.parent is None: # Item at the top-level? toplevel = True if item.opts.right: classes.append("menu-right") else: toplevel = False if item.components: classes.append("has-dropdown not-click") _class = " ".join(classes) # Menu item with Dropdown if item.get_first(enabled=True): _href = item.url() return LI( A(item.label, _href=_href, _id=item.attr._id), UL(items, _class="dropdown"), _class=_class, ) else: # Menu item without Drop-Down if toplevel: item_url = item.url() if item_url == URL(c="default", f="index"): classes.append("menu-home") if item.selected: classes.append("active") _class = " ".join(classes) icon = item.opts.icon if icon: label = LABEL(ICON(icon), item.label) else: label = item.label return LI( A( label, _href=item_url, _id=item.attr._id, _target=item.attr._target, ), _class=_class, ) else: # Submenu item if isinstance(item.label, dict): if "id" in item.label: return S3MainMenuDefaultLayout.checkbox_item( item) elif "name" in item.label: label = item.label["name"] else: return None else: label = item.label link = A( label, _href=item.url(), _id=item.attr._id, _target=item.attr._target, ) _class = " ".join(classes) return LI(link, _class=_class) else: # The main menu itself T = current.T settings = current.deployment_settings if item.opts.title_area: # Custom override title_area = item.opts.title_area else: # Standard: render a menu logo logo = settings.get_ui_menu_logo() if logo is None: # Render an icon logo = SPAN( settings.get_system_name_short(), _class="logo", ) elif isinstance(logo, str): # Assume image-URL logo = IMG( _src=logo, _class="logo", _alt=settings.get_system_name_short(), ) #else: # use as-is (assume HTML or T()) title_area = A( logo, _href=URL(c="default", f="index"), _title=T("Homepage"), ) # Arrange items left/right right = [] left = [] for item in items: if "menu-right" in item["_class"]: item.remove_class("menu-right") right.append(item) else: left.append(item) right.reverse() # Reverse if right-to-left if current.response.s3.rtl: right, left = left, right # Build top-bar HTML return NAV( UL( LI( title_area, _class="name", ), LI( A(SPAN(T("Menu"))), _class="toggle-topbar menu-icon", ), _class="title-area", ), SECTION( UL( right, _class="right", ), UL( left, _class="left", ), _class="top-bar-section", ), _class="top-bar", data={"topbar": " "}, ) else: return None
def layout(item): """ Layout Method (Item Renderer) """ # Manage flags: hide any disabled/unauthorized items if not item.authorized: enabled = False visible = False elif item.enabled is None or item.enabled: enabled = True visible = True if enabled and visible: if item.parent is not None: if item.enabled and item.authorized: attr = {"_id": item.attr._id} if item.attr._onclick: attr["_onclick"] = item.attr._onclick else: attr["_href"] = item.url() if item.components: # Submenu items = item.render_components() # Hide submenus which have no active links if not items and not item.link: return None _class = "" if item.parent.parent is None and item.selected: _class = "active" section = [ LI( A(item.label, **attr), _class="heading %s" % _class, ), ] if items: section.append(UL(items)) return section else: # Submenu item if item.parent.parent is None: _class = "heading" else: _class = "" return LI( A(item.label, **attr), _class=_class, ) else: # Main menu items = item.render_components() return DIV(NAV( UL(items, _id="main-sub-menu", _class="side-nav")), _class="sidebar") else: return None
def comment_internal(self): is_author = False if self.session.auth and self.session.auth.user: is_author = True if self.session.auth.user.id == self.context.article.author else False self.db.Comments.article_id.default = self.context.article.id self.db.Comments.user_id.default = self.session.auth.user.id self.db.Comments.commenttime.default = self.request.now self.db.Comments.comment_text.label = self.T("Post your comment") from plugin_ckeditor import CKEditor ckeditor = CKEditor() self.db.Comments.comment_text.widget = ckeditor.basicwidget form = SQLFORM(self.db.Comments, formstyle='divs') if form.process( message_onsuccess=self.T('Comment included')).accepted: self.new_article_event( 'new_article_comment', self.session.auth.user, data={ 'event_text': form.vars.comment_text, 'event_link': "%s/%s#comment_%s" % (self.context.article.id, self.context.article.slug, form.vars.id) }) else: form = A( self.T("Login to post comments"), _class="button", _href=self.CURL( 'default', 'user', args='login', vars=dict(_next=self.CURL('article', 'show', args=[ self.context.article.id, self.context.article.slug ])))) comments = self.db( self.db.Comments.article_id == self.context.article.id).select( orderby=self.db.Comments.created_on) if comments and is_author: edit_in_place = ckeditor.bulk_edit_in_place( ["comment_%(id)s" % comment for comment in comments], URL('editcomment')) elif comments and self.session.auth and self.session.auth.user: usercomments = comments.find( lambda row: row.user_id == self.session.auth.user.id) if usercomments: edit_in_place = ckeditor.bulk_edit_in_place( ["comment_%(id)s" % comment for comment in usercomments], URL('editcomment')) else: edit_in_place = ('', '') else: edit_in_place = ('', '') return DIV(H4( IMG(_src=URL('static', '%s/images/icons' % self.context.theme_name, args='board.24.png')), self.T("Comments")), UL( *[ LI(H5( A(self.T("%s %s" % (comment.nickname or comment.user_id, self.db.pdate(comment.commenttime))), _href=self.CURL('person', 'show', args=comment.nickname or comment.user_id))), DIV( XML(comment.comment_text), **{ '_class': 'editable commentitem', '_data-object': 'comment', '_data-id': comment.id, '_id': "comment_%s" % comment.id }), _class="comment_li") for comment in comments ], **dict(_class="comment_ul")), edit_in_place[1], form, _class="internal-comments article-box")
def layout(item): """ Layout Method (Item Renderer) """ # Manage flags: hide any disabled/unauthorized items if not item.authorized and not item.opts.always_display: item.enabled = False item.visible = False elif item.enabled is None or item.enabled: item.enabled = True item.visible = True if item.enabled and item.visible: items = item.render_components() if item.parent is not None: if item.attr._class: classes = item.attr._class.split(" ") else: classes = [] if item.parent.parent is None: # Item at the top-level? toplevel = True if item.opts.right: classes.append("menu-right") else: toplevel = False if item.components: # Menu item with Dropdown if item.get_first(enabled=True): classes.append( "is-dropdown-submenu-parent") # Prevent FoUC _class = " ".join(classes) return LI( A( item.label, _href=item.url(), _id=item.attr._id, ), UL( items, _class="menu", ), _class=_class, ) else: # Menu item without Drop-Down if toplevel: item_url = item.url() if item_url == URL(c="default", f="index"): classes.append("menu-home") if item.selected: classes.append("active") _class = " ".join(classes) icon = item.opts.icon if icon: label = LABEL(ICON(icon), item.label) else: label = item.label return LI( A( label, _href=item_url, _id=item.attr._id, _target=item.attr._target, ), _class=_class, ) else: # Submenu item if isinstance(item.label, dict): if "id" in item.label: return S3MainMenuDefaultLayout.checkbox_item( item) elif "name" in item.label: label = item.label["name"] else: return None else: label = item.label link = A( label, _href=item.url(), _id=item.attr._id, _target=item.attr._target, ) _class = " ".join(classes) return LI( link, _class=_class, ) else: # The main menu itself # Arrange items left/right right = [] left = [] for item in items: if "menu-right" in item["_class"]: item.remove_class("menu-right") right.append(item) else: left.append(item) right.reverse() # Reverse if right-to-left if current.response.s3.rtl: right, left = left, right left = UL( left, _class="menu dropdown", ) left["_data-dropdown-menu"] = "" right = UL( right, _class="menu dropdown", ) right["_data-dropdown-menu"] = "" # Build top-bar HTML return NAV( DIV( left, _class="top-bar-left", ), DIV( right, _class="top-bar-right", ), _class="top-bar", ) else: return None
def layout(item): """ Custom Layout Method """ # Manage flags: hide any disabled/unauthorized items if not item.authorized: item.enabled = False item.visible = False elif item.enabled is None or item.enabled: item.enabled = True item.visible = True if item.enabled and item.visible: items = item.render_components() if item.parent is not None: classes = [] if item.parent.parent is None: # Item at the top-level? toplevel = True if item.opts.right: classes.append("menu-right") else: toplevel = False if items: classes.append("has-dropdown not-click") if item.selected: classes.append("active") _class = " ".join(classes) # Menu item with Dropdown if item.get_first(enabled=True, link=True): _href = item.url() return LI( A(item.label, _href=_href, _id=item.attr._id), UL(items, _class="dropdown"), _class=_class, ) else: return None else: # Menu item without Drop-Down if toplevel: item_url = item.url() if item_url == URL(c="default", f="index"): classes.append("menu-home") if item.selected: classes.append("active") _class = " ".join(classes) return LI( A( item.label, _href=item_url, _id=item.attr._id, ), _class=_class, ) else: # Submenu item if isinstance(item.label, dict): if "name" in item.label: label = item.label["name"] else: return None else: label = item.label link = A(label, _href=item.url(), _id=item.attr._id) return LI(link) else: # Main menu right = [] left = [] for item in items: if "menu-right" in item["_class"]: item.remove_class("menu-right") right.append(item) else: left.append(item) right.reverse() if current.response.s3.rtl: right, left = left, right T = current.T data_options = { "back": T("Back"), } return NAV( UL( LI(A( " ", _href=URL(c="default", f="index"), ), _class="name"), LI( A(SPAN(current.T("Menu"))), _class="toggle-topbar menu-icon", ), _class="title-area", ), SECTION( UL(right, _class="right"), UL(left, _class="left"), _class="top-bar-section", ), _class="top-bar", data={ "topbar": " ", "options": "back_text:%(back)s" % data_options, }, ) else: return None
def serialize(self, data, level=0, menu_name=None): if level == 0: ul = UL(**self.attributes) elif level == 1 and menu_name : ul = UL(_class=self['ul_class'], _id=menu_name) else: return '' # Navbar works only for 1 level for n, item in enumerate(data): if isinstance(item, LI): ul.append(item) else: (name, active, link) = item[:3] if isinstance(link, DIV): li = LI(link) elif 'no_link_url' in self.attributes and self['no_link_url'] == link: li = LI(DIV(name)) elif isinstance(link, dict): li = LI(A(name, **link)) elif link: li = LI(A(name, _href=link)) elif not link and isinstance(name, A): li = LI(name) else: li = LI(A(name, _href='#', _onclick='javascript:void(0);return false;')) if len(item) > 3 and item[3]: li['_class'] = self['li_class'] menu_id = "%s-%s" % (self.menu_name, n) a = li.element('a') a['_class'] = "dropdown-button" a['_data-activates'] = menu_id li.append(self.serialize(item[3], level + 1, menu_id)) if active or ('active_url' in self.attributes and self['active_url'] == link): if li['_class']: li['_class'] = li['_class'] + ' ' + self['li_active'] else: li['_class'] = self['li_active'] if len(item) <= 4 or item[4] == True: ul.append(li) return ul
def invite(self, r, **attr): """ Prepare and process invitation form @param r: the S3Request instance @param attr: controller attributes """ T = current.T db = current.db s3db = current.s3db response = current.response request = current.request session = current.session settings = current.deployment_settings auth = current.auth auth_settings = auth.settings auth_messages = auth.messages output = { "title": T("Invite Organisation"), } # Get all accounts that are linked to this org utable = auth_settings.table_user oltable = s3db.org_organisation_user pltable = s3db.pr_person_user organisation_id = r.record.id join = oltable.on((oltable.user_id == utable.id) & \ (oltable.deleted == False)) left = pltable.on((pltable.user_id == utable.id) & \ (pltable.deleted == False)) query = (oltable.organisation_id == organisation_id) rows = db(query).select( utable.id, utable.first_name, utable.last_name, utable.email, utable.registration_key, pltable.pe_id, join=join, left=left, ) active, disabled, invited = [], [], [] for row in rows: user = row[utable] person_link = row.pr_person_user if person_link.pe_id: if user.registration_key: disabled.append(user) else: active.append(user) else: invited.append(user) if active or disabled: response.error = T( "There are already user accounts registered for this organization" ) from gluon import UL, LI, H4, DIV from s3 import s3_format_fullname fullname = lambda user: s3_format_fullname( fname=user.first_name, lname=user.last_name, truncate=False, ) account_list = DIV(_class="org-account-list") if active: account_list.append(H4(T("Active Accounts"))) accounts = UL() for user in active: accounts.append( LI("%s <%s>" % (fullname(user), user.email))) account_list.append(accounts) if disabled: account_list.append(H4(T("Disabled Accounts"))) accounts = UL() for user in disabled: accounts.append( LI("%s <%s>" % (fullname(user), user.email))) account_list.append(accounts) output["item"] = account_list response.view = self._view(r, "display.html") return output account = invited[0] if invited else None # Look up existing invite-account email = None if account: email = account.email else: ctable = s3db.pr_contact query = (ctable.pe_id == r.record.pe_id) & \ (ctable.contact_method == "EMAIL") & \ (ctable.deleted == False) contact = db(query).select( ctable.value, orderby=ctable.priority, limitby=(0, 1), ).first() if contact: email = contact.value # Form Fields dbset = db(utable.id != account.id) if account else db formfields = [ Field("email", default=email, requires=[ IS_EMAIL(error_message=auth_messages.invalid_email), IS_LOWER(), IS_NOT_IN_DB( dbset, "%s.email" % utable._tablename, error_message=auth_messages.duplicate_email, ), ]), ] # Generate labels (and mark required fields in the process) labels, has_required = s3_mark_required(formfields, ) response.s3.has_required = has_required # Form buttons SEND_INVITATION = T("Send New Invitation") if account else T( "Send Invitation") buttons = [ INPUT( _type="submit", _value=SEND_INVITATION, ), # TODO cancel-button? ] # Construct the form response.form_label_separator = "" form = SQLFORM.factory( table_name="invite", record=None, hidden={"_next": request.vars._next}, labels=labels, separator="", showid=False, submit_button=SEND_INVITATION, #delete_label = auth_messages.delete_label, formstyle=settings.get_ui_formstyle(), buttons=buttons, *formfields) # Identify form for CSS & JS Validation form.add_class("send_invitation") if form.accepts( request.vars, session, formname="invite", #onvalidation = auth_settings.register_onvalidation, ): error = self.invite_account(r.record, form.vars.email, account=account) if error: response.error = T( "Could not send invitation (%(reason)s)") % { "reason": error } else: response.confirmation = T("Invitation sent") else: if account: response.warning = T( "This organisation has been invited before!") output["form"] = form response.view = self._view(r, "update.html") return output
def summary(self, r, **attr): """ Render the summary page @param r: the S3Request @param attr: controller attributes """ output = {} response = current.response resource = self.resource get_config = resource.get_config # Get Summary Page Configuration config = self._get_config(resource) # Page title crud_string = self.crud_string title = crud_string(self.tablename, "title_list") output["title"] = title # Tabs tablist = UL() sections = [] commons = [] # Active tab if "t" in r.get_vars: active_tab = int(r.get_vars["t"]) else: active_tab = 0 active_map = None show_filter_form = False filter_widgets = get_config("filter_widgets") if filter_widgets and not self.hide_filter: # Apply filter defaults (before rendering the data!) show_filter_form = True S3FilterForm.apply_filter_defaults(r, resource) # Render sections tab_idx = 0 widget_idx = 0 targets = [] pending = [] # Dynamic filtering (e.g. plot-click in report widget) attr["filter_form"] = form_id = "summary-filter-form" for section in config: common = section.get("common") # Section container section_id = section["name"] s = DIV(_class="section-container", _id=section_id) if not common: # Label label = section["label"] translate = section.get("translate", True) if isinstance(label, basestring) and translate: label = current.T(label) # Add tab tablist.append(LI(A(label, _href="#%s" % section_id))) if common or active_tab == tab_idx: visible = True else: visible = False # Widgets widgets = section.get("widgets", []) for widget in widgets: # Widget ID widget_id = "summary-%s" % widget_idx # Make sure widgets include the widget ID when # generating Ajax URLs: r.get_vars["w"] = r.vars["w"] = widget_id # Append to filter targets filterable = widget.get("filterable", True) if filterable: targets.append(widget_id) if not visible and widget.get("ajax_init"): pending.append(widget_id) # Apply method method = widget.get("method") if callable(method): content = method(r, widget_id=widget_id, visible=visible, **attr) else: handler = r.get_widget_handler(method) if handler is None: # Fall back to CRUD handler = resource.crud if handler is not None: if method == "datatable": # Assume that we have a FilterForm, so disable Quick Search dtargs = attr.get("dtargs", {}) dtargs["dt_bFilter"] = "false" attr["dtargs"] = dtargs content = handler(r, method=method, widget_id=widget_id, visible=visible, **attr) else: r.error(405, current.ERROR.BAD_METHOD) # Add content to section if isinstance(content, dict): if r.http == "POST" and content.get("success"): # Form successfully processed: behave like the # primary method handler and redirect to next next_url = content.get("next") if next_url: self.next = next_url return content for k, v in content.items(): if k not in ("tabs", "sections", "widget"): output[k] = v content = content.get("widget", "EMPTY") elif active_tab == tab_idx and isinstance(content, MAP): active_map = content s.append( DIV(content, _id="%s-container" % widget_id, _class="widget-container")) widget_idx += 1 if common: commons.append(s) else: sections.append(s) tab_idx += 1 # Remove widget ID r.get_vars.pop("w", None) # Add tabs + sections to output if len(sections) > 1: output["tabs"] = tablist # Hide tabbed sections initially to avoid visible artifacts # in slow page loads (S3.search.summary_tabs will un-hide the active one): for s in sections: s.add_class("hide") else: # Hide tabs if there's only one section (but then don't hide # the section!) output["tabs"] = "" output["sections"] = sections # Add common sections to output output["common"] = commons # Filter targets target = " ".join(targets) # Filter form filter_ajax = True if show_filter_form: # Where to retrieve filtered data from: if active_tab != 0: submit_url_vars = {"t": active_tab} else: submit_url_vars = {} filter_submit_url = attr.get("filter_submit_url") if not filter_submit_url: _vars = self._remove_filters(r.get_vars) _vars.update(submit_url_vars) filter_submit_url = r.url(vars=_vars) # Where to retrieve updated filter options from: filter_ajax_url = attr.get( "filter_ajax_url", r.url(method="filter", vars={}, representation="options")) filter_formstyle = get_config("filter_formstyle") filter_submit = get_config("filter_submit", True) filter_form = S3FilterForm(filter_widgets, formstyle=filter_formstyle, submit=filter_submit, ajax=filter_ajax, url=filter_submit_url, ajaxurl=filter_ajax_url, _class="filter-form", _id=form_id) fresource = current.s3db.resource(resource.tablename) alias = resource.alias if r.component else None output["filter_form"] = filter_form.html(fresource, r.get_vars, target=target, alias=alias) else: # Render as empty string to avoid the exception in the view output["filter_form"] = "" # View response.view = self._view(r, "summary.html") if len(sections) > 1: # Provide a comma-separated list of initially hidden widgets # which are rendered empty and need a trigger to Ajax-load # their data layer (e.g. maps, reports): pending = ",".join(pending) if pending else "null" # Render the Sections as Tabs script = '''S3.search.summary_tabs("%s",%s,"%s")''' % \ (form_id, active_tab, pending) response.s3.jquery_ready.append(script) if active_map: # If there is a map on the active tab then we need to add # a callback to the Map JS Loader active_map.callback = '''S3.search.summary_maps("%s")''' % form_id return output
def pager(total_records, page_limit, current_page, target_url, page_var): """ Generates a simple pagintator navigation block. """ total_pages = int(math.ceil(total_records / float(page_limit))) current_page = int(current_page) if total_pages <= 1: return None prev_disabled = current_page <= 1 next_disabled = current_page == total_pages # Build the page links... url_fmt = target_url # Any other query params? if '?' in url_fmt: url_fmt += '&' else: url_fmt += '?' url_fmt += page_var + '={0}' result = DIV(_class="pagination") page_list = UL() prev_page = LI() next_page = LI() if prev_disabled: prev_page['_class'] = "disabled" prev_page.append(A(I(_class="icon-backward"), _href="#")) else: prev_page.append( A(I(_class="icon-backward"), _href=url_fmt.format(current_page - 1))) if next_disabled: next_page['_class'] = 'disabled' next_page.append(A(I(_class="icon-forward"), _href="#")) else: next_page.append( A(I(_class="icon-forward"), _href=url_fmt.format(current_page + 1))) page_list.append(prev_page) for page_num, idx in enumerate(xrange(total_pages), 1): entry = LI(A(str(page_num), _href=url_fmt.format(page_num))) if page_num == current_page: entry['_class'] = "active" page_list.append(entry) page_list.append(next_page) result.append(page_list) return result