def organisation_needs(row, need_type=None): """ Field.Method to render structured organisation needs (list views) @param row: the row (passed from Field.Method) @param need_type: the need type (skills|items) """ NONE = current.messages["NONE"] try: needs = getattr(row, "req_organisation_needs") except AttributeError: return NONE needs_id = needs.id s3db = current.s3db if need_type == "skills": ltable = s3db.req_organisation_needs_skill stable = s3db.hrm_skill left = stable.on(stable.id == ltable.skill_id) elif need_type == "items": ltable = s3db.req_organisation_needs_item stable = s3db.supply_item left = stable.on(stable.id == ltable.item_id) query = (ltable.organisation_needs_id == needs_id) rows = current.db(query).select(ltable.demand, stable.name, left = left, ) if not rows: return NONE needs = {} dfield = str(ltable.demand) nfield = str(stable.name) for row in rows: demand = row[dfield] if demand not in needs: needs[demand] = [row[nfield]] else: needs[demand].append(row[nfield]) T = current.T output = DIV(_class="org-needs") for demand in (4, 3, 2, 1): if demand not in needs: continue title = "%s:" % T(demand_options[demand]) items = UL([LI(T(need)) for need in needs[demand] if need is not None]) output.append(TAG[""](title, items)) return output # END =========================================================================
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 xml(self): """ XML """ self.components = [] self.components.append(self.root.render()) return DIV.xml(self)
def buttons(edit=False,view=False,record=None): buttons = DIV(gridbutton('buttonback', 'Back', referrer), _class='form_header row_buttons %(header)s %(cornertop)s' % ui) if edit and (not callable(edit) or edit(record)): args = ['edit',table._tablename,request.args[-1]] buttons.append(gridbutton('buttonedit', 'Edit', url(args=args))) if view: args = ['view',table._tablename,request.args[-1]] buttons.append(gridbutton('buttonview', 'View', url(args=args))) if record and links: for link in links: if isinstance(link,dict): buttons.append(link['body'](record)) elif link(record): buttons.append(link(record)) return buttons
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 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": profile_header = DIV( DIV( DIV(A( T("Personal Profile"), _href=URL(c="default", f="person"), _class="action-btn", ), _class="dashboard-links right", _style="padding:0.5rem 0;"), H2(title), _class="medium-6 columns end", ), _class="row", ) if item: # Append CMS content profile_header = TAG[""]( profile_header, DIV( DIV( item, _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: raise HTTP(501, current.ERROR.BAD_METHOD)
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 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 __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_self_registration() 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 current.request.cookies.has_key("registered"): # 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 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 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 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 __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 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 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 grid(query, fields=None, field_id=None, left=None, join=None, #! orderby=None, groupby=None, groupfields=None, #! having=None, #! headers={}, searchable=False, #True, sortable=True, paginate=20, pagename="page", #! deletable=False, #! True, editable=True, details=False, #! True, selectable=None, create=False, #!True, csv=False, #!True, links=None, links_in_grid=True, upload = '<default>', args=[], user_signature = False, #!True, maxtextlengths={}, maxtextlength=20, onvalidation=None, oncreate=None, onupdate=None, ondelete=None, sorter_icons=(XML('↑'),XML('↓')), ui = 'web2py', showbuttontext=True, _class="web2py_grid", formname='web2py_grid', search_widget='default', ignore_rw = False, formstyle = 'table3cols', exportclasses = None, formargs={}, createargs={}, editargs={}, viewargs={}, ): # jQuery UI ThemeRoller classes (empty if ui is disabled) if ui == 'jquery-ui': ui = dict(widget='ui-widget', header='ui-widget-header', content='ui-widget-content', default='ui-state-default', cornerall='ui-corner-all', cornertop='ui-corner-top', cornerbottom='ui-corner-bottom', button='ui-button-text-icon-primary', buttontext='ui-button-text', buttonadd='ui-icon ui-icon-plusthick', buttonback='ui-icon ui-icon-arrowreturnthick-1-w', buttonexport='ui-icon ui-icon-transferthick-e-w', buttondelete='ui-icon ui-icon-trash', buttonedit='ui-icon ui-icon-pencil', buttontable='ui-icon ui-icon-triangle-1-e', buttonview='ui-icon ui-icon-zoomin', ) elif ui == 'web2py': ui = dict(widget='', header='', content='', default='', cornerall='', cornertop='', cornerbottom='', button='button btn', buttontext='buttontext button', buttonadd='icon plus icon-plus', buttonback='icon leftarrow icon-arrow-left', buttonexport='icon downarrow icon-download', buttondelete='icon trash icon-trash', buttonedit='icon pen icon-pencil', buttontable='icon rightarrow icon-arrow-right', buttonview='icon magnifier icon-zoom-in', ) elif not isinstance(ui,dict): raise RuntimeError,'SQLFORM.grid ui argument must be a dictionary' db = query._db T = current.T request = current.request session = current.session response = current.response wenabled = (not user_signature or (session.auth and session.auth.user)) create = wenabled and create editable = wenabled and editable deletable = wenabled and deletable def url(**b): b['args'] = args+b.get('args',[]) b['hash_vars']=False b['user_signature'] = user_signature return URL(**b) def url2(**b): b['args'] = request.args+b.get('args',[]) b['hash_vars']=False b['user_signature'] = user_signature return URL(**b) referrer = session.get('_web2py_grid_referrer_'+formname, url()) # if not user_signature every action is accessible # else forbid access unless # - url is based url # - url has valid signature (vars are not signed, only path_info) # = url does not contain 'create','delete','edit' (readonly) if user_signature: if not( '/'.join(str(a) for a in args) == '/'.join(request.args) # or # URL.verify(request,user_signature=user_signature, # hash_vars=False) or not ( 'create' in request.args or 'delete' in request.args or 'edit' in request.args)): session.flash = T('not authorized') redirect(referrer) def gridbutton(buttonclass='buttonadd', buttontext='Add', buttonurl=url(args=[]), callback=None, delete=None, trap=True): if showbuttontext: if callback: return A(SPAN(_class=ui.get(buttonclass)), SPAN(T(buttontext),_title=buttontext, _class=ui.get('buttontext')), callback=callback,delete=delete, _class=trap_class(ui.get('button'),trap)) else: return A(SPAN(_class=ui.get(buttonclass)), SPAN(T(buttontext),_title=buttontext, _class=ui.get('buttontext')), _href=buttonurl, _class=trap_class(ui.get('button'),trap)) else: if callback: return A(SPAN(_class=ui.get(buttonclass)), callback=callback,delete=delete, _title=buttontext, _class=trap_class(ui.get('buttontext'),trap)) else: return A(SPAN(_class=ui.get(buttonclass)), _href=buttonurl,_title=buttontext, _class=trap_class(ui.get('buttontext'),trap)) dbset = db(query) tablenames = db._adapter.tables(dbset.query) #if left!=None: tablenames+=db._adapter.tables(left) if left!=None: if isinstance(left,list): for _left in left: tablenames=tablenames+db._adapter.tables(_left) else: tablenames=tablenames+db._adapter.tables(left) if join!=None: if isinstance(join,list): for _join in join: tablenames=tablenames+db._adapter.tables(_join) else: tablenames=tablenames+db._adapter.tables(join) tables = [db[tablename] for tablename in tablenames] if not fields: fields = reduce(lambda a,b:a+b, [[field for field in table] for table in tables]) if not field_id: field_id = tables[0]._id columns = [str(field) for field in fields \ if field._tablename in tablenames] if not str(field_id) in [str(f) for f in fields]: fields.append(field_id) table = field_id.table tablename = table._tablename if upload=='<default>': upload = lambda filename: url(args=['download',filename]) if len(request.args)>1 and request.args[-2]=='download': stream = response.download(request,db) raise HTTP(200,stream,**response.headers) def buttons(edit=False,view=False,record=None): buttons = DIV(gridbutton('buttonback', 'Back', referrer), _class='form_header row_buttons %(header)s %(cornertop)s' % ui) if edit and (not callable(edit) or edit(record)): args = ['edit',table._tablename,request.args[-1]] buttons.append(gridbutton('buttonedit', 'Edit', url(args=args))) if view: args = ['view',table._tablename,request.args[-1]] buttons.append(gridbutton('buttonview', 'View', url(args=args))) if record and links: for link in links: if isinstance(link,dict): buttons.append(link['body'](record)) elif link(record): buttons.append(link(record)) return buttons formfooter = DIV( _class='form_footer row_buttons %(header)s %(cornerbottom)s' % ui) create_form = update_form = view_form = search_form = None sqlformargs = dict(formargs) if create and len(request.args)>1 and request.args[-2] == 'new': table = db[request.args[-1]] sqlformargs.update(createargs) create_form = SQLFORM( table, ignore_rw=ignore_rw, formstyle=formstyle, _class='web2py_form', **sqlformargs) create_form.process(formname=formname, next=referrer, onvalidation=onvalidation, onsuccess=oncreate) res = DIV(buttons(), create_form, formfooter, _class=_class) res.create_form = create_form res.update_form = update_form res.view_form = view_form res.search_form = search_form return res elif details and len(request.args)>2 and request.args[-3]=='view': table = db[request.args[-2]] record = table(request.args[-1]) or redirect(URL('error')) sqlformargs.update(viewargs) view_form = SQLFORM(table, record, upload=upload, ignore_rw=ignore_rw, formstyle=formstyle, readonly=True, _class='web2py_form', **sqlformargs) res = DIV(buttons(edit=editable, record=record), view_form, formfooter, _class=_class) res.create_form = create_form res.update_form = update_form res.view_form = view_form res.search_form = search_form return res # elif editable and len(request.args)>2 and request.args[-3]=='edit': # table = db[request.args[-2]] # record = table(request.args[-1]) or redirect(URL('error')) # sqlformargs.update(editargs) # update_form = SQLFORM(table, record, upload=upload, ignore_rw=ignore_rw, # formstyle=formstyle, deletable=deletable, # _class='web2py_form', # submit_button=T('Submit'), # delete_label=T('Check to delete'), # **sqlformargs) # update_form.process(formname=formname, # onvalidation=onvalidation, # onsuccess=onupdate, # next=referrer) # res = DIV(buttons(view=details, record=record), # update_form, formfooter, _class=_class) # res.create_form = create_form # res.update_form = update_form # res.view_form = view_form # res.search_form = search_form # return res elif deletable and len(request.args)>2 and request.args[-3]=='delete': table = db[request.args[-2]] if ondelete: ondelete(table,request.args[-1]) ret = db(table[table._id.name]==request.args[-1]).delete() return ret exportManager = dict( csv_with_hidden_cols=(ExporterCSV,'CSV (hidden cols)'), csv=(ExporterCSV,'CSV'), xml=(ExporterXML, 'XML'), html=(ExporterHTML, 'HTML'), tsv_with_hidden_cols=\ (ExporterTSV,'TSV (Excel compatible, hidden cols)'), tsv=(ExporterTSV, 'TSV (Excel compatible)')) if not exportclasses is None: exportManager.update(exportclasses) export_type = request.vars._export_type if export_type: order = request.vars.order or '' if sortable: if order and not order=='None': if order[:1]=='~': sign, rorder = '~', order[1:] else: sign, rorder = '', order tablename,fieldname = rorder.split('.',1) orderby=db[tablename][fieldname] if sign=='~': orderby=~orderby table_fields = [f for f in fields if f._tablename in tablenames] if export_type in ('csv_with_hidden_cols','tsv_with_hidden_cols'): if request.vars.keywords: try: dbset = dbset(SQLFORM.build_query( fields,request.vars.get('keywords',''))) rows = dbset.select(cacheable=True) except Exception: response.flash = T('Internal Error') rows = [] else: rows = dbset.select(cacheable=True) else: rows = dbset.select(left=left,orderby=orderby, cacheable=True*columns) if export_type in exportManager: value = exportManager[export_type] clazz = value[0] if hasattr(value, '__getitem__') else value oExp = clazz(rows) filename = '.'.join(('rows', oExp.file_ext)) response.headers['Content-Type'] = oExp.content_type response.headers['Content-Disposition'] = \ 'attachment;filename='+filename+';' raise HTTP(200, oExp.export(),**response.headers) elif request.vars.records and not isinstance( request.vars.records,list): request.vars.records=[request.vars.records] elif not request.vars.records: request.vars.records=[] session['_web2py_grid_referrer_'+formname] = url2(vars=request.vars) console = DIV(_class='web2py_console %(header)s %(cornertop)s' % ui) error = None search_actions = DIV(_class='web2py_search_actions') if create: search_actions.append(gridbutton(buttonclass='buttonadd', buttontext=T('Add'), buttonurl=url(args=['new',tablename]))) console.append(search_actions) # if create: # add = gridbutton( # buttonclass='buttonadd', # buttontext='Add', # buttonurl=url(args=['new',tablename])) # if not searchable: # console.append(add) else: add = '' if searchable: sfields = reduce(lambda a,b:a+b, [[f for f in t if f.readable] for t in tables]) if isinstance(search_widget,dict): search_widget = search_widget[tablename] if search_widget=='default': search_menu = SQLFORM.search_menu(sfields) search_widget = lambda sfield, url: CAT(add,FORM( INPUT(_name='keywords',_value=request.vars.keywords, _id='web2py_keywords',_onfocus="jQuery('#w2p_query_fields').change();jQuery('#w2p_query_panel').slideDown();"), INPUT(_type='submit',_value=T('Search'),_class="btn"), INPUT(_type='submit',_value=T('Clear'),_class="btn", _onclick="jQuery('#web2py_keywords').val('');"), _method="GET",_action=url),search_menu) form = search_widget and search_widget(sfields,url()) or '' console.append(form) keywords = request.vars.get('keywords','') try: if callable(searchable): subquery = searchable(sfields, keywords) else: subquery = SQLFORM.build_query(sfields, keywords) except RuntimeError: subquery = None error = T('Invalid query') else: subquery = None if subquery: dbset = dbset(subquery) try: if groupby: nrows = len(dbset.select(*groupfields, join=join, left=left, groupby=groupby, having=having, cacheable=True)) elif left or join: nrows = dbset.select('count(*)',join=join,left=left, cacheable=True).first()['count(*)'] # if left or groupby: # c = 'count(*)' # nrows = dbset.select(c,left=left,cacheable=True, # groupby=groupby).first()[c] else: nrows = dbset.count() except: nrows = 0 error = T('Unsupported query') order = request.vars.order or '' if sortable: if order and not order=='None': if groupby: if str(groupby[0]).find(order)>-1: tablename,fieldname = order.split('~')[-1].split('.',1) sort_field = db[tablename][fieldname] exception = sort_field.type in ('date','datetime','time') if exception: orderby = (order[:1]=='~' and sort_field) or ~sort_field else: orderby = (order[:1]=='~' and ~sort_field) or sort_field else: tablename,fieldname = order.split('~')[-1].split('.',1) gfields = str(groupfields[0]).split(",") for gfield in gfields: if len(gfield.split(" AS "))>1: if gfield.split(" AS ")[1]==fieldname: if str(gfield.split(" AS ")[0]).find("SUM")>-1: sort_field = db[tablename][fieldname].sum() elif str(gfield.split(" AS ")[0]).find("COUNT")>-1: sort_field = db[tablename][fieldname].count() elif str(gfield.split(" AS ")[0]).find("MIN")>-1: sort_field = db[tablename][fieldname].min() elif str(gfield.split(" AS ")[0]).find("MAX")>-1: sort_field = db[tablename][fieldname].max() elif str(gfield.split(" AS ")[0]).find("LENGTH")>-1: sort_field = db[tablename][fieldname].len() else: break orderby = (order[:1]=='~' and ~sort_field) or sort_field break else: tablename,fieldname = order.split('~')[-1].split('.',1) sort_field = db[tablename][fieldname] exception = sort_field.type in ('date','datetime','time') if exception: orderby = (order[:1]=='~' and sort_field) or ~sort_field else: orderby = (order[:1]=='~' and ~sort_field) or sort_field head = TR(_class=ui.get('header')) if selectable: head.append(TH(_class=ui.get('default'))) for field in fields: if columns and not str(field) in columns: continue if not field.readable: continue key = str(field) header = headers.get(str(field), hasattr(field,'label') and field.label or key) if sortable: if key == order: key, marker = '~'+order, sorter_icons[0] elif key == order[1:]: marker = sorter_icons[1] else: marker = '' header = A(header,marker,_href=url(vars=dict( keywords=request.vars.keywords or '', order=key)),_class=trap_class()) head.append(TH(header, _class=ui.get('default'))) if links and links_in_grid: for link in links: if isinstance(link,dict): head.append(TH(link['header'], _class=ui.get('default'))) # Include extra column for buttons if needed. include_buttons_column = (details or editable or deletable or (links and links_in_grid and not all([isinstance(link, dict) for link in links]))) if include_buttons_column: head.insert(0,TH(_class=ui.get('default',''))) # head.append(TH(_class=ui.get('default'))) paginator = UL() if paginate and paginate<nrows: npages,reminder = divmod(nrows,paginate) if reminder: npages+=1 try: page = int(request.vars.page or 1)-1 except ValueError: page = 0 limitby = (paginate*page,paginate*(page+1)) def self_link(name,p): d = dict(page=p+1) if order: d['order']=order if request.vars.keywords: d['keywords']=request.vars.keywords return A(name,_href=url(vars=d),_class=trap_class()) NPAGES = 5 # window is 2*NPAGES if page>NPAGES+1: paginator.append(LI(self_link('<<',0))) if page>NPAGES: paginator.append(LI(self_link('<',page-1))) pages = range(max(0,page-NPAGES),min(page+NPAGES,npages)) for p in pages: if p == page: paginator.append(LI(A(p+1,_onclick='return false'), _class=trap_class('current'))) else: paginator.append(LI(self_link(p+1,p))) if page<npages-NPAGES: paginator.append(LI(self_link('>',page+1))) if page<npages-NPAGES-1: paginator.append(LI(self_link('>>',npages-1))) else: limitby = None try: table_fields = [f for f in fields if f._tablename in tablenames] if groupby: rows = dbset.select(*groupfields,join=join,left=left,groupby=groupby,having=having,orderby=orderby,limitby=limitby,cacheable=True) else: rows = dbset.select(join=join,left=left,orderby=orderby,limitby=limitby,cacheable=True,*table_fields) # rows = dbset.select(left=left,orderby=orderby, # groupby=groupby,limitby=limitby, # cacheable=True,*table_fields) except SyntaxError: rows = None error = T("Query Not Supported") if nrows: message = error or T('%(nrows)s records found') % dict(nrows=nrows) console.append(DIV(message,_class='web2py_counter')) if rows: htmltable = TABLE(THEAD(head)) tbody = TBODY() numrec=0 for row in rows: if numrec % 2 == 0: classtr = 'even' else: classtr = 'odd' numrec+=1 id = row[field_id] #@ReservedAssignment if id: rid = id if callable(rid): ### can this ever be callable? rid = rid(row) tr = TR(_id=rid, _class='%s %s' % (classtr, 'with_id')) else: tr = TR(_class=classtr) if selectable: tr.append(INPUT(_type="checkbox",_name="records",_value=id, value=request.vars.records)) for field in fields: if not str(field) in columns: continue if not field.readable: continue if field.type=='blob': continue value = row[field] maxlength = maxtextlengths.get(str(field),maxtextlength) if field.represent: try: value=field.represent(value,row) except Exception: try: value=field.represent(value,row[field._tablename]) except Exception: pass elif field.type=='boolean': value = INPUT(_type="checkbox",_checked = value, _disabled=True) elif field.type=='upload': if value: if callable(upload): value = A(current.T('file'), _href=upload(value)) elif upload: value = A(current.T('file'), _href='%s/%s' % (upload, value)) else: value = '' if isinstance(value,str): value = truncate_string(value,maxlength) elif not isinstance(value,DIV): value = field.formatter(value) if not include_buttons_column: tr.append(TD(value,_style="padding:10px;")) else: tr.append(TD(value)) row_buttons = TD(_class='row_buttons') if links and links_in_grid: for link in links: if isinstance(link, dict): tr.append(TD(link['body'](row))) else: if link(row): row_buttons.append(link(row)) if include_buttons_column: if details and (not callable(details) or details(row)): row_buttons.append(gridbutton( 'buttonview', 'View', url(args=['view',tablename,id]))) if editable and (not callable(editable) or editable(row)): row_buttons.append(gridbutton( 'buttonedit', 'Edit', url(args=['edit',tablename,id]))) if deletable and (not callable(deletable) or deletable(row)): row_buttons.append(gridbutton( 'buttondelete', 'Delete', callback=url(args=['delete',tablename,id]), delete='tr')) #tr.append(row_buttons) tr.insert(0,row_buttons) tbody.append(tr) htmltable.append(tbody) htmltable = DIV(htmltable,_style='width:100%;overflow-x:auto') if selectable: htmltable = FORM(htmltable,INPUT(_type="submit")) if htmltable.process(formname=formname).accepted:# htmltable.vars.records = htmltable.vars.records or [] htmltable.vars.records = htmltable.vars.records if type(htmltable.vars.records) == list else [htmltable.vars.records] records = [int(r) for r in htmltable.vars.records] selectable(records) redirect(referrer) else: htmltable = DIV(current.T('No records found')) if csv and nrows: export_links =[] for k,v in sorted(exportManager.items()): label = v[1] if hasattr(v, "__getitem__") else k link = url2(vars=dict( order=request.vars.order or '', _export_type=k, keywords=request.vars.keywords or '')) export_links.append(A(T(label),_href=link)) export_menu = \ DIV(T('Export:'),_class="w2p_export_menu",*export_links) else: export_menu = None res = DIV(console,DIV(htmltable,_class="web2py_table"), _class='%s %s' % (_class, ui.get('widget'))) if paginator.components: res.append( DIV(paginator, _class="web2py_paginator %(header)s %(cornerbottom)s"%ui)) if export_menu: res.append(export_menu) res.create_form = create_form res.update_form = update_form res.view_form = view_form res.search_form = search_form return res
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 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 # 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
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 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 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 __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_self_registration() 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 current.request.cookies.has_key("registered"): # 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 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 target is not 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] + [str(a) for a in 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): 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 fmt_impressions_by_usrid(question, f=None, c=None, T=None): """Used for actions where we need identify SINGLE physically presented impression: review or loans. Args: question: rik, ean, isxn (title?) of the book which we want find for review or loan f: action if clicked; if None you can set jQuery .click() later to call ajax (based on <a data_id="nnn">) c: controller for the action (if it is different as the current one) Returns: tuple (imp_id, candidates) imp_id: provided only if we have SINGLE impression found (to allow make the action without offering the list), otherwise this is None candidates: formatted output for possible candidates (empty in case of SINGLE impression) """ if T is None: T = current.T def imp_info(imp): iorder = imp[1] lbl = SPAN('%s-%s' % (rik, iorder)) if uses_iid: lbl.append(' ') lbl.append(B(imp[2])) if uses_sgn: lbl.append(' ') lbl.append(imp[3]) imp_id = "%s" % imp[0] return A(lbl, _href=(URL(c, f, args=imp_id) if c else URL(f, args=imp_id)) if f else "#", _data_id=imp_id, _class='btn btn-warning') libstyle = get_libstyle() rik_short_pos = get_rik_short_pos(libstyle) uses_iid = libstyle['id'][0] == 'I' uses_sgn = libstyle['sg'][0] == 'G' books, overflow, imp_id = impressions_by_usrid(question, stop_if_single=True) if imp_id: return imp_id, '' '''boooks is list of dictionaries, one dict for one publication, keys are: 'owned_book_id', 'answer_id', 'rik', 'fastinfo' and 'imp', where 'imp' is list of impressions (of single book) each item in 'imp' is tuple: (id, iorder, iid) imp_id will be set if we have exactly SINGLE impression - this terminates the formatting immediately ''' fmt = [] if books: for book in books: rik = book['rik'] rik = rik[rik_short_pos::-1] if rik else '' impressions = book['imp'] cnt_imp = len(impressions) tit, aut, pub, puy = parse_fastinfo(book['fastinfo']) book_div = DIV(*get_book_line(tit, aut), _class='btn btn-default btn-sm') if cnt_imp > 1: # summary as visible fmt.append(DIV(DIV('%s x' % cnt_imp, _class='btn btn-info btn-sm'), book_div)) # detail rows as hidden imps = DIV(_style="overflow: auto;") for imp in impressions: imps.append(imp_info(imp)) fmt.append(imps) else: # single impression # summary=detail as visible fmt.append(DIV(imp_info(impressions[0]), book_div)) result = DIV() if overflow: result.append(DIV(T("Je zobrazen omezený počet - méně výtisků než odpovídá zadání. Použij přesnější zadání."))) result.append(DIV(*fmt)) else: result = DIV(T("Zadání neodpovídá žádný výtisk.")) return None, result
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