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("Services"), "service_location"), (T("Facilities"), "facility"), (T("Projects"), "project"), ] # Use OrganisationRepresent for title to get L10n name if available represent = s3db.org_OrganisationRepresent( acronym=False, parent=False, ) title = represent(record.id) # Retrieve details for the rheader data = resource.select( [ "organisation_organisation_type.organisation_type_id", "country", "website", ], raw_data=True, represent=True, ) row = data.rows[0] raw = row["_row"] # Construct subtitle subtitle_fields = ( "org_organisation_organisation_type.organisation_type_id", "org_organisation.country", ) items = [] for fname in subtitle_fields: if raw[fname]: items.append(s3_unicode(row[fname])) subtitle = ", ".join(items) # Website 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 toolbar(self): from gluon.html import DIV, SCRIPT, BEAUTIFY, TAG, A BUTTON = TAG.button admin = URL("admin", "default", "design", extension='html', args=current.request.application) from gluon.dal import DAL dbstats = [] dbtables = {} infos = DAL.get_instances() for k, v in iteritems(infos): dbstats.append( TABLE(*[ TR(PRE(row[0]), '%.2fms' % (row[1] * 1000)) for row in v['dbstats'] ])) dbtables[k] = dict(defined=v['dbtables']['defined'] or '[no defined tables]', lazy=v['dbtables']['lazy'] or '[no lazy tables]') u = web2py_uuid() backtotop = A('Back to top', _href="#totop-%s" % u) # Convert lazy request.vars from property to Storage so they # will be displayed in the toolbar. request = copy.copy(current.request) request.update(vars=current.request.vars, get_vars=current.request.get_vars, post_vars=current.request.post_vars) return DIV(BUTTON('design', _onclick="document.location='%s'" % admin), BUTTON('request', _onclick="jQuery('#request-%s').slideToggle()" % u), BUTTON('response', _onclick="jQuery('#response-%s').slideToggle()" % u), BUTTON('session', _onclick="jQuery('#session-%s').slideToggle()" % u), BUTTON('db tables', _onclick="jQuery('#db-tables-%s').slideToggle()" % u), BUTTON('db stats', _onclick="jQuery('#db-stats-%s').slideToggle()" % u), DIV(BEAUTIFY(request), backtotop, _class="w2p-toolbar-hidden", _id="request-%s" % u), DIV(BEAUTIFY(current.session), backtotop, _class="w2p-toolbar-hidden", _id="session-%s" % u), DIV(BEAUTIFY(current.response), backtotop, _class="w2p-toolbar-hidden", _id="response-%s" % u), DIV(BEAUTIFY(dbtables), backtotop, _class="w2p-toolbar-hidden", _id="db-tables-%s" % u), DIV(BEAUTIFY(dbstats), backtotop, _class="w2p-toolbar-hidden", _id="db-stats-%s" % u), SCRIPT("jQuery('.w2p-toolbar-hidden').hide()"), _id="totop-%s" % u)
def customise_org_organisation_resource(r, tablename): s3db = current.s3db # Simplify form table = s3db.org_organisation field = table.comments from gluon import DIV field.comment = DIV( _class="tooltip", _title="%s|%s" % (T("About"), T("Describe the organisation, e.g. mission, history and other relevant details" ))) if not current.auth.is_logged_in(): field = table.logo field.readable = field.writable = False # User can create records since we need this during registration, # but we don't want to let the user do this from the list view s3db.configure( "org_organisation", listadd=False, ) # Custom filters to match the information provided from s3 import S3LocationFilter, S3OptionsFilter, S3TextFilter filter_widgets = [ S3TextFilter( [ "name", "acronym", #"website", #"comments", ], label=T("Search"), comment= T("Search by organization name or acronym. You can use * as wildcard." ), ), #S3OptionsFilter("sector_organisation.sector_id", # ), S3OptionsFilter( "organisation_organisation_type.organisation_type_id", label=T("Type"), ), #S3LocationFilter("organisation_location.location_id", # label = T("Areas Served"), # levels = ("L1", "L2", "L3", "L4"), # #hidden = True, # ), ] # CRUD Form from s3 import S3SQLCustomForm, \ S3SQLInlineComponent, \ S3SQLInlineLink, \ S3SQLVerticalSubFormLayout multitype = settings.get_org_organisation_types_multiple() crud_form = S3SQLCustomForm( "name", "acronym", S3SQLInlineLink( "organisation_type", field="organisation_type_id", filter=False, label=T("Type"), multiple=multitype, ), "country", S3SQLInlineLink( "sector", cols=3, label=T("Sectors"), field="sector_id", #required = True, ), (T("About"), "comments"), "website", S3SQLInlineComponent( "facility", label=T("Main Facility"), fields=[ "name", "phone1", "phone2", "email", "location_id", ], layout=S3SQLVerticalSubFormLayout, filterby={ "field": "main_facility", "options": True, }, multiple=False, ), ) s3db.configure( "org_organisation", filter_widgets=filter_widgets, crud_form=crud_form, )
def apply_method(self, r, **attr): """ Entry point for REST API @param r: the request (S3Request) @param attr: REST controller parameters """ if r.record and r.representation in ("html", "aadata"): T = current.T db = current.db s3db = current.s3db auth = current.auth is_admin = auth.s3_has_role("ADMIN") accessible = auth.s3_accessible_query # Profile widgets profile_widgets = [] add_widget = profile_widgets.append dt_row_actions = self.dt_row_actions from s3 import FS # Organisations widget = { "label": T("My Organizations"), "icon": "organisation", "insert": False, "tablename": "org_organisation", "type": "datatable", "actions": dt_row_actions("org", "organisation"), "list_fields": [ "name", (T("Type"), "organisation_organisation_type.organisation_type_id"), "phone", (T("Email"), "email.value"), "website", ], } if not is_admin: otable = s3db.org_organisation rows = db(accessible("update", "org_organisation")).select(otable.id) organisation_ids = [row.id for row in rows] widget["filter"] = FS("id").belongs(organisation_ids) add_widget(widget) # Facilities widget = { "label": T("My Facilities"), "icon": "facility", "insert": False, "tablename": "org_facility", "type": "datatable", "actions": dt_row_actions("org", "facility"), "list_fields": [ "name", "code", "site_facility_type.facility_type_id", "organisation_id", "location_id", ], } if not is_admin: ftable = s3db.org_facility rows = db(accessible("update", "org_facility")).select(ftable.id) facility_ids = [row.id for row in rows] widget["filter"] = FS("id").belongs(facility_ids) add_widget(widget) # Networks (only if user can update any records) widget_filter = None if not is_admin: gtable = s3db.org_group rows = db(accessible("update", "org_group")).select(gtable.id) group_ids = [row.id for row in rows] if group_ids: widget_filter = FS("id").belongs(group_ids) if is_admin or widget_filter: widget = { "label": T("My Networks"), "icon": "org-network", "insert": False, "tablename": "org_group", "filter": widget_filter, "type": "datatable", "actions": dt_row_actions("org", "group"), } add_widget(widget) # Groups (only if user can update any records) widget_filter = None if not is_admin: gtable = s3db.pr_group rows = db(accessible("update", "pr_group")).select(gtable.id) group_ids = [row.id for row in rows] if group_ids: widget_filter = FS("id").belongs(group_ids) if is_admin or widget_filter: widget = { "label": T("My Groups"), "icon": "group", "insert": False, "tablename": "pr_group", "filter": widget_filter, "type": "datatable", "actions": dt_row_actions("hrm", "group"), "list_fields": [ (T("Network"), "group_team.org_group_id"), "name", "description", (T("Chairperson"), "chairperson"), ], } add_widget(widget) # CMS Content from gluon.html import A, DIV, H2, TAG item = None title = T("Dashboard") if current.deployment_settings.has_module("cms"): name = "Dashboard" ctable = s3db.cms_post query = (ctable.name == name) & (ctable.deleted != True) row = db(query).select(ctable.id, ctable.title, ctable.body, limitby=(0, 1)).first() get_vars = { "page": name, "url": URL(args="dashboard", vars={}), } if row: title = row.title if is_admin: item = DIV( XML(row.body), DIV( A( T("Edit"), _href=URL( c="cms", f="post", args=[row.id, "update"], vars=get_vars, ), _class="action-btn", ), _class="cms-edit", ), ) else: item = DIV(XML(row.body)) elif is_admin: item = DIV( DIV( A( T("Edit"), _href=URL( c="cms", f="post", args="create", vars=get_vars, ), _class="action-btn", ), _class="cms-edit", )) # Rheader if r.representation == "html": # Dashboard title profile_header = TAG[""](DIV( DIV( H2(title), _class="medium-6 columns end", ), _class="row", )) # CMS content if item: profile_header.append( DIV( DIV( item, _class="medium-12 columns", ), _class="row", )) # Dashboard links dashboard_links = DIV(A( T("Personal Profile"), _href=URL(c="default", f="person"), _class="action-btn", ), _class="dashboard-links", _style="padding:0.5rem 0;") profile_header.append( DIV( DIV( dashboard_links, _class="medium-12 columns", ), _class="row", )) else: profile_header = None # Configure profile tablename = r.tablename s3db.configure( tablename, profile_cols=2, profile_header=profile_header, profile_widgets=profile_widgets, ) # Render profile from s3 import S3Profile profile = S3Profile() profile.tablename = tablename profile.request = r output = profile.profile(r, **attr) if r.representation == "html": output["title"] = \ current.response.title = T("Personal Dashboard") return output else: r.error(405, current.ERROR.BAD_METHOD)
def LOAD(c=None, f='index', args=None, vars=None, extension=None, target=None, ajax=False, ajax_trap=False, url=None, user_signature=False, timeout=None, times=1, content='loading...', post_vars=Storage(), **attr): """ LOADs a component into the action's document Args: c(str): controller f(str): function args(tuple or list): arguments vars(dict): vars extension(str): extension target(str): id of the target ajax(bool): True to enable AJAX bahaviour ajax_trap(bool): True if `ajax` is set to `True`, traps both links and forms "inside" the target url(str): overrides `c`,`f`,`args` and `vars` user_signature(bool): adds hmac signature to all links with a key that is different for every user timeout(int): in milliseconds, specifies the time to wait before starting the request or the frequency if times is greater than 1 or "infinity" times(integer or str): how many times the component will be requested "infinity" or "continuous" are accepted to reload indefinitely the component """ from gluon.html import TAG, DIV, URL, SCRIPT, XML if args is None: args = [] vars = Storage(vars or {}) target = target or 'c' + str(random.random())[2:] attr['_id'] = target request = current.request if '.' in f: f, extension = f.rsplit('.', 1) if url or ajax: url = url or URL(request.application, c, f, r=request, args=args, vars=vars, extension=extension, user_signature=user_signature) # timing options if isinstance(times, basestring): if times.upper() in ("INFINITY", "CONTINUOUS"): times = "Infinity" else: raise TypeError("Unsupported times argument %s" % times) elif isinstance(times, int): if times <= 0: raise ValueError("Times argument must be greater than zero, 'Infinity' or None") else: raise TypeError("Unsupported times argument type %s" % type(times)) if timeout is not None: if not isinstance(timeout, (int, long)): raise ValueError("Timeout argument must be an integer or None") elif timeout <= 0: raise ValueError( "Timeout argument must be greater than zero or None") statement = "$.web2py.component('%s','%s', %s, %s);" \ % (url, target, timeout, times) attr['_data-w2p_timeout'] = timeout attr['_data-w2p_times'] = times else: statement = "$.web2py.component('%s','%s');" % (url, target) attr['_data-w2p_remote'] = url if not target is None: return DIV(content, **attr) else: if not isinstance(args, (list, tuple)): args = [args] c = c or request.controller other_request = Storage(request) other_request['env'] = Storage(request.env) other_request.controller = c other_request.function = f other_request.extension = extension or request.extension other_request.args = List(args) other_request.vars = vars other_request.get_vars = vars other_request.post_vars = post_vars other_response = Response() other_request.env.path_info = '/' + \ '/'.join([request.application, c, f] + map(str, other_request.args)) other_request.env.query_string = \ vars and URL(vars=vars).split('?')[1] or '' other_request.env.http_web2py_component_location = \ request.env.path_info other_request.cid = target other_request.env.http_web2py_component_element = target other_request.restful = types.MethodType(request.restful.__func__, other_request) # A bit nasty but needed to use LOAD on action decorates with @request.restful() other_response.view = '%s/%s.%s' % (c, f, other_request.extension) other_environment = copy.copy(current.globalenv) # NASTY other_response._view_environment = other_environment other_response.generic_patterns = \ copy.copy(current.response.generic_patterns) other_environment['request'] = other_request other_environment['response'] = other_response ## some magic here because current are thread-locals original_request, current.request = current.request, other_request original_response, current.response = current.response, other_response page = run_controller_in(c, f, other_environment) if isinstance(page, dict): other_response._vars = page other_response._view_environment.update(page) page = run_view_in(other_response._view_environment) current.request, current.response = original_request, original_response js = None if ajax_trap: link = URL(request.application, c, f, r=request, args=args, vars=vars, extension=extension, user_signature=user_signature) js = "$.web2py.trap_form('%s','%s');" % (link, target) script = js and SCRIPT(js, _type="text/javascript") or '' return TAG[''](DIV(XML(page), **attr), script)
def __call__(self): output = {} T = current.T s3 = current.response.s3 auth = current.auth settings = current.deployment_settings roles = current.session.s3.roles system_roles = auth.get_system_roles() # Allow editing of page content from browser using CMS module if settings.has_module("cms"): ADMIN = system_roles.ADMIN in roles s3db = current.s3db table = s3db.cms_post ltable = s3db.cms_post_module module = "default" resource = "index" query = (ltable.module == module) & \ ((ltable.resource == None) | \ (ltable.resource == resource)) & \ (ltable.post_id == table.id) & \ (table.deleted != True) item = current.db(query).select(table.id, table.body, limitby=(0, 1)).first() if item: if ADMIN: item = DIV( XML(item.body), BR(), A(current.T("Edit"), _href=URL(c="cms", f="post", args=[item.id, "update"]), _class="action-btn")) else: item = DIV(XML(item.body)) elif ADMIN: if s3.crud.formstyle == "bootstrap": _class = "btn" else: _class = "action-btn" item = A(T("Edit"), _href=URL(c="cms", f="post", args="create", vars={ "module": module, "resource": resource }), _class="%s cms-edit" % _class) else: item = "" else: item = "" output["item"] = item # Login/Registration forms self_registration = settings.get_security_registration_visible() registered = False login_form = None login_div = None register_form = None register_div = None # Check logged in and permissions if system_roles.AUTHENTICATED not in roles: login_buttons = DIV(A(T("Login"), _id="show-login", _class="tiny secondary button"), _id="login-buttons") # @ToDo: Move JS to static script = ''' $('#show-intro').click(function(e){ e.preventDefault() $('#intro').slideDown(400, function() { $('#login_box').hide() }); }) $('#show-login').click(function(e){ e.preventDefault() $('#login_form').show() $('#register_form').hide() $('#login_box').show() $('#intro').slideUp() })''' s3.jquery_ready.append(script) # This user isn't yet logged-in if "registered" in current.request.cookies: # This browser has logged-in before registered = True if self_registration is True: # Provide a Registration box on front page login_buttons.append( A( T("Register"), _id="show-register", _class="tiny secondary button", # @ToDo: Move to CSS _style="margin-left:5px")) script = ''' $('#show-register').click(function(e){ e.preventDefault() $('#login_form').hide() $('#register_form').show() $('#login_box').show() $('#intro').slideUp() })''' s3.jquery_ready.append(script) register_form = auth.register() register_div = DIV(H3(T("Register")), P(XML(T("If you would like to help, then please %(sign_up_now)s") % \ dict(sign_up_now=B(T("sign-up now")))))) register_script = ''' $('#register-btn').click(function(e){ e.preventDefault() $('#register_form').show() $('#login_form').hide() }) $('#login-btn').click(function(e){ e.preventDefault() $('#register_form').hide() $('#login_form').show() })''' s3.jquery_ready.append(register_script) # Provide a login box on front page auth.messages.submit_button = T("Login") login_form = auth.login(inline=True) login_div = DIV(H3(T("Login")), P(XML(T("Registered users can %(login)s to access the system") % \ dict(login=B(T("login")))))) else: login_buttons = "" output["login_buttons"] = login_buttons output["self_registration"] = self_registration output["registered"] = registered output["login_div"] = login_div output["login_form"] = login_form output["register_div"] = register_div output["register_form"] = register_form output["items"] = network()() self._view(THEME, "index.html") return output
def __call__(self): request = current.request response = current.response s3 = response.s3 settings = current.deployment_settings if request.env.request_method == "POST": # Processs Form vars = request.post_vars result = current.msg.send_email( to=settings.get_mail_approver(), subject=vars.subject, message=vars.message, reply_to=vars.address, ) if result: response.confirmation = "Thankyou for your message - we'll be in touch shortly" T = current.T # Allow editing of page content from browser using CMS module if settings.has_module("cms"): ADMIN = current.auth.get_system_roles().ADMIN in \ current.session.s3.roles s3db = current.s3db table = s3db.cms_post ltable = s3db.cms_post_module module = "default" resource = "contact" query = (ltable.module == module) & \ ((ltable.resource == None) | \ (ltable.resource == resource)) & \ (ltable.post_id == table.id) & \ (table.deleted != True) item = current.db(query).select(table.id, table.body, limitby=(0, 1)).first() if item: if ADMIN: item = DIV( XML(item.body), BR(), A(T("Edit"), _href=URL(c="cms", f="post", args=[item.id, "update"]), _class="action-btn")) else: item = DIV(XML(item.body)) elif ADMIN: if s3.crud.formstyle == "bootstrap": _class = "btn" else: _class = "action-btn" item = A(T("Edit"), _href=URL(c="cms", f="post", args="create", vars={ "module": module, "resource": resource }), _class="%s cms-edit" % _class) else: item = "" else: item = "" form = FORM(TABLE( TR(LABEL("Your name:", SPAN(" *", _class="req"), _for="name")), TR(INPUT(_name="name", _type="text", _size=62, _maxlength="255")), TR( LABEL("Your e-mail address:", SPAN(" *", _class="req"), _for="address")), TR(INPUT(_name="address", _type="text", _size=62, _maxlength="255")), TR(LABEL("Subject:", SPAN(" *", _class="req"), _for="subject")), TR(INPUT(_name="subject", _type="text", _size=62, _maxlength="255")), TR(LABEL("Message:", SPAN(" *", _class="req"), _for="name")), TR(TEXTAREA(_name="message", _class="resizable", _rows=5, _cols=62)), TR(INPUT(_type="submit", _value="Send e-mail")), ), _id="mailform") if s3.cdn: if s3.debug: s3.scripts.append( "http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.js" ) else: s3.scripts.append( "http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js" ) else: if s3.debug: s3.scripts.append("/%s/static/scripts/jquery.validate.js" % request.application) else: s3.scripts.append("/%s/static/scripts/jquery.validate.min.js" % request.application) # @ToDo: Move to static with i18n s3.jquery_ready.append('''$('#mailform').validate({ errorClass:'req', rules:{ name:{ required:true }, subject:{ required:true }, message:{ required:true }, name:{ required:true }, address: { required:true, email:true } }, messages:{ name:"Enter your name", subject:"Enter a subject", message:"Enter a message", address:{ required:"Please enter a valid email address", email:"Please enter a valid email address" } }, errorPlacement:function(error,element){ error.appendTo(element.parents('tr').prev().children()) }, submitHandler:function(form){ form.submit() } })''') # @ToDo: Move to static s3.jquery_ready.append( '''$('textarea.resizable:not(.textarea-processed)').each(function() { // Avoid non-processed teasers. if ($(this).is(('textarea.teaser:not(.teaser-processed)'))) { return false; } var textarea = $(this).addClass('textarea-processed'), staticOffset = null; // When wrapping the text area, work around an IE margin bug. See: // http://jaspan.com/ie-inherited-margin-bug-form-elements-and-haslayout $(this).wrap('<div class="resizable-textarea"><span></span></div>') .parent().append($('<div class="grippie"></div>').mousedown(startDrag)); var grippie = $('div.grippie', $(this).parent())[0]; grippie.style.marginRight = (grippie.offsetWidth - $(this)[0].offsetWidth) +'px'; function startDrag(e) { staticOffset = textarea.height() - e.pageY; textarea.css('opacity', 0.25); $(document).mousemove(performDrag).mouseup(endDrag); return false; } function performDrag(e) { textarea.height(Math.max(32, staticOffset + e.pageY) + 'px'); return false; } function endDrag(e) { $(document).unbind("mousemove", performDrag).unbind("mouseup", endDrag); textarea.css('opacity', 1); } });''') response.title = "Contact | NYC:Prepared" self._view(THEME, "contact.html") return dict( form=form, item=item, )
def formstyle_bootstrap_modal(form, fields, **kwargs): """" Bootstrap format modal form layout """ span = kwargs.get('span') or 'span8' select_attributes = kwargs.get('select_attributes', '') form.add_class('form-horizontal') parent = FIELDSET() for id, label, controls, help in fields: _controls = DIV(controls, _class='controls') # submit unflag by default _submit = False if isinstance(controls, INPUT): controls.add_class(span) if controls['_type'] == 'submit': # flag submit button _submit = True controls['_class'] = 'btn btn-primary' if controls['_type'] == 'file': controls['_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(span) if isinstance(controls, SELECT): controls.add_class(span) if isinstance(controls, TEXTAREA): controls.add_class(span) if isinstance(label, LABEL): label['_class'] = 'control-label' if help: label.append( I(_class="icon-question-sign", _rel="tooltip", **{'_data-content': help})) if _submit: # submit button has unwrapped label and controls, different class parent.append( DIV(label, BUTTON("Close", _class="btn", **{ '_data-dismiss': 'modal', '_aria-hidden': True }), controls, _class='modal-footer', _id=id)) # unflag submit (possible side effect) _submit = False else: # unwrapped label _class = 'control-group' parent.append(DIV(label, _controls, _class=_class, _id=id)) # append tooltip and chosen field attributes if 'id' not in form.attributes: form.attributes['_id'] = "%s-id" % (str(form.table)) script_data = """$(document).ready(function() {{ $("[rel=tooltip]").popover({{ placement: 'right', trigger: 'hover', }}); $('#{0:s} select').select2({{{1:s}}}); {2:s} }});""".format(form.attributes['_id'], select_attributes, kwargs.get('script', '')) parent.append(SCRIPT(script_data)) return parent
def test_DIV(self): # Empty DIV() self.assertEqual(DIV().xml(), b'<div></div>') self.assertEqual( DIV('<>', _a='1', _b='2').xml(), b'<div a="1" b="2"><></div>') # attributes can be updated like in a dict div = DIV('<>', _a='1') div['_b'] = '2' self.assertEqual(div.xml(), b'<div a="1" b="2"><></div>') # also with a mapping div.update(_b=2, _c=3) self.assertEqual(div.xml(), b'<div a="1" b="2" c="3"><></div>') # length of the DIV is the number of components self.assertEqual(len(DIV('a', 'bc')), 2) # also if empty, DIV is True in a boolean evaluation self.assertTrue(True if DIV() else False) # parent and siblings a = DIV(SPAN('a'), DIV('b')) s = a.element('span') d = s.parent d['_class'] = 'abc' self.assertEqual(a.xml(), b'<div class="abc"><span>a</span><div>b</div></div>') self.assertEqual([el.xml() for el in s.siblings()], [b'<div>b</div>']) self.assertEqual(s.sibling().xml(), b'<div>b</div>') # siblings with wrong args self.assertEqual(s.siblings('a'), []) # siblings with good args self.assertEqual(s.siblings('div')[0].xml(), b'<div>b</div>') # Check for siblings with wrong kargs and value self.assertEqual(s.siblings(a='d'), []) # Check for siblings with good kargs and value # Can't figure this one out what is a right value here?? # Commented for now... # self.assertEqual(s.siblings(div='<div>b</div>'), ???) # No other sibling should return None self.assertEqual(DIV(P('First element')).element('p').sibling(), None) # -------------------------------------------------------------------------------------------------------------- # This use unicode to hit xmlescape() line : # """ # elif isinstance(data, unicode): # data = data.encode('utf8', 'xmlcharrefreplace') # """ self.assertEqual( DIV(u'Texte en français avec des caractères accentués...').xml(), b'<div>Texte en fran\xc3\xa7ais avec des caract\xc3\xa8res accentu\xc3\xa9s...</div>' ) # -------------------------------------------------------------------------------------------------------------- self.assertEqual( DIV('Test with an ID', _id='id-of-the-element').xml(), b'<div id="id-of-the-element">Test with an ID</div>') self.assertEqual(DIV().element('p'), None) # Corner case for raise coverage of one line # I think such assert fail cause of python 2.6 # Work under python 2.7 # with self.assertRaises(SyntaxError) as cm: # DIV(BR('<>')).xml() # self.assertEqual(cm.exception[0], '<br/> tags cannot have components') # test .get('attrib') self.assertEqual( DIV('<p>Test</p>', _class="class_test").get('_class'), 'class_test')
def customise_org_organisation_resource(r, tablename): s3db = current.s3db # Use comments field for org description table = s3db.org_organisation field = table.comments from gluon import DIV field.comment = DIV( _class="tooltip", _title="%s|%s" % (T("About"), T("Describe the organisation, e.g. mission, history and other relevant details" ))) if not current.auth.is_logged_in(): field = table.logo field.readable = field.writable = False # User can create records since we need this during registration, # but we don't want to let the user do this from the list view s3db.configure( "org_organisation", listadd=False, ) # Custom filters to match the information provided from s3 import S3LocationFilter, \ S3OptionsFilter, \ S3TextFilter, \ s3_get_filter_opts filter_widgets = [ S3TextFilter( [ "name", "acronym", #"website", #"comments", ], label=T("Search"), comment= T("Search by organization name or acronym. You can use * as wildcard." ), ), S3OptionsFilter( "organisation_organisation_type.organisation_type_id", label=T("Type"), ), S3OptionsFilter( "service_location.service_location_service.service_id", options=s3_get_filter_opts( "org_service", translate=True, ), ), S3OptionsFilter( "sector_organisation.sector_id", options=s3_get_filter_opts( "org_sector", translate=True, ), hidden=True, ), ] # CRUD Form from s3 import S3SQLCustomForm, \ S3SQLInlineComponent, \ S3SQLInlineLink, \ S3SQLVerticalSubFormLayout multitype = settings.get_org_organisation_types_multiple() crud_form = S3SQLCustomForm( "name", "acronym", S3SQLInlineLink( "organisation_type", field="organisation_type_id", filter=False, label=T("Type"), multiple=multitype, ), "country", S3SQLInlineLink( "sector", cols=3, label=T("Sectors"), field="sector_id", #required = True, ), (T("About"), "comments"), "website", S3SQLInlineComponent( "contact", name="email", label=T("Email"), #multiple = False, fields=[ ("", "value"), ], filterby=[ { "field": "contact_method", "options": "EMAIL", }, ], ), S3SQLInlineComponent( "facility", label=T("Main Office"), fields=[ "name", "phone1", "phone2", #"email", "location_id", ], layout=S3SQLVerticalSubFormLayout, filterby={ "field": "main_facility", "options": True, }, multiple=False, ), S3SQLInlineComponent( "document", fields=[ (T("Title"), "name"), "file", ], filterby={ "field": "file", "options": "", "invert": True, }, label=T("Files"), name="file", ), S3SQLInlineComponent( "document", fields=[ (T("Title"), "name"), "url", ], filterby={ "field": "url", "options": None, "invert": True, }, label=T("Links"), name="url", ), ) s3db.configure( "org_organisation", filter_widgets=filter_widgets, crud_form=crud_form, )
def __call__(self, field, value): mylogger.debug(message='current.request.vars:%s' % current.request.vars) mylogger.debug(message='field._tablename:%s' % (str(field._tablename))) mylogger.debug(message='field:%s' % (str(field))) mylogger.debug(message='field.name:%s' % (str(field.name))) mylogger.debug(message='field.type:%s' % (str(field.type))) mylogger.debug(message='field.requires:%s' % (str(field.requires))) mylogger.debug(message='type(value):%s' % (str(type(value)))) mylogger.debug(message='value:%s' % (str(value))) if current.request and current.request['function']: function = current.request['function'] function_configuration = self.configuration[ '*'] if self.configuration.keys().count( '*') > 0 else self.configuration[ function] if function in self.configuration.keys() else '' # query parameter not used yet... if 'query' in function_configuration: query = function_configuration['query'].as_json() else: query = None if 'disable_validate' in function_configuration: disable_validate = function_configuration['disable_validate'] else: disable_validate = False if 'add_in_db' in function_configuration: add_in_db = function_configuration['add_in_db'] else: add_in_db = False if 'multiple' in function_configuration: multiple = function_configuration['multiple'] else: multiple = False if 'submit_on_select' in function_configuration: submit_on_select = function_configuration['submit_on_select'] else: submit_on_select = False max_nb_item = 20 if 'max_nb_item' in function_configuration: max_nb_item = function_configuration['max_nb_item'] func_lambda = '' if 'func_lambda' in function_configuration: func_lambda = function_configuration['func_lambda'] # use this option for no required fields only, to force the user to confirm that the field is empty if 'confirm_empty' in function_configuration: confirm_empty = function_configuration['confirm_empty'] else: confirm_empty = current.request.vars[ 'confirm_empty_%s' % field. name] == 'on' if 'confirm_empty_%s' % field.name in current.request.vars else False is_not_a_reference = (field._tablename == self.ref_field._tablename) disabled = '_disabled' in self.attributes.keys() mylogger.debug(message='add_in_db:%s' % (str(add_in_db))) mylogger.debug(message='multiple:%s' % (str(multiple))) mylogger.debug(message='disabled:%s' % (str(disabled))) mylogger.debug(message='max_nb_item:%s' % (str(max_nb_item))) mylogger.debug(message='is_not_a_reference:%s' % (str(is_not_a_reference))) if (value) and (type(value) is StringType) and (value == '0'): nb_item = 0 elif (value) and (type(value) is StringType) and (value == '|0|'): nb_item = 0 elif (value) and (type(value) is ListType) and (value[0] == 0): nb_item = 0 elif (value) and (type(value) is ListType) and (value[0] == '|0|'): nb_item = 0 elif (value) and (type(value) is ListType): nb_item = len(value) elif value and value != '': nb_item = 1 else: nb_item = 0 if value and not type(value) is ListType and value != '': value = [value] mylogger.debug(message='nb_item:%s' % (str(nb_item))) # # basic widget structure # checkboxes_form = DIV() suggestions_form = DIV( _id='%s_suggestions' % (self.uid), _class='CHIMITHEQUE_MULTIPLE_widget_suggestions') message_form = DIV(_id='%s_message' % (self.uid), _class='CHIMITHEQUE_MULTIPLE_widget_message', _style='display: none;') search_input_form = DIV(INPUT(_name='%s_search' % self.uid, _type='text', _title='%s_search' % self.uid), suggestions_form, _id='%s_search' % (self.uid), _class='search_input_form') # # adding a confirm empty checkbox if needed # if confirm_empty: confirm_empty_form = DIV( INPUT(_name='confirm_empty_%s' % field.name, _id='confirm_empty_%s' % field.name, _type='checkbox', _title=self.text_confirm_empty_form_field, _class='CHIMITHEQUE_MULTIPLE_widget_confirm_empty', _onclick='''$('div[id=%(uid)s]').empty(); if ($('input[type=checkbox][name=confirm_empty_%(field_name)s]').is(':checked')) { $('div[id=%(uid)s]').append('<span id="%(field_name)s_span_no_selected"></span>'); } else { $('div[id=%(uid)s]').append('<span id="%(field_name)s_span_no_selected">%(no_item_selected)s</span>'); } ''' % { 'uid': self.uid, 'field_name': field.name, 'no_item_selected': self.text_no_item_selected })) confirm_empty_form.append( IMG(_src=self.image_disable_url, _alt='disable', _id='%s_disable' % self.uid, _title=self.text_confirm_empty_form_field)) else: confirm_empty_form = DIV() # # building the AJAX query parameters # _ajax_parameters = { 'uid': self.uid, 'multiple': multiple, 'disable_validate': disable_validate, 'add_in_db': add_in_db, 'field_tablename': field._tablename, 'ref_field_tablename': self.ref_field._tablename, 'ref_field_name': self.ref_field.name, 'max_nb_item': max_nb_item, 'max_item_length': self.max_item_length, 'lambda': func_lambda, 'query': query, 'text_close_list': str(self.text_close_list), 'text_submit': str(self.text_submit), 'image_select_url': self.image_select_url, 'submit_on_select': submit_on_select } ajax_parameters = json.dumps(_ajax_parameters) # # adding the "add" image # if not disabled and add_in_db: search_input_form.append( IMG(_src=self.image_insert_url, _alt='submit', _id='%s_add' % self.uid, _title=self.text_submit, _style='visibility: hidden;', _class='CHIMITHEQUE_MULTIPLE_widget_addindb', _onclick=''' // adding the search parameter to the JSON object ajax_parameters = %(ajax_parameters)s; ajax_parameters["search"] = $('input[name=%(uid)s_search]').val(); var ret = $.ajax({ type: "POST", url: "/%(application)s/chimitheque_multiple_widget/item_add", data: JSON.stringify(ajax_parameters), dataType: "json", contentType: "application/json; charset=utf-8", async: false }).done(function(data) { var _action = data['action']; var _id = data['id']; var _val = data['val']; var _encval = data['encval']; var funcCall = "addReplaceCheckBox%(uid)s" + "('" + _action + "','" + _id + "','" + _val + "','" + _encval + "')"; eval(funcCall); $('img#%(uid)s_add').attr('style', 'visibility: hidden;'); }); ''' % { 'uid': self.uid, 'application': current.request.application, 'ajax_parameters': ajax_parameters })) # # adding the selected items DIV # if nb_item == 0: if 'confirm_empty_%s' % field.name in current.request.vars: checkboxes_form.append(SPAN()) else: checkboxes_form.append( SPAN(XML(self.text_no_item_selected), _id='%s_span_no_selected' % field.name)) hidden_box_form = DIV( INPUT(_name='%s' % field.name, _id='%s_hidden' % field.name, _type='checkbox', _value='', _style='visibility: hidden; height: 0px;', _checked='checked', requires=field.requires)) else: hidden_box_form = DIV() # # prepopulating the form # for i in range(0, nb_item): mylogger.debug(message='i:%i' % (i)) prepop_value_id = None prepop_value_label = None if is_not_a_reference: # just populating with the value passed in parameter mylogger.debug(message='case 1') prepop_value_id = value[i] prepop_value_label = value[i] else: # the parameter value is an id in the reference table, then querying the table mylogger.debug(message='case 2') prepop_value = current.db( current.db['%s' % self.ref_field._tablename]['id'] == ( value[i])).select().first() if prepop_value is not None: prepop_value_label = current.db[ '%s' % self.ref_field._tablename]._format(prepop_value) prepop_value_id = value[i] mylogger.debug(message='prepop_value_id:%s' % prepop_value_id) mylogger.debug(message='prepop_value_label:%s' % prepop_value_label) if prepop_value_id: # # adding the checkboxes or radio for the selected items # if multiple: _input = INPUT( _name='%s' % field.name, _id='%s' % field.name, _type='checkbox', _class='CHIMITHEQUE_MULTIPLE_widget_selected', _encvalue=self.uid, _value=prepop_value_id, value=True, requires=field.requires) else: if is_not_a_reference: _input = INPUT( _name='%s' % field.name, _id='%s' % field.name, _type='radio', _class='CHIMITHEQUE_MULTIPLE_widget_selected', _encvalue=self.uid, _value= prepop_value_label, # or prepop_value_id, don't mind... value= prepop_value_label, # or prepop_value_id, don't mind... requires=field.requires) else: _input = INPUT( _name='%s' % field.name, _id='%s' % field.name, _type='radio', _class='CHIMITHEQUE_MULTIPLE_widget_selected', _encvalue=self.uid, _value=prepop_value_id, value=prepop_value_id, requires=field.requires) # # then the delete selected item image # if not disabled and not multiple: img_del = IMG(_src=self.image_delete_url, _alt=self.text_delete, _title=self.text_delete, _onclick='deleteItem%s();' % self.uid, _style='float: left;') else: img_del = SPAN() # # then the label # checkboxes_form.append( DIV(_input, img_del, XML('%s' % prepop_value_label), _class='CHIMITHEQUE_MULTIPLE_widget_selected')) else: # TODO: code identical to line 232... if 'confirm_empty_%s' % field.name in current.request.vars: checkboxes_form.append(SPAN()) else: checkboxes_form.append( SPAN(XML(self.text_no_item_selected), _id='%s_span_no_selected' % field.name)) hidden_box_form = DIV( INPUT(_name='%s' % field.name, _id='%s_hidden' % field.name, _type='checkbox', _value='', _style='visibility: hidden; height: 0px;', _checked='checked', requires=field.requires)) # # building the final form # final_form = DIV( DIV( DIV(checkboxes_form, _id='%s' % self.uid, _class='%s_%s' % (self.ref_field._tablename, self.ref_field.name)), **self.attributes)) if not disabled: final_form.insert(0, confirm_empty_form) final_form.insert(0, search_input_form) # hidden field to export the uid for the pages uid_field = INPUT(_name='uid_%s' % field.name, _type='hidden', value='%s' % self.uid, style='visibility: hidden; height: 0px;') return DIV(final_form, uid_field, hidden_box_form, message_form, SCRIPT( """ function disableAddButton%(uid)s() { $('#%(uid)s_add').attr('style', 'visibility: hidden;'); } function displayMessage%(uid)s(message) { $('#%(uid)s_message span').remove(); $('#%(uid)s_message').append('<span class="error">' + message + '</span>'); } function deleteItem%(uid)s() { $('#%(uid)s').find('div[class=CHIMITHEQUE_MULTIPLE_widget_selected]').remove(); console.log($('input[name=%(field_name)s]').length); /* enabling the hidden field if needed */ if ($('input[name=%(field_name)s]').length <= 1) { console.log("input name '%(field_name)s' was the last element"); $('input[id=%(field_name)s_hidden]').removeAttr('disabled'); $('div[id=%(uid)s]').append('<span id="%(field_name)s_span_no_selected">%(no_item_selected)s</span>'); } else { console.log("input name '%(field_name)s' was not the last element"); } } function addReplaceCheckBox%(uid)s(action, id, val, encval) { console.log(arguments.callee.name); console.log('action:' + action); console.log('id:' + id); console.log('val:' + val); console.log('encval:' + encval); /* base64 decoding the string */ val = Base64.decode(val); /* disabling the hidden field */ $('input[id=%(field_name)s_hidden]').attr('disabled','true'); $('span[id=%(field_name)s_span_no_selected]').remove(); if ($('#%(uid)s').find('input[value="'+id+'"][encvalue='+encval+']').length != 0) { alert('%(text_item_already_selected)s'); } else { var newDiv = $('<div class="CHIMITHEQUE_MULTIPLE_widget_selected"/>'); var newDel = $('<img/>').attr({ 'src': '%(image_delete_url)s', 'alt': '%(image_delete_alt)s', 'title': '%(image_delete_title)s', 'onclick': 'deleteItem%(uid)s();' }); var newElem = $('<input/>').attr({ 'id': '%(field_name)s', 'type': '%(type)s', 'checked': 'checked', 'name': '%(field_name)s', 'value': id, 'class': 'CHIMITHEQUE_MULTIPLE_widget_selected', 'encvalue': encval, }); if (action == 'replace') { newDiv.append(newDel); } newDiv.append(newElem); newDiv.append(val); if (action == 'replace') { $('#%(uid)s div').remove(); } $('#%(uid)s').append(newDiv); } $('input[name=%(uid)s_search]').val(''); $('#' + encval + '_suggestions div').remove(); } function autocomplete%(uid)s() { $elem = $('input[type=text][name=%(uid)s_search]') var inputLength = $elem.val().length; if (inputLength >= %(minchar)s) { // adding the search parameter to the JSON object ajax_parameters = %(ajax_parameters)s; ajax_parameters["search"] = $elem.val(); var ret = $.ajax({ type: "POST", url: "/%(application)s/chimitheque_multiple_widget/item_selector", data: JSON.stringify(ajax_parameters), dataType: "json", contentType: "application/json; charset=utf-8", async: false }).responseText; $('#%(uid)s_suggestions > *').remove(); $('#%(uid)s_message').show(); $('#%(uid)s_message').text(''); if (ret.substr(0, 5) == 'ERROR') { $('#%(uid)s_message').text(ret); $('#%(uid)s_add').attr('style', 'visibility: hidden;'); }else if (ret.substr(0, 4) == 'INDB'){ $('#%(uid)s_add').attr('style', 'visibility: hidden;'); $('#%(uid)s_suggestions').append(ret); }else if (ret.substr(0, 4) == 'NONE'){ $('#%(uid)s_add').attr('style', 'visibility: visible;'); } else { $('#%(uid)s_add').attr('style', 'visibility: visible;'); $('#%(uid)s_suggestions').append(ret); } } } $(document).ready(function() { jQuery('input[type=text][name=%(uid)s_search]').bind('paste', function(e) { setTimeout(function() { autocomplete%(uid)s(); }, 0); }); timer = 0; jQuery('input[type=text][name=%(uid)s_search]').bind('keypress click paste input',function() { if (timer) { clearTimeout(timer); } timer = setTimeout(autocomplete%(uid)s, 400); }); }); """ % { 'disable_validate': disable_validate, 'add_in_db': add_in_db, 'multiple': multiple, 'uid': self.uid, 'field_tablename': field._tablename, 'field_name': field.name, 'field_label': field.label, 'ref_field_tablename': self.ref_field._tablename, 'ref_field_name': self.ref_field.name, 'minchar': self.minchar, 'image_delete_url': self.image_delete_url, 'image_delete_alt': self.text_delete, 'image_delete_title': self.text_delete, 'type': 'checkbox' if multiple else 'radio', 'max_nb_item': max_nb_item, 'max_item_length': self.max_item_length, 'lambda': func_lambda, 'image_delete_small': self.image_delete_url, 'text_item_already_selected': self.text_item_already_selected, 'no_item_selected': self.text_no_item_selected, 'application': current.request.application, 'ajax_parameters': ajax_parameters }), _class='CHIMITHEQUE_MULTIPLE_widget')
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("Services"), "service_location"), (T("Facilities"), "facility"), (T("Projects"), "project"), (T("Attachments"), "document"), ] # Use OrganisationRepresent for title to get L10n name if available represent = s3db.org_OrganisationRepresent( acronym=False, parent=False, ) title = represent(record.id) # Retrieve details for the rheader data = resource.select( [ "organisation_organisation_type.organisation_type_id", "country", "website", ], raw_data=True, represent=True, ) row = data.rows[0] raw = row["_row"] # Construct subtitle subtitle_fields = ( "org_organisation_organisation_type.organisation_type_id", "org_organisation.country", ) items = [] for fname in subtitle_fields: if raw[fname]: items.append(s3_unicode(row[fname])) subtitle = ", ".join(items) # Website website = row["org_organisation.website"] # Compose the rheader rheader = DIV( DIV( H1(title), H2(subtitle), website if record.website else "", _class="rheader-details", ), ) elif tablename == "project_project": if not tabs: tabs = [ (T("About"), None), (T("Locations"), "location"), (T("Attachments"), "document"), ] # Retrieve details for the rheader data = resource.select( [ "name", "organisation_id", ], represent=True, ) row = data.rows[0] # Title and Subtitle title = row["project_project.name"] subtitle = row["project_project.organisation_id"] # Compose the rheader rheader = DIV(DIV( H1(title), H2(subtitle), _class="rheader-details", ), ) elif tablename == "pr_person": if not tabs: tabs = [ (T("Person Details"), None), ] from s3 import s3_fullname title = s3_fullname(record) # Link organisation_id representation to staff tab linkto = URL( c="org", f="organisation", args=["[id]", "human_resource"], ) htable = s3db.hrm_human_resource field = htable.organisation_id field.represent = s3db.org_OrganisationRepresent( show_link=True, linkto=linkto, ) # Retrieve details for the rheader data = resource.select( [ "human_resource.job_title_id", "human_resource.organisation_id", ], raw_data=True, represent=True, ) row = data.rows[0] raw = row["_row"] # Construct subtitle organisation_id = raw["hrm_human_resource.organisation_id"] if organisation_id: subtitle = row["hrm_human_resource.organisation_id"] job_title_id = raw["hrm_human_resource.job_title_id"] if job_title_id: subtitle = TAG[""]( "%s, " % row["hrm_human_resource.job_title_id"], subtitle, ) # Compose the rheader rheader = DIV(DIV( H1(title), H2(subtitle), _class="rheader-details", ), ) if tabs: rheader_tabs = s3_rheader_tabs(r, tabs) rheader.append(rheader_tabs) return rheader
def customize_deploy_mission(**attr): """ Customize deploy_mission controller """ db = current.db s3db = current.s3db s3 = current.response.s3 MEMBER = T("Member") from gluon.html import DIV hr_comment = \ DIV(_class="tooltip", _title="%s|%s" % (MEMBER, T("Enter some characters to bring up " "a list of possible matches"))) table = s3db.deploy_mission table.code.label = T("Operation Code") table.event_type_id.label = T("Disaster Type") table.organisation_id.readable = table.organisation_id.writable = False # Restrict Location to just Countries from s3.s3fields import S3Represent from s3.s3widgets import S3SelectChosenWidget field = table.location_id field.label = current.messages.COUNTRY field.requires = s3db.gis_country_requires field.widget = S3SelectChosenWidget() field.represent = S3Represent(lookup="gis_location", translate=True) rtable = s3db.deploy_response rtable.human_resource_id.label = MEMBER rtable.human_resource_id.comment = hr_comment from s3.s3validators import IS_ONE_OF atable = s3db.deploy_assignment atable.human_resource_id.label = MEMBER atable.human_resource_id.comment = hr_comment field = atable.job_title_id field.comment = None field.label = T("Sector") field.requires = IS_ONE_OF( db, "hrm_job_title.id", field.represent, filterby="type", filter_opts=(4, ), ) # CRUD Strings s3.crud_strings["deploy_assignment"] = Storage( title_create=T("New Deployment"), title_display=T("Deployment Details"), title_list=T("Deployments"), title_update=T("Edit Deployment Details"), title_search=T("Search Deployments"), title_upload=T("Import Deployments"), subtitle_create=T("Add New Deployment"), label_list_button=T("List Deployments"), label_create_button=T("Add Deployment"), label_delete_button=T("Delete Deployment"), msg_record_created=T("Deployment added"), msg_record_modified=T("Deployment Details updated"), msg_record_deleted=T("Deployment deleted"), msg_list_empty=T("No Deployments currently registered")) # Custom prep standard_prep = s3.prep def custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) else: result = True if not r.component and r.method == "create": # Org is always IFRC otable = s3db.org_organisation query = ( otable.name == "International Federation of Red Cross and Red Crescent Societies" ) organisation = db(query).select( otable.id, limitby=(0, 1), ).first() if organisation: r.table.organisation_id.default = organisation.id return result s3.prep = custom_prep return attr
def rdrt_member_profile_header(r): """ Custom profile header to allow update of RDRT roster status """ record = r.record if not record: return "" person_id = record.person_id from s3 import s3_fullname, s3_avatar_represent name = s3_fullname(person_id) table = r.table # Organisation comments = table.organisation_id.represent(record.organisation_id) from s3 import s3_unicode from gluon.html import A, DIV, H2, LABEL, P, SPAN # Add job title if present job_title_id = record.job_title_id if job_title_id: comments = (SPAN("%s, " % \ s3_unicode(table.job_title_id.represent(job_title_id))), comments) # Determine the current roster membership status (active/inactive) atable = current.s3db.deploy_application status = atable.active query = atable.human_resource_id == r.id row = current.db(query).select(atable.id, atable.active, limitby=(0, 1)).first() if row: active = 1 if row.active else 0 status_id = row.id roster_status = status.represent(row.active) else: active = None status_id = None roster_status = current.messages.UNKNOWN_OPT if status_id and \ current.auth.s3_has_permission("update", "deploy_application", record_id=status_id): # Make inline-editable roster_status = A( roster_status, data={"status": active}, _id="rdrt-roster-status", _title=T("Click to edit"), ) s3 = current.response.s3 script = "/%s/static/themes/IFRC/js/rdrt.js" % r.application if script not in s3.scripts: s3.scripts.append(script) script = '''$.rdrtStatus('%(url)s','%(active)s','%(inactive)s','%(submit)s')''' from gluon import URL options = { "url": URL(c="deploy", f="application", args=["%s.s3json" % status_id]), "active": status.represent(True), "inactive": status.represent(False), "submit": T("Save"), } s3.jquery_ready.append(script % options) else: # Read-only roster_status = SPAN(roster_status) # Render profile header return DIV( A( s3_avatar_represent( person_id, tablename="pr_person", _class="media-object", ), _class="pull-left", ), H2(name), P(comments), DIV(LABEL(status.label + ": "), roster_status), _class="profile-header", )
def customise_deploy_mission_controller(**attr): db = current.db s3db = current.s3db s3 = current.response.s3 MEMBER = T("Member") from gluon.html import DIV hr_comment = \ DIV(_class="tooltip", _title="%s|%s" % (MEMBER, current.messages.AUTOCOMPLETE_HELP)) table = s3db.deploy_mission table.code.label = T("Appeal Code") table.event_type_id.label = T("Disaster Type") table.organisation_id.readable = table.organisation_id.writable = False # Restrict Location to just Countries from s3 import S3Represent, S3MultiSelectWidget field = table.location_id field.label = current.messages.COUNTRY field.requires = s3db.gis_country_requires field.widget = S3MultiSelectWidget(multiple=False) field.represent = S3Represent(lookup="gis_location", translate=True) rtable = s3db.deploy_response rtable.human_resource_id.label = MEMBER rtable.human_resource_id.comment = hr_comment _customise_assignment_fields() # Report options report_fact = [ (T("Number of Missions"), "count(id)"), (T("Number of Countries"), "count(location_id)"), (T("Number of Disaster Types"), "count(event_type_id)"), (T("Number of Responses"), "sum(response_count)"), (T("Number of Deployments"), "sum(hrquantity)"), ] report_axis = [ "code", "location_id", "event_type_id", "status", ] report_options = Storage( rows=report_axis, cols=report_axis, fact=report_fact, defaults=Storage( rows="location_id", cols="event_type_id", fact="sum(hrquantity)", totals=True, ), ) s3db.configure( "deploy_mission", report_options=report_options, ) # CRUD Strings s3.crud_strings["deploy_assignment"] = Storage( label_create=T("New Deployment"), title_display=T("Deployment Details"), title_list=T("Deployments"), title_update=T("Edit Deployment Details"), title_upload=T("Import Deployments"), label_list_button=T("List Deployments"), label_delete_button=T("Delete Deployment"), msg_record_created=T("Deployment added"), msg_record_modified=T("Deployment Details updated"), msg_record_deleted=T("Deployment deleted"), msg_list_empty=T("No Deployments currently registered")) # Custom prep standard_prep = s3.prep def custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) else: result = True if r.interactive and not current.auth.s3_has_role("RDRT_ADMIN"): # Limit write-access to these fields to RDRT Admins: fields = ( "name", "event_type_id", "location_id", "code", "status", ) table = r.resource.table for f in fields: if f in table: table[f].writable = False #if not r.component and r.method == "create": # # Org is always IFRC # otable = s3db.org_organisation # query = (otable.name == "International Federation of Red Cross and Red Crescent Societies") # organisation = db(query).select(otable.id, # limitby = (0, 1), # ).first() # if organisation: # r.table.organisation_id.default = organisation.id return result s3.prep = custom_prep return attr
def __call__(self): output = {} T = current.T request = current.request response = current.response s3 = response.s3 # Check logged in and permissions auth = current.auth settings = current.deployment_settings roles = current.session.s3.roles system_roles = auth.get_system_roles() AUTHENTICATED = system_roles.AUTHENTICATED # Login/Registration forms self_registration = current.deployment_settings.get_security_registration_visible( ) registered = False login_form = None login_div = None register_form = None register_div = None # Contact Form request_email = settings.get_frontpage("request_email") if request_email: from s3dal import Field from gluon.validators import IS_NOT_EMPTY from gluon.sqlhtml import SQLFORM fields = [ Field( "name", label="Your name", requires=IS_NOT_EMPTY(), ), Field( "address", label="Your e-mail address", requires=IS_NOT_EMPTY(), ), Field( "subject", label="Subject", requires=IS_NOT_EMPTY(), ), Field( "message", "text", label="Message", requires=IS_NOT_EMPTY(), ), ] from s3 import s3_mark_required labels, required = s3_mark_required(fields) s3.has_required = required response.form_label_separator = "" contact_form = SQLFORM.factory( formstyle=settings.get_ui_formstyle(), submit_button=T("Submit"), labels=labels, separator="", table_name="contact", # Dummy table name _id="mailform", *fields) if contact_form.accepts(request.post_vars, current.session, formname="contact_form", keepvalues=False, hideerror=False): # Processs Contact Form form_vars = contact_form.vars sender = "%s <%s>" % (form_vars.name, form_vars.address) result = current.msg.send_email( to=request_email, sender=sender, subject=form_vars.subject, message=form_vars.message, reply_to=form_vars.address, ) if result: response.confirmation = "Thank you for your message - we'll be in touch shortly" if s3.cdn: if s3.debug: s3.scripts.append( "http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.js" ) else: s3.scripts.append( "http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js" ) else: if s3.debug: s3.scripts.append("/%s/static/scripts/jquery.validate.js" % request.application) else: s3.scripts.append( "/%s/static/scripts/jquery.validate.min.js" % request.application) validation_script = ''' $('#mailform').validate({ errorClass:'req', rules:{ name:{ required:true }, address: { required:true, email:true }, subject:{ required:true }, message:{ required:true } }, messages:{ name:"Enter your name", subject:"Enter a subject", message:"Enter a message", address:{ required:"Please enter a valid email address", email:"Please enter a valid email address" } }, errorPlacement:function(error,element){ error.appendTo(element.parents('div.controls')) }, submitHandler:function(form){ form.submit() } })''' s3.jquery_ready.append(validation_script) else: contact_form = "" if AUTHENTICATED not in roles: login_buttons = DIV(A(T("Login"), _id="show-login", _class="tiny secondary button"), _id="login-buttons") script = ''' $('#show-mailform').click(function(e){ e.preventDefault() $('#intro').slideDown(400, function() { $('#login_box').hide() }); }) $('#show-login').click(function(e){ e.preventDefault() $('#login_form').show() $('#register_form').hide() $('#login_box').show() $('#intro').slideUp() })''' s3.jquery_ready.append(script) # This user isn't yet logged-in if "registered" in request.cookies: # This browser has logged-in before registered = True if self_registration is True: # Provide a Registration box on front page login_buttons.append( A(T("Register"), _id="show-register", _class="tiny secondary button", _style="margin-left:5px")) script = ''' $('#show-register').click(function(e){ e.preventDefault() $('#login_form').hide() $('#register_form').show() $('#login_box').show() $('#intro').slideUp() })''' s3.jquery_ready.append(script) register_form = auth.register() register_div = DIV( H3(T("Register")), P( XML( T("If you would like to help, then please <b>sign up now</b>" )))) register_script = ''' $('#register-btn').click(function(e){ e.preventDefault() $('#register_form').show() $('#login_form').hide() }) $('#login-btn').click(function(e){ e.preventDefault() $('#register_form').hide() $('#login_form').show() })''' s3.jquery_ready.append(register_script) # Provide a login box on front page auth.messages.submit_button = T("Login") login_form = auth.login(inline=True) login_div = DIV( H3(T("Login")), P( XML( T("Registered users can <b>login</b> to access the system" )))) else: login_buttons = "" output["login_buttons"] = login_buttons output["self_registration"] = self_registration output["registered"] = registered output["login_div"] = login_div output["login_form"] = login_form output["register_div"] = register_div output["register_form"] = register_form output["contact_form"] = contact_form # Slick slider if s3.debug: s3.scripts.append("/%s/static/scripts/slick.js" % request.application) else: s3.scripts.append("/%s/static/scripts/slick.min.js" % request.application) script = ''' $(document).ready(function(){ $('#title-image').slick({ autoplay:true, autoplaySpeed:5000, speed:1000, fade:true, cssEase:'linear' }); });''' s3.jquery_ready.append(script) s3.stylesheets.append("../themes/%s/homepage.css" % THEME) self._view(THEME, "index.html") return output