def render_row(row_id, label, widget, comment, hidden=False): if hasattr(widget, "element"): submit = widget.element("input", _type="submit") if submit: submit.add_class("small primary button") controls_width = "medium-12" if label is False else "medium-10" controls_col = DIV(widget, _class="%s columns controls" % controls_width) if label: if isinstance(label, LABEL): label.add_class("left inline") label_col = DIV(label, _class="medium-2 columns") else: if label is not False: controls_col.add_class("medium-offset-2") label_col = "" if comment: comment = render_tooltip(label, comment, _class="inline-tooltip tooltip", ) if hasattr(comment, "add_class"): comment.add_class("inline-tooltip") controls_col.append(comment) _class = "form-row row hide" if hidden else "form-row row" return DIV(label_col, controls_col, _class=_class, _id=row_id)
class Leyenda(DIV): def __init__(self, *components, **attributes): out_body = DIV(components, _class="panel-body") self.my_body = DIV(_class="btn-group", _role="group") out_body.append(self.my_body) out_body.append(XML(''' <script> $(function () { $('[data-toggle="popover"]').popover() }) </script>''')) attributes['_class'] = 'panel panel-default' super(Leyenda, self).__init__(out_body, **attributes) def append(self, titulo, valores, direccion="bottom"): co = CAT(titulo, SPAN(**{'_class': 'glyphicon glyphicon-question-sign', '_aria-hidden': 'true'})) item = A(co, **{'_type': 'button', '_role': 'button', '_tabindex': '0', '_class': 'btn btn-default btn-xs', '_data-container': 'body', '_data-toggle': 'popover', '_data-placement': direccion, '_data-trigger': 'focus', '_data-content': reduce( lambda x, y: x + ' ({0}){1}'.format(y[0], y[1]), valores.iteritems(), '')}) self.my_body.append(item)
def render_row(row_id, label, widget, comment, hidden=False): if hasattr(widget, "element"): try: submit = widget.element("input", _type="submit") except TypeError: # e.g. plain Reference submit = None if submit: submit.add_class("small primary button") _class = "form-row row hide" if hidden else "form-row row" hints = DIV(render_tooltip(label, comment), _class="inline-tooltip") controls = DIV( label, DIV( widget, hints, _class="controls", ), _class="small-12 columns", ) return DIV( controls, _class=_class, _id=row_id, )
def selector(rules): """ Generate the rule selector for anonymize-form @param rules: the list of configured rules @return: the selector (DIV) """ T = current.T selector = DIV(_class="anonymize-select") for rule in rules: name = rule.get("name") if not name: continue title = T(rule.get("title", name)) selector.append(DIV(INPUT(value = "on", _name = s3_str(name), _type = "checkbox", _class = "anonymize-rule", ), LABEL(title), _class = "anonymize-option", )) return selector
def selector(rules): """ Generate the rule selector for anonymize-form @param rules: the list of configured rules @return: the selector (DIV) """ T = current.T selector = DIV(_class="anonymize-select", ) for rule in rules: name = rule.get("name") if not name: continue title = T(rule.get("title", name)) selector.append( DIV( INPUT( value="on", _name=s3_str(name), _type="checkbox", _class="anonymize-rule", ), LABEL(title), _class="anonymize-option", )) return selector
def widget(self, linktext, content, classnames=None, trigger='click', placement='bottom', id=None, **kwargs): ''' Returns the actual popover widget. In addition to the link text and popup content, any of the bootstrap popover properties may be set by passing a keyword-argument whose name is the property in question. The inline style display:none is necessary to hide the popover content initially. ''' myid = linktext if not id else id classes = "popover-trigger {}".format(classnames) myargs = { '_data-trigger': trigger, '_data-placement': placement, '_data-toggle': 'popover' } if kwargs: newargs = {'_data-{}'.format(k): v for k, v in kwargs.iteritems()} myargs.update(newargs) popover = DIV(linktext, _id=myid, _class=classes, **myargs) popover.append( DIV(content, _class="popover-content", _style="display: none")) return popover
def ACCORDION(panels, id='my_accordion'): ''' [0] pid [1] panel link text [2] panel content [3] body classes (string); 'in' marks default panel ''' acc = DIV(_class='panel-group', _id=id) for panel in panels: pid = panel[0] linktext = panel[1] content = panel[2] bclasses = '' if len(panel) <= 3 else panel[3] linkattrs = {'_class': "panel-toggle {}-toggle".format(pid), '_data-toggle': "collapse", '_data-parent': "#{}".format(id), '_href': "#{}".format(pid)} headattrs = {'_class': "panel-heading"} bodyattrs = {'_class': 'panel-body '} innerattrs = {'_class': 'panel collapse {}'.format(bclasses), '_id': pid} p = CAT(DIV(H4(A(linktext, **linkattrs), _class="panel-title"), **headattrs), DIV(DIV(content, **bodyattrs), **innerattrs), ) acc.append(p) return acc
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 serialize(self, data): div = DIV(**self.attributes) for item in data[:-1]: (link, name) = item a = A(name, _href=link, _class=self['a_class']) div.append(a) div.append(data[-1][1]) return div
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
def mavc_rheader(r, tabs=None): """ Custom rheaders """ if r.representation != "html": return None from s3 import s3_rheader_resource, s3_rheader_tabs from gluon import A, DIV, H1, H2, TAG tablename, record = s3_rheader_resource(r) if record is None: return None T = current.T s3db = current.s3db if tablename != r.tablename: resource = s3db.resource(tablename, id=record.id if record else None) else: resource = r.resource rheader = "" if tablename == "org_organisation": # Tabs if not tabs: INDIVIDUALS = current.deployment_settings.get_hrm_staff_label() tabs = [ (T("About"), None), (INDIVIDUALS, "human_resource"), (T("Service Locations"), "service_location"), # @todo: activities ] # Use OrganisationRepresent for title to get L10n name if available represent = s3db.org_OrganisationRepresent(acronym=False, parent=False) title = represent(record.id) # Retrieve other details for the rheader data = resource.select(["organisation_organisation_type.organisation_type_id", "website"], represent=True) row = data.rows[0] subtitle = row["org_organisation_organisation_type.organisation_type_id"] website = row["org_organisation.website"] # Compile the rheader rheader = DIV(DIV(H1(title), H2(subtitle), website if record.website else "", _class="rheader-details")) if tabs: rheader_tabs = s3_rheader_tabs(r, tabs) rheader.append(rheader_tabs) return rheader
def render_row(row_id, label, controls, comment, hidden=False): # Based on web2py/gluon/sqhtml.py # wrappers _help = DIV(comment, _class="help-block") # embed _help into _controls _controls = DIV(controls, _help, _class="controls") # submit unflag by default _submit = False element = None if isinstance(controls, INPUT): controls.add_class("span4") element = controls elif hasattr(controls, "element"): element = controls.element("input") if element: if element["_type"] == "submit": # flag submit button _submit = True element["_class"] = "btn btn-primary" elif element["_type"] == "file": element["_class"] = "input-file" # For password fields, which are wrapped in a CAT object. if isinstance(controls, CAT) and isinstance(controls[0], INPUT): controls[0].add_class("span4") if isinstance(controls, SELECT): controls.add_class("span4") if isinstance(controls, TEXTAREA): controls.add_class("span4") if isinstance(label, LABEL): label["_class"] = "control-label" _class = "hide " if hidden else "" if _submit: # submit button has unwrapped label and controls, different class return DIV( label, controls, _class="%sform-actions" % _class, _id=row_id, ) else: # unwrapped label return DIV( label, _controls, _class="%scontrol-group" % _class, _id=row_id, )
def formstyle_row(id, label, widget, comment, hidden=False): if hidden: hide = "hide" else: hide = "" row = DIV( DIV(comment, label, _id=id + "1", _class="w2p_fl %s" % hide), DIV(widget, _id=id, _class="w2p_fw %s" % hide), _class="w2p_r", ) return row
def formstyle_row(id, label, widget, comment, hidden=False): if hidden: hide = "hide" else: hide = "" row = DIV( DIV(label, _id=id + "_label", _class="w2p_fl"), DIV(widget, _id=id + "_widget", _class="w2p_fw"), DIV(comment, _id=id + "_comment", _class="w2p_fc"), _id=id, _class="w2p_r %s" % hide, ) return row
def render_row(row_id, label, widget, comment, hidden=False): # Inspect widget columns = None if hasattr(widget, "element"): # Check for widget columns width override attr = widget.element().attributes if "s3cols" in attr: columns = attr["s3cols"] or columns # Set additional CSS classes for submit button submit = widget.element("input", _type="submit") if submit: submit.add_class("small primary button") # Render tooltip hints = render_tooltip(label, comment) # Wrap the label if isinstance(label, LABEL): label.add_class("right inline") else: label = LABEL( label, _class="right inline", ) label = DIV( label, _class="small-2 columns", ) # Wrap the controls if columns is None: _columns = "small-10 columns" else: _columns = "small-%s columns end" % columns controls = DIV( widget, hints, _class=_columns, ) # Render the row _class = "form-row row" if hidden: _class = "%s hide" % _class return DIV( label, controls, _class=_class, _id=row_id, )
def formstyle(self, xfields): """ Use new Web2Py formstyle to generate form using DIVs & CSS CSS can then be used to create MUCH more flexible form designs: - Labels above vs. labels to left - Multiple Columns @ToDo: Requires further changes to code to use """ form = DIV() for id, a, b, c, in xfields: form.append(formstyle_row(id, a, b, c)) return form
def widget(self,field, value): self.tablename = self.tablename or field._tablename _name=field.name, _id="%s_%s" % (self.tablename, field.name) self.kwargs.update({ '_type': "text", '_name': "%s_text" %field.name, '_id': "%s_%s_text" % (self.tablename, field.name), '_value': '' if self.show_result else self.format(value), '_class': "bt_autocomplete form-control", '_data-url': self.url, '_data-resume': 'true' if self.show_result else 'false'}) kwargs = self.kwargs element = DIV(INPUT(_type="hidden",_name=field.name,_id="%s_%s" %(self.tablename, field.name),_value=value,_class="typeahead"), INPUT(**kwargs), _class="input-group" ) if not self.show_result: element.append( SPAN(BUTTON("Adicionar!",_class="btn btn-sm disabled", _type="button",_id="id_add_%s" %field.name, _title="Clique para adicionar",_disabled="disabled"), _class="input-group-btn" ) ) # else: # widget +=INPUT(_type="text",_name="%s_text" %field.name, # _id="%s_%s_text" % (self.tablename, field.name), # _value=value, # _class="bt_autocomplete") # {{ extra_attrs }} /> # widget = element if self.add_link: element.append( SPAN( A(I(_class="icon-plus"),_href="",_class="btn btn-sm add-another addlink", _id="add_%s_%s_text" % (self.tablename, field.name), _onclick="return showAddAnotherPopup(this);"), _class="input-group-btn" ) ) if self.show_result: element+=DIV( A(I(_class="icon-trash")," ",self.format(value) if callable(self.format) else self.format %value, _id="%s_%s_trash" %(self.tablename, field.name), _class="btn btn-sm", _title="Clique para remover") if value else "", _id="%s_%s_on_deck" %(self.tablename, field.name), _class="resume", _style="margin-top:5px;" ) # element += return element
def render_row(row_id, label, widget, comment, hidden=False): if hasattr(widget, "element"): submit = widget.element("input", _type="submit") if submit: submit.add_class("small primary button") controls_width = "medium-12" if label is False else "medium-10" controls_col = DIV(widget, _class="%s columns controls" % controls_width) if label: if isinstance(label, LABEL): label.add_class("left inline") label_col = DIV(label, _class="medium-2 columns") else: if label is not False: controls_col.add_class("medium-offset-2") label_col = "" if comment: comment = render_tooltip( label, comment, _class="inline-tooltip tooltip", ) if hasattr(comment, "add_class"): comment.add_class("inline-tooltip") controls_col.append(comment) _class = "form-row row hide" if hidden else "form-row row" return DIV(label_col, controls_col, _class=_class, _id=row_id)
def get_html(self, **args): if len(args["cta_links"]) > 0: actions_div = DIV(*args["cta_links"], _class="card-action") else: actions_div = "" return DIV(DIV(DIV(SPAN(args["card_title"], _class="card-title"), args["card_content"], _class="card-content " + \ args["card_text_color_class"]), actions_div, _class="card stopstalk-dashboard-card " + \ args["card_color_class"]), _class="col s4")
def _thumb(row, cls, title=None): """ Return a column DIV thumbnail. """ caption = DIV(H3(row.chapter.title), H4('Chapter %i' % row.chapter.number), H5(row.published.strftime(date_format)), H3(row.intro_hanzi), H4(row.intro_en), _class='caption', _role='button', _title=title) anchor = A(caption, _class='ddj-thumbnail', _href=URL('poems', 'chapter', args=[row.chapter.number])) thumbnail = DIV(anchor, _class='thumbnail') return DIV(thumbnail, _class=cls)
def _render_tag_input_upload(self, label, controls, help): row = DIV(_class='file-field input-field col s12') btn = DIV(_class='btn') label.tag = 'SPAN' self._append_basic_field(btn, controls, label, help) # reverse label and controls row.append(btn) row.append(DIV(INPUT(_class='file-path validate', _type='text'), _class='file-path-wrapper')) return row
def message_widget(field, value, **attr): """ Widget to edit and preview a notification message body @param field: the Field @param value: the current field value @param attr: DOM attributes for the widget """ widget_id = attr.get("_id") if not widget_id: widget_id = "%s_%s" % (field._tablename, field.name) edit = TEXTAREA( _name=attr.get("_name", field.name), _id=widget_id, _class="message %s" % (field.type), _placeholder=attr.get("_placeholder"), _rows=6, _style="display:none", value=value, requires=field.requires, ) preview = P("", _class="preview") return DIV(preview, edit, _class="preview-widget")
def layout(item): """ Layout for popup link """ if not item.authorized: return None if current.deployment_settings.get_ui_use_button_icons(): label = (ICON("add"), item.label) else: label = item.label # @ToDo Ensure that if we are in an inline component, these links are different for each of the 3 _id = item.attr._id or "%s_add" % item.function popup_link = A(label, _href = item.url(format = "popup"), _class = "s3_add_resource_link", _id = _id, _target = "top", _title = item.opts.info, ) tooltip = item.opts.tooltip if tooltip is not None: ttip = DIV(_class = "tooltip", _title = "%s|%s" % (item.opts.title, tooltip, ), ) else: ttip = "" return TAG[""](popup_link, ttip)
def render_trending_table(caption, problems, column_name, user_id): """ Create trending table from the rows """ T = current.T table = TABLE(_class="bordered centered") thead = THEAD( TR(TH(T("Problem")), TH(T("Recent Submissions")), TH(column_name))) table.append(thead) tbody = TBODY() for problem in problems: tr = TR() link_class = get_link_class(problem[0], user_id) link_title = (" ".join(link_class.split("-"))).capitalize() tr.append( TD( problem_widget(problem[1]["name"], problem[0], link_class, link_title))) tr.append(TD(problem[1]["total_submissions"])) tr.append(TD(len(problem[1]["users"]) + \ len(problem[1]["custom_users"]))) tbody.append(tr) table.append(tbody) table = DIV(H5(caption, _class="center"), HR(), table) return table
def layout(item): """ Layout for popup link """ if not item.authorized: return None if current.deployment_settings.get_ui_use_button_icons(): label = (ICON("add"), item.label) else: label = item.label popup_link = A( label, _href=item.url(format="popup"), _class="s3_add_resource_link", _id="%s_add" % item.function, _target="top", _title=item.opts.info, ) tooltip = item.opts.tooltip if tooltip is not None: ttip = DIV(_class="tooltip", _title="%s|%s" % (item.opts.title, tooltip)) else: ttip = "" return TAG[""](popup_link, ttip)
def login_form(self): """ Combine the auth() form with alt_login_form. If signals are set and a parameter in request matches any signals, it will return the call of alt_login_form.login_form instead. So alt_login_form can handle some particular situations, for example, multiple steps of OpenID login inside alt_login_form.login_form. Otherwise it will render the normal login form combined with alt_login_form.login_form. """ request = current.request args = request.args if (self.signals and any( [True for signal in self.signals if request.vars.has_key(signal)])): return self.alt_login_form.login_form() self.auth.settings.login_form = self.auth form = DIV(self.auth()) self.auth.settings.login_form = self form.components.append(self.alt_login_form.login_form()) return form
def rheader(r, **attr): """ S3SyncLog resource header """ if r.id is None: return DIV(current.T("Showing latest entries first")) else: return None
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 subject_widget(field, value, **attr): """ Widget to edit and preview a notification subject line @param field: the Field @param value: the current field value @param attr: DOM attributes for the widget """ widget_id = attr.get("_id") if not widget_id: widget_id = "%s_%s" % (field._tablename, field.name) edit = INPUT(_name=attr.get("_name", field.name), _id=widget_id, _type="text", _class="subject %s" % (field.type), _placeholder=attr.get("_placeholder"), _style="display:none", value=value, requires=field.requires) preview = H6("", _class="preview") return DIV(preview, edit, _class="preview-widget")
def layout(item): """ Layout Method (Item Renderer) """ if item.enabled: if item.parent is not None: output = A( SPAN(item.label), _class="zocial %s" % item.opts.api, _href=item.url(), _title=item.opts.get("title", item.label), ) else: items = item.render_components() if items: output = DIV( items, _class="zocial-login", ) else: # Hide if empty output = None else: # Hide if disabled output = None return output
def html(self, widget_id=None, formkey=None): """ Render the organizer container and instantiate the UI widget @param widget_id: the container's DOM ID """ T = current.T settings = current.deployment_settings if not widget_id: widget_id = "organizer" # Parse resource configuration resources = self.resources if not isinstance(resources, (list, tuple)): resources = [resources] resource_configs = [] use_time = False for resource_config in resources: resource_use_time = resource_config.get("useTime") if resource_use_time: use_time = True resource_configs.append(resource_config) # Inject script and widget instantiation script_opts = {"resources": resource_configs, "useTime": use_time, "labelEdit": s3_str(T("Edit")), "labelDelete": s3_str(T("Delete")), "deleteConfirmation": s3_str(T("Do you want to delete this entry?")), "firstDay": settings.get_L10n_firstDOW(), } # Options from settings bhours = settings.get_ui_organizer_business_hours() if bhours: script_opts["businessHours"] = bhours tformat = settings.get_ui_organizer_time_format() if tformat: script_opts["timeFormat"] = tformat self.inject_script(widget_id, script_opts) # Add a datepicker to navigate to arbitrary dates picker = S3DateWidget()(Storage(name="date_select"), None, _type="hidden", _id="%s-date-picker" % widget_id, ) # Generate and return the HTML for the widget container return DIV(INPUT(_name = "_formkey", _type = "hidden", _value = str(formkey) if formkey else "", ), picker, _id = widget_id, _class = "s3-organizer", )
def index(page_number, db): """ Return a row DIV of a page of poems. """ low, high = chapter_range(page_number) qry = ((db.poem.chapter >= low) & (db.poem.chapter <= high)) thumbs = [] for row in db(qry).select(orderby=db.poem.chapter): thumbs.append(_thumb(row, index_class)) return DIV(thumbs, _class='row display-flex')
def ACCORDION(panels, id='my_accordion'): ''' [0] pid [1] panel link text [2] panel content [3] body classes (string); 'in' marks default panel ''' acc = DIV(_class='panel-group', _id=id) for panel in panels: pid = panel[0] linktext = panel[1] content = panel[2] bclasses = '' if len(panel) <= 3 else panel[3] linkattrs = { '_class': "panel-toggle {}-toggle".format(pid), '_data-toggle': "collapse", '_data-parent': "#{}".format(id), '_href': "#{}".format(pid) } headattrs = {'_class': "panel-heading"} bodyattrs = {'_class': 'panel-body '} innerattrs = { '_class': 'panel collapse {}'.format(bclasses), '_id': pid } p = CAT( DIV(H4(A(linktext, **linkattrs), _class="panel-title"), **headattrs), DIV(DIV(content, **bodyattrs), **innerattrs), ) acc.append(p) return acc
def bookmark(cls, r, tablename, record_id): """ Get a bookmark link for a record in order to embed it in the view, also renders a link to the duplicate bookmark list to initiate the merge process from @param r: the S3Request @param tablename: the table name @param record_id: the record ID """ auth = current.auth system_roles = auth.get_system_roles() if not auth.s3_has_role(system_roles.ADMIN): return "" if r.component and not r.component.multiple: # Cannot de-duplicate single-components return "" s3 = current.session.s3 DEDUPLICATE = cls.DEDUPLICATE remove = DEDUPLICATE in s3 and \ tablename in s3[DEDUPLICATE] and \ str(record_id) in s3[DEDUPLICATE][tablename] and \ True or False mark = "mark-deduplicate action-lnk" unmark = "unmark-deduplicate action-lnk" deduplicate = "deduplicate action-lnk" if remove: mark += " hide" else: unmark += " hide" deduplicate += " hide" T = current.T link = DIV(A(T("Mark as duplicate"), _class=mark, ), A(T("Unmark as duplicate"), _class=unmark, ), A("", _href=r.url(method="deduplicate", vars={}), _id="markDuplicateURL", _class="hide", ), A(T("De-duplicate"), _href=r.url(method="deduplicate", target=0, vars={}), _class=deduplicate, ), _id="markDuplicate", ) return link
def customise_project_task_resource(r, tablename): from gluon import DIV current.s3db.project_task.comment = DIV(_class = "tooltip", _title = "%s|%s" % (T("Detailed Description/URL"), T("Please provide as much detail as you can, including the URL(s) where the bug occurs or you'd like the new feature to go."), ), )
def index(): log('acceso') # menu favoritos form = CENTER( FORM(DIV(I(' Personal', _class='fa fa-ticket fa-2x', _id='tit_minigrid'), DIV(grand_button('empleados', 'admin_tabla', 'fa-cart-plus', vars={'tabla': 'empleado'}), grand_button('ver marcadas', 'admin_tabla', 'fa-th-large'), grand_button('informe mes empleado', 'informe_mes_empleado', 'fa-truck'), _id='mini_grid'), _id='indexdiv'), _id='panel_grid')) return dict(form=form)
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 widget(self, linktext, content, classnames=None, trigger='click', placement='bottom', id=None, **kwargs): ''' Returns the actual popover widget. In addition to the link text and popup content, any of the bootstrap popover properties may be set by passing a keyword-argument whose name is the property in question. The inline style display:none is necessary to hide the popover content initially. ''' myid = linktext if not id else id classes = "popover-trigger {}".format(classnames) myargs = {'_data-trigger': trigger, '_data-placement': placement, '_data-toggle': 'popover'} if kwargs: newargs = {'_data-{}'.format(k): v for k, v in kwargs.iteritems()} myargs.update(newargs) popover = DIV(linktext, _id=myid, _class=classes, **myargs) popover.append(DIV(content, _class="popover-content", _style="display: none")) return popover
def __init__(self, *components, **attributes): out_body = DIV(components, _class="panel-body") self.my_body = DIV(_class="btn-group", _role="group") out_body.append(self.my_body) out_body.append(XML(''' <script> $(function () { $('[data-toggle="popover"]').popover() }) </script>''')) attributes['_class'] = 'panel panel-default' super(Leyenda, self).__init__(out_body, **attributes)
def TOOLTIP(title, text, content, icon=None): ''' Build and return a tooltip widget with the supplied content. ''' # build widget wrapper wrapper_title = '{}_wrapper'.format(title) wrapper_classes = '{} tip_wrapper'.format(wrapper_title) tip_wrapper = DIV(_class=wrapper_classes, _id=wrapper_title) # add tip trigger link if icon: tip_wrapper.append(ICONLINK(title, text, icon)) else: trigger_title = '{}_trigger'.format(title) trigger_classes = '{} trigger'.format(trigger_title) tip_wrapper.append(A(text, _classes=trigger_classes, _id=trigger_title)) # add tip content tip_classes = '{} tip'.format(title) tip_wrapper.append(DIV(content, _class=tip_classes, _id=title)) return tip_wrapper
def customfield(form, field, css={"main": "row", "label": "", "comment": "", "widget": "", "input": "", "error": ""}): tablefield = (form.table, field) maindiv = DIV(_id="%s_%s__row" % tablefield, _class=css.get("main", "")) if field in form.errors: maindiv["_class"] += css.get("error", "") labeldiv = DIV(_class="w2p_fl %s" % css.get("label", "")) commentdiv = DIV(_class="w2p_fc %s" % css.get("comment", "")) widgetdiv = DIV(_class="w2p_fw %s" % css.get("widget", "")) label = LABEL(form.custom.label[field], _for="%s_%s" % tablefield, _id="%s_%s__label" % tablefield) comment = form.custom.comment[field] widget = form.custom.widget[field] widget_class = widget.attributes.get("_class", "") widget_class += css.get("input", "") widget["_class"] = widget_class labeldiv.append(label) commentdiv.append(comment) widgetdiv.append(widget) maindiv.append(labeldiv) maindiv.append(commentdiv) maindiv.append(widgetdiv) return maindiv
def customfield(form, field): tablefield = (form.table, field) maindiv = DIV(_id="%s_%s__row" % tablefield, _class="row") labeldiv = DIV(_class="w2p_fl") commentdiv = DIV(_class="w2p_fc") widgetdiv = DIV(_class="w2p_fw") label = LABEL(form.custom.label[field], _for="%s_%s" % tablefield, _id="%s_%s__label" % tablefield) comment = form.custom.comment[field] widget = form.custom.widget[field] labeldiv.append(label) commentdiv.append(comment) widgetdiv.append(widget) maindiv.append(labeldiv) maindiv.append(commentdiv) maindiv.append(widgetdiv) return maindiv
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_searching"] = "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_clear = get_config("filter_clear", current.deployment_settings.get_ui_filter_clear()) filter_formstyle = get_config("filter_formstyle") filter_submit = get_config("filter_submit", True) filter_form = S3FilterForm(filter_widgets, clear=filter_clear, 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 monthcal(self, year=None, month=None): ''' Assemble and return an html calendar displaying the number of attempts per day in the month 'month' for the user represented by self.user_id. The calendar is returned as a web2py DIV helper. The calendar html structure is: <table border="0" cellpadding="0" cellspacing="0" class="month">\n <tr> <th class="month" colspan="7">December 2013</th> </tr>\n <tr> <th class="sun">Sun</th> <th class="mon">Mon</th> <th>class="tue">Tue</th> <th>class="wed">Wed</th> <th>class="thu">Thu</th> <th>class="fri">Fri</th> <th>class="sat">Sat</th> </tr>\n <tr> <td class="sun">1</td> <td class="mon">2</td> <td class="tue">3</td> <td class="wed">4</td> <td class="thu">5</td> <td class="fri">6</td> <td class="sat">7</td> </tr>\n ... <tr> <td class="sun">29</td> <td class="mon">30</td> <td class="tue">31</td> <td class="noday">\xc2\xa0</td> <td class="noday">\xc2\xa0</td> <td class="noday">\xc2\xa0</td> <td class="noday">\xc2\xa0</td> </tr>\n </table>\n ''' # TODO: get settings for this user's class requirements month = datetime.date.today().month if not month else int(month) year = datetime.date.today().year if not year else int(year) monthend = calendar.monthrange(year, month)[1] monthname = calendar.month_name[month] rangelogs = self._get_logs_for_range(datetime.datetime(year, month, 1, 0, 0), datetime.datetime(year, month, monthend, 23, 59)) newmcal = calendar.HTMLCalendar(6).formatmonth(year, month) mycal = TAG(newmcal) try: try: daycounts = {parse(k): len(v) for week in rangelogs[year].values() for k, v in week[0].iteritems()} except (TypeError, AttributeError): daycounts = {k: len(v) for week in rangelogs[year].values() for k, v in week[0].iteritems()} # Create html calendar and add daily count numbers for week in mycal.elements('tr'): weekcount = 0 for day in week.elements('td[class!="noday"]'): try: mycount = [v for k, v in daycounts.iteritems() if k.day == int(day[0])][0] countspan = SPAN(mycount, _class='daycount') if mycount >= self.targetcount: countspan['_class'] = 'daycount full' weekcount += 1 day.append(countspan) except (ValueError, IndexError): pass day[0] = SPAN(day[0], _class='cal_num') if weekcount >= 5: week[-1].append(SPAN(_class='icon-ok success')) except KeyError: # if no logs for this month pass dropdown = self._monthpicker(calendar, year, month, monthname) mycal.elements('th.month')[0][0] = dropdown for link in self._navlinks(year, month): mycal.elements('th.month')[0].insert(0, link) wrap = DIV(_class='paideia_monthcal') wrap.append(SPAN('Questions answered each day in', _class='monthcal_intro_line')) wrap.append(mycal) # TODO: Add weekly summary counts to the end of each table return wrap
def materialize_form(form, fields): """ Change layout of SQLFORM forms """ form.add_class("form-horizontal center") main_div = DIV(_class="center") for field_id, label, controls, field_help in fields: curr_div = DIV(_class="row") input_field = None _controls = controls try: _name = controls.attributes["_name"] except: _name = "" try: _type = controls.attributes["_type"] except: _type = "string" try: _id = controls.attributes["_id"] except: _id = "" if isinstance(controls, INPUT): if _type == "file": # Layout for file type inputs input_field = DIV(DIV(SPAN("Upload"), INPUT(_type=_type, _id=_id), _class="btn"), DIV(INPUT(_type="text", _class="file-path", _placeholder=label.components[0]), _class="file-path-wrapper"), _class="col input-field file-field offset-s3 s6") if isinstance(controls, SPAN): # Mostly for ids which cannot be edited by user _controls = INPUT(_value=controls.components[0], _id=_id, _name=_name, _disabled="disabled") elif isinstance(controls, TEXTAREA): # Textarea inputs try: _controls = TEXTAREA(controls.components[0], _name=_name, _id=_id, _class="materialize-textarea text") except IndexError: _controls = TEXTAREA(_name=_name, _id=_id, _class="materialize-textarea text") elif isinstance(controls, SELECT): # Select inputs _controls = SELECT(OPTION(label, _value=""), _name=_name, _class="browser-default", *controls.components[1:]) # Note now label will be the first element # of Select input whose value would be "" label = "" elif isinstance(controls, A): # For the links in the bottom while updating tables like auth_user label = "" elif isinstance(controls, INPUT) is False: # If the values are readonly _controls = INPUT(_value=controls, _name=_name, _disabled="") if input_field is None: input_field = DIV(_controls, label, _class="input-field col offset-s3 s6") curr_div.append(input_field) main_div.append(curr_div) return main_div
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