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(cls, field, value, **attributes): """ Simple and best way to do radio boxes and/or checkboxes """ if isinstance(value, (list, tuple)): value = str(value[0]) else: value = str(value) attr = cls._attributes(field, {}, **attributes) attr['_class'] = add_class(attr.get('_class'), 'radio-widget') # attr['_class'] = 'row' requires = field.requires if not isinstance(requires, (list, tuple)): requires = [requires] if requires: if hasattr(requires[0], 'options'): options = requires[0].options() else: raise SyntaxError('widget cannot determine options of %s' % field) _type = 'checkbox' if getattr(requires[0], 'multiple') else 'radio' options = [(k, v) for k, v in options if str(v)] opts = [] cols = attributes.get('cols', 1) totals = len(options) mods = totals % cols rows = totals / cols if mods: rows += 1 parent, child, inner = DIV, DIV, P for r_index in range(rows): tds = [] for k, v in options[r_index * cols:(r_index + 1) * cols]: checked = {'_checked': 'checked'} if k == value else {} tds.append( inner(INPUT(_type=_type, _id='%s%s' % (field.name, k), _name=field.name, requires=attr.get('requires', None), hideerror=True, _value=k, value=value, **checked), LABEL(v, _for='%s%s' % (field.name, k)), _class="col s12 m%s" % (12 / cols))) opts.append(child(tds, _class='row')) if opts: opts[-1][0][0]['hideerror'] = False if len(opts) == 1: opts[0].attributes.update(attr) return opts[0] return parent(*opts, **attr)
def _render_tag_div(self, label, controls, help): row = DIV(_class='col s12') label.tag = 'SPAN' row.append(DIV( DIV(label, controls[0], _class='btn'), DIV(INPUT(_class='file-path validate', _type='text'), _class='file-path-wrapper'), _class='file-field input-field' )) row.append(A(controls[3], _href=controls[1][1]['_href'])) row.append(DIV( P(LABEL(controls[1][3], SPAN(controls[1][4][0]))) )) 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 widget(cls, field, value, **attributes): """ Turn me on. lol! (or off) """ _id = str(field).replace('.', '_') attributes['_type'] = 'checkbox' return DIV(P(LABEL( 'Off', INPUT(_id=_id, _name=field.name, requires=field.requires, value=value, **attributes), SPAN(_class='lever'), 'On', _for=_id, ), _style='padding:20px'), _class='switch')
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 apply_method(r, **attr): """ Apply method. @param r: the S3Request @param attr: controller options for this request """ if r.representation == "html": T = current.T s3db = current.s3db response = current.response table = r.table tracker = S3Trackable(table, record_id=r.id) title = T("Check-In") get_vars = r.get_vars # Are we being passed a location_id? location_id = get_vars.get("location_id", None) if not location_id: # Are we being passed a lat and lon? lat = get_vars.get("lat", None) if lat is not None: lon = get_vars.get("lon", None) if lon is not None: form_vars = Storage( lat=float(lat), lon=float(lon), ) form = Storage(vars=form_vars) s3db.gis_location_onvalidation(form) location_id = s3db.gis_location.insert(**form_vars) form = None if not location_id: # Give the user a form to check-in # Test the formstyle formstyle = current.deployment_settings.get_ui_formstyle() row = formstyle("test", "test", "test", "test") if isinstance(row, tuple): # Formstyle with separate row for label (e.g. default Eden formstyle) tuple_rows = True else: # Formstyle with just a single row (e.g. Bootstrap, Foundation or DRRPP) tuple_rows = False form_rows = [] comment = "" _id = "location_id" label = LABEL("%s:" % T("Location")) from .s3widgets import S3LocationSelector field = table.location_id #value = tracker.get_location(_fields=["id"], # as_rows=True).first().id value = None # We always want to create a new Location, not update the existing one widget = S3LocationSelector(show_latlon=True)(field, value) row = formstyle("%s__row" % _id, label, widget, comment) if tuple_rows: form_rows.append(row[0]) form_rows.append(row[1]) else: form_rows.append(row) _id = "submit" label = "" widget = INPUT(_type="submit", _value=T("Check-In")) row = formstyle("%s__row" % _id, label, widget, comment) if tuple_rows: form_rows.append(row[0]) form_rows.append(row[1]) else: form_rows.append(row) if tuple_rows: # Assume TRs form = FORM(TABLE(*form_rows)) else: form = FORM(*form_rows) if form.accepts(current.request.vars, current.session): location_id = form.vars.get("location_id", None) if location_id: # We're not Checking-in in S3Track terms (that's about interlocking with another object) #tracker.check_in() #timestmp = form.vars.get("timestmp", None) #if timestmp: # # @ToDo: Convert from string # pass #tracker.set_location(location_id, timestmp=timestmp) tracker.set_location(location_id) response.confirmation = T("Checked-In successfully!") response.view = "check-in.html" output = dict( form=form, title=title, ) return output # @ToDo: JSON representation for check-in from mobile devices else: raise HTTP(415, current.ERROR.BAD_FORMAT)
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 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 None: # The menu itself number_of_links = 0 components = [] append = components.append for submenu in items: append(submenu) number_of_links += len(submenu.elements("a")) # Hide the entire menu if it doesn't contain any links if not number_of_links: return None title = H3(item.label) if item.label else "" menu = DIV( title, DIV( TAG[""](components), _class="icon-bar four-up", ), _id=item.attr._id, _class=item.attr._class, ) return menu else: # A menu item _class = item.attr._class if _class: _class = "%s item" % _class else: _class = "item" _id = item.attr._id icon = item.opts.icon if icon: label = LABEL(ICON(icon), item.label) else: label = LABEL(item.label) return A( label, _class=_class, _href=item.url(), _id=_id, ) 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: # 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 widget( cls, r, record_ids=None, _class="action-lnk", ): """ Render an action item (link or button) to anonymize the provided records @param r: the S3Request @param record_ids: The list of record_ids to act on @param _class: HTML class for the action item @returns: the action item (a HTML helper instance), or an empty string if no anonymize-rules are configured for the target table, no target record was specified or the user is not permitted to anonymize it """ T = current.T default = "" # Determine target table if r.component: resource = r.component if resource.link and not r.actuate_link(): resource = resource.link else: resource = r.resource table = resource.table # Determine target record if not record_ids: return default # Check if target is configured for anonymize rules = resource.get_config("anonymize") if not rules: return default if not isinstance(rules, (tuple, list)): # Single rule rules["name"] = "default" rules = [rules] # Determine widget ID widget_id = "%s-anonymize" % table # Dialog and Form INFO = T( "The following information will be deleted from all the selected records" ) CONFIRM = T("Are you sure you want to delete the selected details?") #SUCCESS = T("Action successful - please wait...") form = FORM( P("%s:" % INFO), cls.selector(rules), P(CONFIRM), DIV( INPUT( value="anonymize_confirm", _name="anonymize_confirm", _type="checkbox", ), LABEL(T("Yes, delete the selected details")), _class="anonymize-confirm", ), DIV( INPUT( _class="small alert button anonymize-submit", _disabled="disabled", _type="submit", _value=T("Anonymize"), ), _class="anonymize-buttons", ), _class="anonymize-form", # Store action key in form hidden={"action-key": cls.action_key(widget_id)}, ) script = '''var submitButton=$('.anonymize-submit'); $('input[name="anonymize_confirm"]').off('.anonymize').on('click.anonymize',function(){if ($(this).prop('checked')){submitButton.prop('disabled',false);}else{submitButton.prop('disabled',true);}});''' current.response.s3.jquery_ready.append(script) return form
def widget( cls, r, label="Anonymize", ajaxURL=None, _class="action-lnk", ): """ Render an action item (link or button) to anonymize the target record of an S3Request, which can be embedded in the record view @param r: the S3Request @param label: The label for the action item @param ajaxURL: The URL for the AJAX request @param _class: HTML class for the action item @returns: the action item (a HTML helper instance), or an empty string if no anonymize-rules are configured for the target table, no target record was specified or the user is not permitted to anonymize it """ T = current.T default = "" # Determine target table if r.component: resource = r.component if resource.link and not r.actuate_link(): resource = resource.link else: resource = r.resource table = resource.table # Determine target record record_id = S3Anonymize._record_id(r) if not record_id: return default # Check if target is configured for anonymize rules = resource.get_config("anonymize") if not rules: return default if not isinstance(rules, (tuple, list)): # Single rule rules["name"] = "default" rules = [rules] # Check permissions to anonymize if not S3Anonymize.permitted(table, record_id): return default # Determine widget ID widget_id = "%s-%s-anonymize" % (table, record_id) # Inject script if ajaxURL is None: ajaxURL = r.url( method="anonymize", representation="json", ) script_options = { "ajaxURL": ajaxURL, } next_url = resource.get_config("anonymize_next") if next_url: script_options["nextURL"] = next_url cls.inject_script(widget_id, script_options) # Action button translated_label = T(label) action_button = A(translated_label, _class="anonymize-btn") if _class: action_button.add_class(_class) # Dialog and Form INFO = T("The following information will be deleted from the record") CONFIRM = T("Are you sure you want to delete the selected details?") SUCCESS = T("Action successful - please wait...") form = FORM( P("%s:" % INFO), cls.selector(rules), P(CONFIRM), DIV( INPUT( value="anonymize_confirm", _name="anonymize_confirm", _type="checkbox", ), LABEL(T("Yes, delete the selected details")), _class="anonymize-confirm", ), cls.buttons(), _class="anonymize-form", # Store action key in form hidden={"action-key": cls.action_key(widget_id)}, ) dialog = DIV( form, DIV( P(SUCCESS), _class="hide anonymize-success", ), _class="anonymize-dialog hide", _title=translated_label, ) # Assemble widget widget = DIV( action_button, dialog, _class="s3-anonymize", _id=widget_id, ) return widget
def _render_tag_input_boolean(self, label, controls, help): row = DIV(_class='input-field col s12') row.append(P(LABEL(controls, SPAN(label[0])))) return row
def __call__(self, field, value, **attributes): """ Widget renderer for the input field; to be set as widget=self for the field returned by the resolve()-method. @param field: the input field @param value: the value to populate the widget @param attributes: attributes for the widget @return: the widget for this form element as HTML helper """ T = current.T settings = current.deployment_settings # Check current value if isinstance(value, str): try: value = json.loads(value) if value else {} except JSONERRORS: value = {} elif not value: value = {} delegation_id = value.get("delegationID") if value else None # Form name and widget ID formname = self._formname() widget_id = attributes.get("_id") if not widget_id: widget_id = str(field).replace(".", "_") # Ajax parameters if delegation_id: ajax_args = [delegation_id, "notifications.json"] ajax_vars = {} else: ajax_args = ["notifications.json"] dtable = current.s3db.hrm_delegation person_id = dtable.person_id.default ajax_vars = { "viewing": "pr_person.%s" % person_id } if person_id else {} # Sender and recipient types sender = self.options.get("sender") if sender: ajax_vars["sender"] = sender notifications = DeploymentNotifications(delegation_id, sender=sender) recipients = list(notifications.recipients.keys()) # Selectable organisations organisations = self.options.get("organisations") # Inject script options = { "ajaxURL": URL( c="hrm", f="delegation", args=ajax_args, vars=ajax_vars, ), "formName": formname, "recipients": recipients, "organisations": organisations, } self.inject_js(widget_id, options) # The widget widget = DIV( INPUT( _type="hidden", _name=field.name, _value=json.dumps(value), _class="notification-data", ), _id=widget_id, ) # Add field set per recipient type labels = { "organisation": T("Requesting Organisation"), "volunteer": T("Volunteer"), "office": T("Office##gov"), } formstyle = settings.get_ui_formstyle() for recipient in recipients: input_name = "%s_%s" % (formname, recipient) formfields = [ Field( "%s_email" % input_name, label=T("Email"), ), Field( "%s_subject" % input_name, label=T("Subject"), widget=self.subject_widget, ), Field( "%s_message" % input_name, "text", label=T("Message"), widget=self.message_widget, ), ] form = SQLFORM.factory(record=None, showid=False, formstyle=formstyle, buttons=[], table_name="sub", *formfields) toggle_name = "%s_notify_%s" % (formname, recipient) toggle_edit = DIV( A( T("Preview"), _class="preview-toggle action-lnk", _style="display:none", ), A( T("Edit"), _class="preview-toggle action-lnk", ), _class="preview-toggles", ) subform = DIV( FIELDSET( LEGEND( LABEL( INPUT( _type="checkbox", _class="notify-toggle", value=True, _name=toggle_name, _id=toggle_name, ), labels.get(recipient, "?"), ), ), form[0], toggle_edit, ), _class="notification", ) widget.append(subform) return widget