def inline(): """ Demo/test case for inline component subforms, to be removed after implementation is complete. """ from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent crud_form = S3SQLCustomForm( "first_name", "last_name", # Email Addresses S3SQLInlineComponent( "contact", name="email", label=T("Email Addresses"), fields=["value"], filterby = dict( field = "contact_method", options = "EMAIL" ) ), # Other Contact Information S3SQLInlineComponent( "contact", name="all", label=T("Contact Information"), fields=["contact_method", "value"], filterby = dict( field = "contact_method", options = "EMAIL", invert = True, default = "SMS" ) ), "age_group", "date_of_birth", S3SQLInlineComponent( "note", label=T("Notes"), fields=["timestmp", "note_text"] ), "identification.status" ) s3db.configure("pr_person", crud_form=crud_form) return s3_rest_controller("pr", "person")
def inline(): """ Test controller for inline link tables """ from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent crud_form = S3SQLCustomForm( "name", # Project Organisations S3SQLInlineComponent( "organisation", label=T("Participating Organisations"), fields=["organisation_id", "role", "amount"], ), ) s3db.configure("project_project", crud_form=crud_form) return s3_rest_controller("project", "project")
def custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) if not result: return False s3db = current.s3db tablename = "pr_person" if r.interactive: # Set the list fields list_fields = [ "first_name", "middle_name", "last_name", "human_resource.organisation_id", "address.location_id" ] # Set the CRUD Strings s3.crud_strings[tablename] = Storage( label_create=T("Create a Contributor"), title_display=T("Contributor Details"), title_list=T("Contributors"), title_update=T("Edit Contributor Details"), label_list_button=T("List Contributors"), label_delete_button=T("Delete Contributor"), msg_record_created=T("Contributor added"), msg_record_modified=T("Contributor details updated"), msg_record_deleted=T("Contributor deleted"), msg_list_empty=T("No Contributors currently registered")) # Custom Form (Read/Create/Update) from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent crud_form = S3SQLCustomForm( "first_name", "middle_name", "last_name", S3SQLInlineComponent( "contact", label=T("Email"), multiple=False, fields=[("", "value")], filterby=dict(field="contact_method", options="EMAIL"), ), "gender", S3SQLInlineComponent( "note", name="bio", label=T("Bio Paragraph"), multiple=False, fields=[("", "note_text")], ), S3SQLInlineComponent( "image", name="image", label=T("Photo"), multiple=False, fields=[("", "image")], filterby=dict(field="profile", options=[True]), ), S3SQLInlineComponent( "human_resource", name="hrm_human_resource", label="", multiple=False, fields=["", "organisation_id", "job_title_id"], ), S3SQLInlineComponent("address", label=T("Home Location"), fields=[("", "location_id")], render_list=True), ) s3db.configure(tablename, crud_form=crud_form, list_fields=list_fields) return True
def custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) if not result: return False s3.crud_strings["project_member"] = Storage(msg_record_created=None, msg_record_deleted=None) if r.interactive: is_deployment = False stable = s3db.project_sector_project otable = s3db.org_sector # Edit the end_date label of "project_milestone" table milestone_table = s3db.project_milestone milestone_table.date.label = T("End Date") # Check if current record is Deployment if r.id: # Viewing details of project_project record query = (stable.project_id == r.id) & \ (otable.id == stable.sector_id) rows = db(query).select(otable.name) for row in rows: if row.name == "Deployment": is_deployment = True request_sector = r.get_vars.get("sector.name") # Viewing Projects/Deployments Page if request_sector and "Deployment" in request_sector: is_deployment = True if is_deployment: # Change the CRUD strings and labels s3db[tablename].name.label = T("Deployment Name") s3.crud_strings[tablename] = Storage( label_create=T("Create Deployment"), title_display=T("Deployment Details"), title_list=T("Deployments"), title_update=T("Edit Deployment"), title_report=T("Deployment Report"), 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 updated"), msg_record_deleted=T("Deployment deleted"), msg_list_empty=T("No Deployments currently registered")) # Set the method for deployment page s3db.set_method(r.controller, r.function, method="deployment", action=deployment_page) if not r.component: # Viewing project/deployment's Basic Details from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent, S3SQLInlineLink if is_deployment: # Bring back to the Deployments page if record deleted delete_next = URL(c="project", f="project", vars={"sector.name": "None,Deployment"}) # Get sector_id for Deployment row = db(otable.name == "Deployment").select( otable.id, limitby=(0, 1)).first() # Modify the CRUD form crud_form = S3SQLCustomForm( "organisation_id", "name", "sector_project.sector_id", "description", "status_id", "start_date", "end_date", "calendar", S3SQLInlineComponent("location", label=T("Countries"), fields=["location_id"], orderby="location_id$name", render_list=True), S3SQLInlineLink( "hazard", label=T("Hazard"), field="hazard_id", ), S3SQLInlineLink( "theme", label=T("Type"), field="theme_id", ), "human_resource_id", # Files S3SQLInlineComponent("document", name="file", label=T("Files"), fields=[(T("Type"), "name"), "file"], filterby=dict( field="file", options="", invert=True, )), # Links S3SQLInlineComponent("document", name="url", label=T("Links"), fields=[(T("Type"), "name"), "url"], filterby=dict( field="url", options=None, invert=True, )), S3SQLInlineComponent("image", fields=["", "file"], filterby=dict( field="file", options="", invert=True, )), "comments", ) location_id = s3db.project_location.location_id # Limit to just Countries location_id.requires = s3db.gis_country_requires # Use dropdown, not AC location_id.widget = None else: # Bring back to the Projects page if record deleted delete_next = URL(c="project", f="project", vars={"sector.name": "None,Project"}) # Get sector_id for Project row = db(otable.name == "Project").select( otable.id, limitby=(0, 1)).first() # Modify the CRUD form crud_form = S3SQLCustomForm( "organisation_id", "name", "sector_project.sector_id", "description", "status_id", "start_date", "end_date", "calendar", "human_resource_id", "comments", ) # Set the default sector try: stable.sector_id.default = row.id except: current.log.error("Pre-Populate", "Sectors not prepopulated") # Remove Add Sector button stable.sector_id.comment = None s3db.configure( tablename, crud_form=crud_form, delete_next=delete_next, ) return True
def customise_project_task_resource(r, tablename): """ Customise project_task resource - CRUD Form Runs after controller customisation But runs before prep """ s3db = current.s3db db = current.db T = current.T crud_strings = current.response.s3.crud_strings crud_strings["project_member"] = Storage(msg_record_created=None, msg_record_deleted=None) if r.interactive: trimmed_task = False get_vars = r.get_vars ADD_TASK = T("Create Task") # Check if it is a bug report if get_vars.get("bug"): tagname = "bug" trimmed_task = True ADD_TASK = T("Report a Bug") # Check if it is a feature request elif get_vars.get("featureRequest"): tagname = "feature request" trimmed_task = True ADD_TASK = T("Request a Feature") # Check if it is a support task elif get_vars.get("support"): tagname = "support" trimmed_task = True ADD_TASK = T("Request Support") from s3.s3forms import S3SQLCustomForm, S3SQLInlineLink, S3SQLInlineComponent if trimmed_task: # Show a trimmed view of creating task crud_fields = [ "name", "description", S3SQLInlineLink( "tag", label=T("Tag"), field="tag_id", ), "priority", "status", S3SQLInlineComponent( "document", label=T("Attachment"), fields=["", "file"], ), ] crud_strings["project_task"]["label_create"] = ADD_TASK tagtable = s3db.project_tag query = (tagtable.deleted != True) & \ (tagtable.name == tagname) row = db(query).select(tagtable.id, limitby=(0, 1)).first() # Set the tag try: s3db.project_task_tag.tag_id.default = row.id except: current.log.error("Pre-Populate", "Tags not prepopulated") else: # Show all fields for creating the task crud_fields = [ S3SQLInlineComponent( "task_milestone", label=T("Milestone"), fields=[("", "milestone_id")], multiple=False, ), "name", "description", S3SQLInlineComponent( "task_tag", label=T("Tags"), fields=[("", "tag_id")], ), "priority", "status", S3SQLInlineComponent( "member", label=T("Members"), fields=[("", "person_id")], readonly=True, ), "source", "date_due", "time_estimated", S3SQLInlineComponent( "document", label=T("Attachment"), fields=["", "file"], ), S3SQLInlineComponent( "time", label=T("Time Log"), fields=["date", "person_id", "hours", "comments"], orderby="date"), "time_actual", ] if r.tablename == "project_task": # Add the project field if it is not under the component crud_fields.insert( 0, S3SQLInlineComponent( "task_project", label=T("Project"), fields=[("", "project_id")], multiple=False, )) crud_form = S3SQLCustomForm(*crud_fields) s3db.configure( tablename, crud_form=crud_form, )
def custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) else: result = True if r.interactive or r.representation.lower() == "aadata": list_fields = [ "id", "name", "acronym", "organisation_type_id", (T("Services"), "service.name"), (T("Neighborhoods Served"), "location.name"), ] s3db.configure("org_organisation", list_fields=list_fields) if r.interactive: from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent, S3SQLInlineComponentCheckbox s3db.pr_address.comments.label = "" s3db.pr_contact.value.label = "" crud_form = S3SQLCustomForm( "name", "acronym", "organisation_type_id", S3SQLInlineComponentCheckbox( "service", label=T("Services"), field="service_id", cols=4, ), S3SQLInlineComponentCheckbox( "group", label=T("Network"), field="group_id", cols=3, ), S3SQLInlineComponent( "address", label=T("Address"), multiple=False, # This is just Text - put into the Comments box for now # Ultimately should go into location_id$addr_street fields=["comments"], ), S3SQLInlineComponentCheckbox( "location", label=T("Neighborhoods Served"), field="location_id", filterby=dict(field="level", options="L4"), cols=5, ), "phone", S3SQLInlineComponent("contact", name="phone2", label=T("Phone2"), multiple=False, fields=["value"], filterby=dict(field="contact_method", options="WORK_PHONE")), S3SQLInlineComponent("contact", name="email", label=T("Email"), multiple=False, fields=["value"], filterby=dict(field="contact_method", options="EMAIL")), "website", S3SQLInlineComponent("contact", name="rss", label=T("RSS"), multiple=False, fields=["value"], filterby=dict(field="contact_method", options="RSS")), S3SQLInlineComponent("contact", name="twitter", label=T("Twitter"), multiple=False, fields=["value"], filterby=dict(field="contact_method", options="TWITTER")), "comments", ) from s3.s3filter import S3LocationFilter, S3OptionsFilter, S3TextFilter filter_widgets = [ S3TextFilter( ["name", "acronym"], label=T("Name"), _class="filter-search", ), S3OptionsFilter( "group_membership.group_id", label=T("Network"), represent="%(name)s", widget="multiselect", cols=3, #hidden=True, ), S3LocationFilter( "organisation_location.location_id", label=T("Neighborhood"), levels=["L3", "L4"], widget="multiselect", cols=3, #hidden=True, ), S3OptionsFilter( "service_organisation.service_id", label=T("Service"), represent="%(name)s", widget="multiselect", cols=3, #hidden=True, ), S3OptionsFilter( "organisation_type_id", label=T("Type"), represent="%(name)s", widget="multiselect", cols=3, #hidden=True, ), ] from s3.s3search import S3Search, S3SearchSimpleWidget, S3SearchOptionsWidget search_method = S3Search( simple=(), advanced=( S3SearchSimpleWidget( name="org_search_text_advanced", label=T("Name"), comment=T( "Search for an Organization by name or acronym"), field=["name", "acronym"]), S3SearchOptionsWidget(name="org_search_network", label=T("Network"), field="group.name", cols=2), S3SearchOptionsWidget(name="org_search_location", label=T("Neighborhood"), field="location.L4", location_level="L4", cols=2), S3SearchOptionsWidget(name="org_search_service", label=T("Services"), field="service.name", cols=2), S3SearchOptionsWidget(name="org_search_type", label=T("Type"), field="organisation_type_id", cols=2), )) s3db.configure( "org_organisation", crud_form=crud_form, # @ToDo: Style & Enable #filter_widgets = filter_widgets, search_method=search_method, ) return result
def customize_project_project(**attr): """ Customize project_project controller """ s3db = current.s3db tablename = "project_project" # Load normal model table = s3db[tablename] # @ToDo: S3SQLInlineComponent for Project orgs # Get IDs for PartnerNS/Partner-Donor # db = current.db # ttable = db.org_organisation_type # rows = db(ttable.deleted != True).select(ttable.id, # ttable.name, # ) # rc = [] # not_rc = [] # nappend = not_rc.append # for row in rows: # if row.name == "Red Cross / Red Crescent": # rc.append(row.id) # elif row.name == "Supplier": # pass # else: # nappend(row.id) # Custom Fields # Organisation needs to be an NS (not a branch) f = table.organisation_id ns_only( f, required=True, branches=False, ) f.label = T("Host National Society") # Custom Crud Form crud_form = S3SQLCustomForm( "organisation_id", "name", "code", "description", "status_id", "start_date", "end_date", #S3SQLInlineComponent( # "location", # label = T("Countries"), # fields = ["location_id"], #), # Outputs S3SQLInlineComponent( "output", label=T("Outputs"), #comment = "Bob", fields=["name", "status"], ), S3SQLInlineComponentCheckbox( "hazard", label=T("Hazards"), field="hazard_id", cols=4, ), S3SQLInlineComponentCheckbox( "sector", label=T("Sectors"), field="sector_id", cols=4, ), S3SQLInlineComponentCheckbox( "theme", label=T("Themes"), field="theme_id", cols=4, # Filter Theme by Sector filter={ "linktable": "project_theme_sector", "lkey": "theme_id", "rkey": "sector_id", }, script=''' S3OptionsFilter({ 'triggerName':'defaultsector-sector_id', 'targetName':'defaulttheme-theme_id', 'targetWidget':'defaulttheme-theme_id_widget', 'lookupResource':'theme', 'lookupURL':S3.Ap.concat('/project/theme_sector_widget?sector_ids='), 'getWidgetHTML':true, 'showEmptyField':false })'''), "drr.hfa", "objectives", "human_resource_id", # Disabled since we need organisation_id filtering to either organisation_type_id == RC or NOT # & also hiding Branches from RCs # Partner NS # S3SQLInlineComponent( # "organisation", # name = "partnerns", # label = T("Partner National Societies"), # fields = ["organisation_id", # "comments", # ], # Filter Organisation by Type # filter = ["organisation_id": {"filterby": "organisation_type_id", # "filterfor": rc, # }], # filterby = dict(field = "role", # options = [9]) # ), # Partner Orgs # S3SQLInlineComponent( # "organisation", # name = "partner", # label = T("Partner Organizations"), # fields = ["organisation_id", # "comments", # ], # Filter Organisation by Type # filter = ["organisation_id": {"filterby": "organisation_type_id", # "filterfor": not_rc, # }], # filterby = dict(field = "role", # options = [2]) # ), # Donors # S3SQLInlineComponent( # "organisation", # name = "donor", # label = T("Donor(s)"), # fields = ["organisation_id", # "amount", # "currency"], # Filter Organisation by Type # filter = ["organisation_id": {"filterby": "organisation_type_id", # "filterfor": not_rc, # }], # filterby = dict(field = "role", # options = [3]) # ), #"budget", #"currency", "comments", ) s3db.configure(tablename, crud_form=crud_form) return attr
def prep(r): if r.interactive or r.representation == "aadata": s3db.cms_customize_post_fields() if r.interactive: field = table.series_id field.label = T("Type") if r.method == "read": # Restore the label for the Location table.location_id.label = T("Location") elif r.method == "create": pass # @ToDo: deployment_setting #ADMIN = session.s3.system_roles.ADMIN #if (not auth.s3_has_role(ADMIN)): # represent = S3Represent(lookup="cms_series", # translate=settings.get_L10n_translate_cms_series()) # field.requires = IS_ONE_OF(db, # "cms_series.id", # represent, # not_filterby="name", # not_filter_opts = ["Alert"], # ) refresh = get_vars.get("refresh", None) if refresh == "datalist": # We must be coming from the News Feed page so can change the type on-the-fly field.readable = field.writable = True #field.requires = field.requires.other #field = table.name #field.readable = field.writable = False #field = table.title #field.readable = field.writable = False field = table.avatar field.default = True #field.readable = field.writable = False field = table.replies field.default = False #field.readable = field.writable = False field = table.body field.label = T("Description") # Plain text not Rich from s3.s3widgets import s3_comments_widget field.widget = s3_comments_widget #table.comments.readable = table.comments.writable = False #if request.controller == "default": # # Don't override card layout for News Feed/Homepage # return True from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent # Filter from a Profile page? # If so, then default the fields we know location_id = get_vars.get("~.(location)", None) if location_id: table.location_id.default = location_id event_id = get_vars.get("~.(event)", None) if event_id: crud_form = S3SQLCustomForm( "date", "series_id", "body", "location_id", S3SQLInlineComponent( "document", name="file", label=T("Files"), fields=[ "file", #"comments", ], ), ) def create_onaccept(form): table = current.s3db.event_event_post table.insert(event_id=event_id, post_id=form.vars.id) s3db.configure( "cms_post", create_onaccept=create_onaccept, ) else: crud_form = S3SQLCustomForm( "date", "series_id", "body", "location_id", # @ToDo: deployment_setting for Events #S3SQLInlineComponent( # "event_post", # #label = T("Disaster(s)"), # label = T("Disaster"), # multiple = False, # fields = ["event_id"], # orderby = "event_id$name", #), # @ToDo: deployment_setting S3SQLInlineComponent( "post_organisation", label=T("Organization"), fields=["organisation_id"], # @ToDo: deployment_setting multiple=False, ), # @ToDo: deployment_setting "person_id", S3SQLInlineComponent( "document", name="file", label=T("Files"), fields=[ "file", #"comments", ], ), ) # Return to List view after create/update/delete # We now do all this in Popups #url_next = URL(c="default", f="index", args="newsfeed") s3db.configure( "cms_post", #create_next = url_next, #delete_next = url_next, #update_next = url_next, crud_form=crud_form, # Don't include a Create form in 'More' popups listadd=False, list_layout=s3db.cms_render_posts, ) elif r.representation == "xls": table.created_by.represent = s3base.s3_auth_user_represent_name #table.created_on.represent = datetime_represent utable = auth.settings.table_user utable.organisation_id.represent = s3db.org_organisation_represent list_fields = [ (T("Date"), "date"), #(T("Disaster"), "event_post.event_id"), (T("Type"), "series_id"), (T("Details"), "body"), ] for level in levels: list_fields.append( (hierarchy[level], "location_id$%s" % level)) list_fields = + [ (T("Contact"), contact_field), (T("Organization"), org_field), ] s3db.configure( "cms_post", list_fields=list_fields, ) elif r.representation == "plain" and \ r.method != "search": # Map Popups table.location_id.represent = s3db.gis_LocationRepresent(sep=" | ") table.created_by.represent = s3base.s3_auth_user_represent_name # Used by default popups series = table.series_id.represent(r.record.series_id) s3.crud_strings[ "cms_post"].title_display = "%(series)s Details" % dict( series=series) s3db.configure( "cms_post", popup_url="", ) table.avatar.readable = False table.body.label = "" table.expired.readable = False table.replies.readable = False table.created_by.readable = True table.created_by.label = T("Author") # Used by cms_post_popup #table.created_on.represent = datetime_represent elif r.representation == "geojson": r.table.age = Field.Lazy(cms_post_age) return True
def customise_project_project_controller(**attr): db = current.db s3db = current.s3db s3 = current.response.s3 tablename = "project_project" # Load normal model table = s3db[tablename] # Custom Components s3db.add_components( tablename, project_drrpp={ "joinby": "project_id", "multiple": False, }, project_output="project_id", doc_document=( # Files { "name": "file", "joinby": "doc_id", "filterby": { "url": ("", None), }, }, # Links { "name": "url", "joinby": "doc_id", "filterby": { "file": ("", None), }, }, ), ) # Custom Fields table.name.label = T("Project Title") s3db.project_project.budget.label = T("Total Funding (USD)") location_id = s3db.project_location.location_id location_id.label = "" # Limit to just Countries location_id.requires = s3db.gis_country_requires # Use dropdown, not AC location_id.widget = None # In DRRPP this is a free field table = s3db.project_organisation table.comments.label = T("Role") table.comments.widget = SQLFORM.widgets.string.widget table.amount.label = T("Amount") table = s3db.doc_document table.file.widget = lambda field, value, download_url: \ SQLFORM.widgets.upload.widget(field, value, download_url, _size = 15) table.comments.widget = SQLFORM.widgets.string.widget # If not logged in, contact person is required logged_in = current.auth.is_logged_in() if not logged_in: table = s3db.project_drrpp table.focal_person.required = True table.email.required = True table.email.requires = IS_EMAIL() # Custom dataTable s3["dataTable_dom"] = 'ripl<"dataTable_table"t>p' # Don't show export buttons for XLS/XML s3.formats = Storage(xls=None, xml=None) # Remove rheader attr["rheader"] = None # Only show 10 Project by default to improve load time attr["dt_lengthMenu"] = [[10, 50, -1], [10, 50, T("All")]] s3.dataTable_pageLength = 10 # Custom PreP standard_prep = s3.prep def custom_prep(r): resource = r.resource # Call standard prep if callable(standard_prep): result = standard_prep(r) if not result: return False # Customise list_fields if r.method == "review": list_fields = [ "id", "created_on", "modified_on", "name", "start_date", (T("Countries"), "location.location_id"), (T("Hazards"), "hazard.name"), (T("Lead Organization"), "organisation_id"), (T("Donors"), "donor.organisation_id"), ] elif r.representation == "xls": # All readable Fields should be exported list_fields = [ "id", "name", "code", "description", "status_id", "start_date", "end_date", "drrpp.duration", (T("Countries"), "location.location_id"), "drrpp.L1", (T("Hazards"), "hazard.name"), (T("Themes"), "theme.name"), "objectives", "drrpp.activities", "output.name", "drr.hfa", "drrpp.rfa", "drrpp.pifacc", "drrpp.jnap", (T("Lead Organization"), "organisation_id"), (T("Partners"), "partner.organisation_id"), (T("Donors"), "donor.organisation_id"), "budget", "currency", "drrpp.focal_person", "drrpp.organisation_id", "drrpp.email", "url.url", "drrpp.parent_project", "comments", ] if logged_in: list_fields.extend([ "created_by", "created_on", "modified_by", "modified_on", ]) else: list_fields = [ "id", "name", "start_date", (T("Countries"), "location.location_id"), (T("Hazards"), "hazard.name"), (T("Lead Organization"), "organisation_id"), (T("Donors"), "donor.organisation_id"), ] resource.configure(list_fields=list_fields) # Customise report_options if r.method == "report": report_fields = [ "name", (T("Countries"), "location.location_id"), (T("Hazards"), "hazard.name"), (T("Themes"), "theme.name"), (T("HFA Priorities"), "drr.hfa"), (T("RFA Priorities"), "drrpp.rfa"), (T("Lead Organization"), "organisation_id"), (T("Partner Organizations"), "partner.organisation_id"), (T("Donors"), "donor.organisation_id"), ] # Report Settings for charts if "chart" in r.get_vars and r.representation != "json": s3.crud_strings[tablename].title_report = T( "Project Graph") report_fact_default = "count(id)" report_facts = [(T("Number of Projects"), "count(id)")] show_table = False else: s3.crud_strings[tablename].title_report = T( "Project Matrix") report_fact_default = "count(id)" report_facts = [ (T("Number of Projects"), "count(id)"), (T("Number of Countries"), "count(location.location_id)"), (T("Number of Hazards"), "count(hazard.id)"), (T("Number of Themes"), "count(theme.id)"), (T("Number of HFA Priorities"), "count(drr.hfa)"), (T("Number of RFA Priorities"), "count(drrpp.rfa)"), (T("Number of Lead Organizations"), "count(organisation_id)"), (T("Number of Partner Organizations"), "count(partner.organisation_id)"), (T("Number of Donors"), "count(donor.organisation_id)"), ] show_table = True report_options = Storage(rows=report_fields, cols=report_fields, fact=report_facts, defaults=Storage( rows="hazard.name", cols="location.location_id", fact=report_fact_default, totals=True, table=show_table, )) resource.configure(report_options=report_options) current.deployment_settings.ui.hide_report_options = True if r.interactive: # Don't show Update/Delete button on Search table if r.method is None and not r.id: resource.configure(editable=False, deletable=False) # JS to show/hide Cook Island fields s3.scripts.append("/%s/static/themes/DRRPP/js/drrpp.js" % current.request.application) if r.method == "read": table_pl = s3db.project_location table_l = s3db.gis_location countries = [ row.name for row in db((table_pl.project_id == r.record.id) & (table_pl.location_id == table_l.id)). select(table_l.name) ] if not ("Cook Islands" in countries and len(countries) == 1): s3db.project_drrpp.L1.readable = False s3db.project_drrpp.pifacc.readable = False s3db.project_drrpp.jnap.readable = False # Filter Options project_hfa_opts = s3db.project_hfa_opts() hfa_options = dict( (key, "HFA %s" % key) for key in project_hfa_opts) #hfa_options[None] = NONE # to search NO HFA project_rfa_opts = s3db.project_rfa_opts() rfa_options = dict( (key, "RFA %s" % key) for key in project_rfa_opts) #rfa_options[None] = NONE # to search NO RFA project_pifacc_opts = s3db.project_pifacc_opts() pifacc_options = dict( (key, "PIFACC %s" % key) for key in project_pifacc_opts) #pifacc_options[None] = NONE # to search NO PIFACC project_jnap_opts = s3db.project_jnap_opts() jnap_options = dict( (key, "JNAP %s" % key) for key in project_jnap_opts) #jnap_options[None] = NONE # to search NO JNAP # Filter widgets from s3 import S3TextFilter, S3OptionsFilter, s3_get_filter_opts filter_widgets = [ S3TextFilter(["name", "code", "description", "location.location_id", "hazard.name", "theme.name", ], label = T("Search Projects"), comment = T("Search for a Project by name, code, or description."), ), S3OptionsFilter("status_id", label = T("Status"), cols = 4, ), S3OptionsFilter("location.location_id", label = T("Country"), cols = 3, hidden = True, ), #S3OptionsFilter("drrpp.L1", # label = T("Cook Islands"), # cols = 3, # hidden = True, # ), S3OptionsFilter("hazard.id", label = T("Hazard"), options = lambda: \ s3_get_filter_opts("project_hazard", translate=True), help_field = s3db.project_hazard_help_fields, cols = 4, hidden = True, ), S3OptionsFilter("theme.id", label = T("Theme"), options = lambda: \ s3_get_filter_opts("project_theme", translate=True), help_field = s3db.project_theme_help_fields, cols = 4, # Don't group size = None, hidden = True, ), S3OptionsFilter("drr.hfa", label = T("HFA"), options = hfa_options, help_field = project_hfa_opts, cols = 5, hidden = True, ), S3OptionsFilter("drrpp.rfa", label = T("RFA"), options = rfa_options, help_field = project_rfa_opts, cols = 6, hidden = True, ), S3OptionsFilter("drrpp.pifacc", label = T("PIFACC"), options = pifacc_options, help_field = project_pifacc_opts, cols = 6, hidden = True, ), S3OptionsFilter("drrpp.jnap", label = T("JNAP"), options = jnap_options, help_field = project_jnap_opts, cols = 6, hidden = True, ), S3OptionsFilter("organisation_id", label = T("Lead Organization"), cols = 3, hidden = True, ), S3OptionsFilter("partner.organisation_id", label = T("Partners"), cols = 3, hidden = True, ), S3OptionsFilter("donor.organisation_id", label = T("Donors"), cols = 3, hidden = True, ) ] resource.configure(filter_widgets=filter_widgets) return True s3.prep = custom_prep # Custom Crud Form from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent, S3SQLInlineComponentCheckbox crud_form = S3SQLCustomForm( "name", "code", "description", "status_id", "start_date", "end_date", "drrpp.duration", S3SQLInlineComponent("location", label=T("Countries"), fields=["location_id"], orderby="location_id$name", render_list=True), "drrpp.L1", S3SQLInlineComponentCheckbox( "hazard", label=T("Hazards"), field="hazard_id", option_help="comments", cols=4, ), S3SQLInlineComponentCheckbox( "theme", label=T("Themes"), field="theme_id", option_help="comments", cols=3, ), "objectives", "drrpp.activities", # Outputs S3SQLInlineComponent( "output", label=T("Outputs"), fields=["name", "status"], ), "drr.hfa", "drrpp.rfa", "drrpp.pifacc", "drrpp.jnap", "organisation_id", # Partner Orgs S3SQLInlineComponent( "organisation", name="partner", label=T("Partner Organizations"), fields=[ "organisation_id", "comments", # NB This is labelled 'Role' in DRRPP ], filterby=dict(field="role", options=[2, 9]), default={"role": 2}), # Donors S3SQLInlineComponent("organisation", name="donor", label=T("Donor(s)"), fields=[ "organisation_id", "amount", "currency", ], filterby=dict(field="role", options=[3]), default={"role": 3}), "budget", "drrpp.local_budget", "drrpp.local_currency", "drrpp.focal_person", "drrpp.organisation_id", "drrpp.email", # Files S3SQLInlineComponent("document", name="file", label=T("Files"), fields=["file", "comments"], filterby=dict( field="file", options="", invert=True, )), # Links S3SQLInlineComponent("document", name="url", label=T("Links"), fields=["url", "comments"], filterby=dict( field="url", options=None, invert=True, )), "drrpp.parent_project", "comments", ) s3db.configure( tablename, crud_form=crud_form, subheadings={ 1: "hazard", 2: "theme", 3: "objectives", 4: "drr_hfa", 5: "drrpp_rfa", 6: "drrpp_pifacc", 7: "drrpp_jnap", 8: "organisation_id", }, ) return attr
def customize_project_activity(**attr): """ Customize project_activity controller """ s3 = current.response.s3 s3db = current.s3db table = s3db.project_activity #Use activities as projects (Temporary - location widget broken inline s3.crud_strings["project_activity"] = s3.crud_strings["project_project"] # Custom PreP standard_prep = s3.prep def custom_prep(r): if r.method in ["create", "update"]: # hide inline labels s3db.project_activity_organisation.organisation_id.label = "" s3db.project_activity_activity_type.activity_type_id.label = "" return True s3.prep = custom_prep list_fields = [ "id", "status_id", "name", "location_id", "activity_organisation.organisation_id", "date", "end_date", ] # Custom Form table.location_id.requires = IS_LOCATION_SELECTOR2(levels=levels) table.location_id.widget = S3LocationSelectorWidget2(levels=levels, show_address=True, show_map=True) # Don't add new Locations here table.location_id.comment = None table.name.label = T("Name") table.comments.label = T("Description") crud_form = S3SQLCustomForm( "status_id", "name", "comments", "location_id", S3SQLInlineComponent( "activity_organisation", label=T("Organization"), fields=["organisation_id"], multiple=False, ), #S3SQLInlineComponent("activity_activity_type", # label = T("Activity Type"), # fields = ["activity_type_id"], # multiple = False, # ), "date", "end_date", ) filter_widgets = [ S3TextFilter( [ "name", ], label=T("Description"), _class="filter-search", ), S3LocationFilter( "location_id", widget="multiselect", levels=levels, ), S3OptionsFilter( "status_id", label=T("Status"), # Doesn't support translation #represent="%(name)s", # @ToDo: Introspect cols cols=3, #widget="multiselect", ), #S3OptionsFilter("activity_activity_type.activity_type_id", # Doesn't support translation #represent="%(name)s", # widget="multiselect", # ), S3OptionsFilter( "activity_organisation.organisation_id", # Doesn't support translation #represent="%(name)s", widget="multiselect", ), S3OptionsFilter( "activity_organisation.organisation_id$organisation_type_id", # Doesn't support translation #represent="%(name)s", widget="multiselect", ), ] # Report options report_fields = [ "activity_organisation.organisation_id", "status_id", ] report_options = Storage( rows=report_fields, cols=report_fields, fact=["count(id)"], defaults=Storage( rows="activity_organisation.organisation_id", cols="status_id", fact="count(id)", totals=True, chart="barchart:rows", #table = "collapse", )) s3db.configure( "project_activity", list_fields=list_fields, crud_form=crud_form, filter_widgets=filter_widgets, report_options=report_options, ) # Remove rheader attr["rheader"] = None return attr
def customize_project_project(**attr): """ Customize project_project controller """ s3 = current.response.s3 s3db = current.s3db table = s3db.project_project # Custom Form location_id_field = s3db.project_location.location_id location_id_field.requires = IS_LOCATION_SELECTOR2(levels=levels) location_id_field.widget = S3LocationSelectorWidget2(levels=levels, show_address=True, show_map=True) # Don't add new Locations here location_id_field.comment = None table.name.label = T("Description") table.comments.label = T("Details") #s3db.project_project_organisation.organisation_id.label = "" #s3db.project_project_project_type.project_type_id.label = "" crud_form = S3SQLCustomForm( "status_id", "name", "description", #"location.location_id", "organisation_id", S3SQLInlineComponent( "location", label=T("Location"), fields=["location_id"], orderby="location_id$name", #multiple = False, ), "start_date", "end_date", ) filter_widgets = [ S3TextFilter( [ "name", ], label=T("Description"), _class="filter-search", ), S3LocationFilter( "location_id", widget="multiselect", levels=levels, ), S3OptionsFilter( "status_id", label=T("Status"), # Doesn't support translation #represent="%(name)s", # @ToDo: Introspect cols cols=3, #widget="multiselect", ), S3OptionsFilter( "project_project_type.project_type_id", # Doesn't support translation #represent="%(name)s", widget="multiselect", ), S3OptionsFilter( "project_organisation.organisation_id", # Doesn't support translation #represent="%(name)s", widget="multiselect", ), S3OptionsFilter( "project_organisation.organisation_id$organisation_type_id", # Doesn't support translation #represent="%(name)s", widget="multiselect", ), ] s3db.configure( "project_project", crud_form=crud_form, #filter_widgets = filter_widgets, ) # Remove rheader attr["rheader"] = None return attr
def email_inbox(): """ RESTful CRUD controller for the Email Inbox - all Inbound Email Messages are visible here @ToDo: Filter to those which have been unable to be automatically processed as being responses to Alerts @ToDo: Filter to those coming into the specific account used for Deployments @ToDo: Provide a mechanism (Action button?) to link a mail manually to an Alert """ if not auth.s3_logged_in(): session.error = T("Requires Login!") redirect(URL(c="default", f="user", args="login")) tablename = "msg_email" table = s3db.msg_email table.inbound.readable = False table.channel_id.readable = False table.to_address.readable = False from s3.s3resource import S3FieldSelector s3.filter = (S3FieldSelector("response.id") == None) & \ (S3FieldSelector("inbound") == True) from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent crud_form = S3SQLCustomForm( "date", "subject", "from_address", "body", S3SQLInlineComponent( "attachment", name="document_id", label=T("Attachments"), fields=[ "document_id", ], ), ) s3db.configure( tablename, crud_form=crud_form, editable=False, insertable=False, list_fields=[ "id", "date", "from_address", "subject", "body", (T("Attachments"), "attachment.document_id"), ], ) # CRUD Strings s3.crud_strings[tablename] = Storage( title_list=T("View InBox"), title_update=T("Edit Message"), label_list_button=T("View InBox"), label_delete_button=T("Delete Message"), msg_record_modified=T("Message updated"), msg_record_deleted=T("Message deleted"), msg_list_empty=T("No Messages currently in InBox")) def prep(r): if r.id: s3db.msg_attachment.document_id.label = "" if r.component and r.component.alias == "select": if not r.method: r.method = "select" if r.method == "select": r.custom_action = s3db.deploy_response_select_mission return True s3.prep = prep def postp(r, output): if r.interactive: # Normal Action Buttons s3_action_buttons(r) # Custom Action Buttons s3.actions += [ dict(label=str(T("Link to Mission")), _class="action-btn link", url=URL(f="email_inbox", args=["[id]", "select"])), ] if r.id: s3.rfooter = s3base.S3CRUD.crud_button( T("Link to Mission"), _href=URL(f="email_inbox", args=[r.id, "select"]), _class="action-btn link", ) return output s3.postp = postp return s3_rest_controller("msg", "email")
def customize_cms_post(**attr): """ Customize cms_post controller """ s3 = current.response.s3 s3db = current.s3db table = s3db.cms_post s3.dl_pagelength = 12 s3.dl_rowsize = 2 # CRUD Form table.location_id.requires = IS_LOCATION_SELECTOR2(levels=levels) table.location_id.widget = S3LocationSelectorWidget2(levels=levels, show_address=True, show_map=True) # Don't add new Locations here table.location_id.comment = None table.series_id.readable = table.series_id.writable = True table.series_id.label = T("Type") table.body.label = T("Description") table.body.widget = None s3db.event_event_post.event_id.label = "" s3db.doc_document.file.label = "" crud_form = S3SQLCustomForm( "date", "series_id", "body", "location_id", S3SQLInlineComponent( "event_post", #label = T("Disaster(s)"), label=T("Disaster"), multiple=False, fields=["event_id"], orderby="event_id$name", ), S3SQLInlineComponent( "document", name="file", label=T("Files"), fields=[ "file", #"comments", ], ), ) # Return to List view after create/update/delete # We now do all this in Popups #url_next = URL(c="default", f="index", args="newsfeed") s3db.configure( "cms_post", crud_form=crud_form, ) # Remove rheader attr["rheader"] = None return attr
def customise_event_event_resource(r, tablename): """ Customise event_event resource - List Fields - CRUD Strings - Form - Filter - Report Runs after controller customisation But runs before prep """ from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent from s3.s3validators import IS_LOCATION_SELECTOR2 from s3.s3widgets import S3LocationSelectorWidget2 db = current.db s3db = current.s3db table = r.table table.name.label = T("Disaster Number") location_field = s3db.event_event_location.location_id location_field.requires = IS_LOCATION_SELECTOR2(levels=gis_levels) location_field.widget = S3LocationSelectorWidget2(levels=gis_levels) impact_fields = OrderedDict( killed="Killed", total_affected="Total Affected", est_damage="Estimated Damage (US$ Million)", ) ptable = s3db.stats_impact_type rows = db(ptable.name.belongs(impact_fields.values())).select( ptable.id, ptable.name, ) parameters = rows.as_dict(key="name") impact_components = [] impact_crud_form_fields = [] impact_list_fields = [] impact_report_fields = [] for tag, label in impact_fields.items(): parameter = parameters[label]["id"] impact_components.append({ "name": tag, "link": "event_event_impact", "joinby": "event_id", "key": "impact_id", "filterby": "parameter_id", "filterfor": (parameter, ), }) label = T(label) impact_crud_form_fields.append( S3SQLInlineComponent(tag, label=label, link=False, multiple=False, fields=[("", "value")], filterby=dict(field="parameter_id", options=parameter))) impact_list_fields.append((label, "%s.value" % tag)) impact_report_fields.append( (T("Total %(param)s") % dict(param=label), "sum(%s.value)" % tag)) s3db.add_components( "event_event", stats_impact=impact_components, ) crud_form = S3SQLCustomForm( "name", "event_type_id", "start_date", "end_date", # @ToDo: Inline location_id field #S3SQLInlineComponent("event_location", # label = T("Location"), # multiple = False, # fields = [("", "location_id")], # ), "comments", *impact_crud_form_fields) list_fields = [ "name", "event_type_id", ] lappend = list_fields.append for level in gis_levels: location_level = "event_location.location_id$%s" % level lappend(location_level) list_fields.extend(( "start_date", "end_date", )) list_fields.extend(impact_list_fields) report_facts = [(T("Number of Disasters"), "count(id)")] report_facts.extend(impact_report_fields) report_options = s3db.get_config("event_event", "report_options") report_options.fact = report_facts s3db.configure( "event_event", crud_form=crud_form, list_fields=list_fields, ) if r.interactive: # Labels table.comments.label = T("Description") s3.crud_strings["event_event"] = Storage( label_create=T("Record Disaster"), title_display=T("Disaster Details"), title_list=T("Disasters"), title_update=T("Edit Disaster"), label_list_button=T("List Disasters"), label_delete_button=T("Delete Disaster"), msg_record_created=T("Disaster added"), msg_record_modified=T("Disaster updated"), msg_record_deleted=T("Disaster deleted"), msg_list_empty=T("No Disasters currently registered"))
def customise_gis_location_controller(**attr): """ Customise org_organisation resource - List Fields - Form - Filter - Report Runs after controller customisation But runs before prep """ s3db = current.s3db # Custom filtered components for custom list_fields s3db.add_components( "gis_location", gis_location_name={ "name": "name_ru", "joinby": "location_id", "filterby": "language", "filterfor": ("ru", ), }, gis_location_tag={ "name": "pcode", "joinby": "location_id", "filterby": "tag", "filterfor": ("PCode", ), }, ) from s3.s3widgets import S3MultiSelectWidget s3db.gis_location.parent.widget = S3MultiSelectWidget(multiple=False) from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent crud_form = S3SQLCustomForm( "name", #"name_ru.name_l10n", S3SQLInlineComponent( "name_ru", label=T("Russian Name"), multiple=False, fields=[("", "name_l10n")], ), "level", S3SQLInlineComponent( "pcode", label=T("PCode"), multiple=False, fields=[("", "value")], ), #"pcode.value", "parent", ) field = s3db.gis_location.inherited field.label = T("Mapped?") field.represent = lambda inherited: T("No") if inherited else T("Yes") filter_widgets = s3db.get_config("gis_location", "filter_widgets") # Remove L2 & L3 filters # NB Fragile: dependent on filters defined in gis/location controller filter_widgets.pop() filter_widgets.pop() s3db.configure( "gis_location", crud_form=crud_form, filter_widgets=filter_widgets, list_fields=[ "name", # @ToDo: Investigate whether we can support this style & hence not need to define custom components #(T("Russian Name"), "name.name_l10n?location_name.language=ru"), #("PCode", "tag.value?location_tag.tag=PCode"), (T("Russian Name"), "name_ru.name_l10n"), "level", ("PCode", "pcode.value"), "L0", "L1", "L2", "inherited", ]) return attr
def custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) else: result = True if r.interactive or r.representation == "aadata": from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent, S3SQLInlineComponentCheckbox s3db = current.s3db table = r.table table.code.label = T("Project blurb (max. 100 characters)") table.code.max_length = 100 table.comments.label = T("How people can help") script = '''$('#project_project_code').attr('maxlength','100')''' s3.jquery_ready.append(script) crud_form = S3SQLCustomForm( "organisation_id", "name", "code", "description", "status_id", "start_date", "end_date", "calendar", #"drr.hfa", #"objectives", "human_resource_id", # Activities S3SQLInlineComponent( "location", label=T("Location"), fields=["location_id"], ), # Partner Orgs S3SQLInlineComponent( "organisation", name="partner", label=T("Partner Organizations"), fields=[ "organisation_id", "comments", # NB This is labelled 'Role' in DRRPP ], filterby=dict(field="role", options="2")), S3SQLInlineComponent( "document", name="media", label=T( "URLs (media, fundraising, website, social media, etc." ), fields=[ "document_id", "name", "url", "comments", ], filterby=dict(field="name")), S3SQLInlineComponentCheckbox( "activity_type", label=T("Categories"), field="activity_type_id", cols=3, # Filter Activity Type by Project filter={ "linktable": "project_activity_type_project", "lkey": "project_id", "rkey": "activity_type_id", }, ), #"budget", #"currency", "comments", ) s3db.configure("project_project", crud_form=crud_form) return result
def customize_cms_post(**attr): """ Customize cms_post controller """ s3 = current.response.s3 s3db = current.s3db table = s3db.cms_post field = table.series_id field.label = T("Type") field.readable = field.writable = True #field.requires = field.requires.other #field = table.name #field.readable = field.writable = False #field = table.title #field.readable = field.writable = False field = table.avatar field.default = True #field.readable = field.writable = False field = table.replies field.default = False #field.readable = field.writable = False field = table.location_id field.represent = location_represent field.requires = IS_NULL_OR(IS_LOCATION(level="L4")) field.widget = S3LocationAutocompleteWidget(level="L4") table.created_by.represent = s3_auth_user_represent_name field = table.body field.label = T("Text") field.widget = None #table.comments.readable = table.comments.writable = False crud_form = S3SQLCustomForm( "series_id", "body", "location_id", S3SQLInlineComponent( "document", name="file", label=T("Files"), fields=[ "file", #"comments", ], ), ) # Return to List view after create/update/delete url_next = URL(c="default", f="index", args=None) list_fields = [ "series_id", "location_id", "created_on", "body", "created_by", "created_by$organisation_id", "document.file", "comments", # Needed for YouTube URLs ] s3db.configure( "cms_post", create_next=url_next, delete_next=url_next, update_next=url_next, crud_form=crud_form, list_fields=list_fields, ) crud_settings = s3.crud crud_settings.formstyle = "bootstrap" crud_settings.submit_button = T("Save changes") # Done already within Bootstrap formstyle (& anyway fails with this formstyle) #crud_settings.submit_style = "btn btn-primary" # Custom PostP standard_postp = s3.postp def custom_postp(r, output): if r.representation == "plain" and \ r.method != "search": # Map Popups - styled like dataList auth = current.auth db = current.db record = r.record record_id = record.id item_class = "thumbnail" item_id = "popup-%s" % record_id table = s3db.cms_post series = table.series_id.represent(record.series_id) date = S3DateTime.date_represent(record.created_on, utc=True) body = record.body location_id = record.location_id location = table.location_id.represent(location_id) location_url = URL(c="gis", f="location", args=[location_id]) # Attachment(s)? table = s3db.doc_document row = db(table.doc_id == record.doc_id).select( table.file, limitby=(0, 1)).first() if row: doc_url = URL(c="default", f="download", args=[row.file]) doc_link = A(I(_class="icon icon-paper-clip fright"), _href=doc_url) else: doc_link = "" if series not in ("News", "Twitter", "Ushahidi", "YouTube"): # We expect an Author author_id = record.created_by author = table.created_by.represent(author_id) utable = auth.settings.table_user user = db(utable.id == author_id).select( utable.organisation_id, limitby=(0, 1)).first() organisation_id = user.organisation_id organisation = s3db.org_organisation_id.attr["represent"]( organisation_id) org_url = URL(c="org", f="organisation", args=[organisation_id]) # @ToDo: Optimise by not doing DB lookups (especially duplicate) within render, but doing these in the bulk query avatar = s3_avatar_represent( author_id, _class="media-object", _style="width:50px;padding:5px;padding-top:0px;") ltable = s3db.pr_person_user ptable = db.pr_person query = (ltable.user_id == author_id) & \ (ltable.pe_id == ptable.pe_id) row = db(query).select(ptable.id, limitby=(0, 1)).first() if row: person_url = URL(c="hrm", f="person", args=[row.id]) else: person_url = "#" author = A( author, _href=person_url, ) avatar = A( avatar, _href=person_url, _class="pull-left", ) card_person = DIV( author, " - ", A( organisation, _href=org_url, _class="card-organisation", ), doc_link, _class="card-person", ) else: # No Author card_person = DIV( doc_link, _class="card-person", ) avatar = None if series == "News": icon = URL(c="static", f="img", args=["markers", "gis_marker.image.News.png"]) elif series == "Twitter": icon = URL(c="static", f="img", args=["social", "twitter.png"]) elif series == "Ushahidi": icon = URL( c="static", f="img", args=["markers", "gis_marker.image.Ushahidi.png"]) elif series == "YouTube": #icon = URL(c="static", f="img", args=["social", "YouTube.png"]) avatar = DIV(IFRAME(_width=320, _height=180, _src=record.comments, _frameborder=0), _class="pull-left") if not avatar: avatar = DIV(IMG( _src=icon, _class="media-object", _style="width:50px;padding:5px;padding-top:0px;", ), _class="pull-left") # Edit Bar permit = auth.s3_has_permission if permit("update", table, record_id=record_id): edit_btn = A( I(" ", _class="icon icon-edit"), _href=URL(c="cms", f="post", args=[record_id, "update"]), ) else: edit_btn = "" # delete_btn looks too much like popup close! #if permit("delete", table, record_id=record_id): # delete_btn = A(I(" ", _class="icon icon-remove-sign"), # _href=URL(c="cms", f="post", # args=[record_id, "delete"]), # ) #else: delete_btn = "" edit_bar = DIV( edit_btn, delete_btn, _class="edit-bar fright", ) # Overall layout output = DIV( DIV( I( SPAN( " %s" % T(series), _class="card-title", ), _class="icon icon-%s" % series.lower(), ), SPAN( A( location, _href=location_url, ), _class="location-title", ), SPAN( date, _class="date-title", ), edit_bar, _class="card-header", ), DIV( avatar, DIV( DIV( body, card_person, _class="media", ), _class="media-body", ), _class="media", ), _class=item_class, _id=item_id, ) elif callable(standard_postp): # Call standard postp output = standard_postp(r, output) return output s3.postp = custom_postp return attr
def customize_pr_person(**attr): """ Customize pr_person controller """ s3db = current.s3db request = current.request s3 = current.response.s3 tablename = "pr_person" table = s3db.pr_person # CRUD Strings ADD_CONTACT = T("Add New Contact") s3.crud_strings[tablename] = Storage( title_create=T("Add Contact"), title_display=T("Contact Details"), title_list=T("Contact Directory"), title_update=T("Edit Contact Details"), title_search=T("Search Contacts"), subtitle_create=ADD_CONTACT, label_list_button=T("List Contacts"), label_create_button=ADD_CONTACT, label_delete_button=T("Delete Contact"), msg_record_created=T("Contact added"), msg_record_modified=T("Contact details updated"), msg_record_deleted=T("Contact deleted"), msg_list_empty=T("No Contacts currently registered")) # Custom PreP standard_prep = s3.prep def custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) if not result: return False if r.method == "validate": # Can't validate image without the file image_field = s3db.pr_image.image image_field.requires = None MOBILE = settings.get_ui_label_mobile_phone() EMAIL = T("Email") htable = s3db.hrm_human_resource htable.organisation_id.widget = None site_field = htable.site_id represent = S3Represent(lookup="org_site") site_field.label = T("Office") site_field.represent = represent site_field.requires = IS_ONE_OF(current.db, "org_site.site_id", represent, orderby="org_site.name") from s3layouts import S3AddResourceLink site_field.comment = S3AddResourceLink( c="org", f="office", vars={"child": "site_id"}, label=T("Add New Office"), title=T("Office"), tooltip= T("If you don't see the Office in the list, you can add a new one by clicking link 'Add New Office'." )) # Best to have no labels when only 1 field in the row s3db.pr_contact.value.label = "" image_field = s3db.pr_image.image image_field.label = "" # ImageCrop widget doesn't currently work within an Inline Form from gluon.validators import IS_IMAGE image_field.requires = IS_IMAGE() image_field.widget = None hr_fields = [ "organisation_id", "job_title_id", "site_id", ] # Context from a Profile page?" organisation_id = request.get_vars.get("(organisation)", None) if organisation_id: field = s3db.hrm_human_resource.organisation_id field.default = organisation_id field.readable = field.writable = False hr_fields.remove("organisation_id") s3_sql_custom_fields = [ "first_name", #"middle_name", "last_name", S3SQLInlineComponent( "human_resource", name="human_resource", label="", multiple=False, fields=hr_fields, ), S3SQLInlineComponent("image", name="image", label=T("Photo"), multiple=False, fields=["image"], filterby=dict(field="profile", options=[True])), ] list_fields = [ "human_resource.organisation_id", "first_name", #"middle_name", "last_name", (T("Job Title"), "human_resource.job_title_id"), (T("Office"), "human_resource.site_id"), ] # Don't include Email/Phone for unauthenticated users if current.auth.is_logged_in(): list_fields += [ (MOBILE, "phone.value"), (EMAIL, "email.value"), ] s3_sql_custom_fields.insert( 3, S3SQLInlineComponent("contact", name="phone", label=MOBILE, multiple=False, fields=["value"], filterby=dict(field="contact_method", options="SMS")), ) s3_sql_custom_fields.insert( 3, S3SQLInlineComponent("contact", name="email", label=EMAIL, multiple=False, fields=["value"], filterby=dict(field="contact_method", options="EMAIL")), ) crud_form = S3SQLCustomForm(*s3_sql_custom_fields) filter_widgets = [ S3TextFilter( [ "pe_label", "first_name", "middle_name", "last_name", "local_name", "identity.value", "human_resource.organisation_id", "human_resource.job_title_id", "human_resource.site_id", ], label=T("Search"), ), S3OptionsFilter( "human_resource.organisation_id", # Doesn't support translation #represent="%(name)s", widget="multiselect", ), S3OptionsFilter( "human_resource.job_title_id", # Doesn't support translation #represent="%(name)s", widget="multiselect", ), S3OptionsFilter( "human_resource.site_id", # Doesn't support translation #represent="%(name)s", widget="multiselect", ), ] # Return to List view after create/update/delete (unless done via Modal) #url_next = URL(c="pr", f="person", ) # Report options report_fields = [ "organisation_id", ] report_options = Storage( rows=report_fields, cols=report_fields, fact=["count(id)"], defaults=Storage( rows="organisation_id", cols="", fact="count(id)", totals=True, chart="barchart:rows", #table = "collapse", )) s3db.configure( tablename, #create_next = url_next, #delete_next = url_next, #update_next = url_next, crud_form=crud_form, filter_widgets=filter_widgets, list_fields=list_fields, report_options=report_options, # Don't include a Create form in 'More' popups #listadd = False if r.method=="datalist" else True, #list_layout = render_contacts, ) # Custom postp standard_postp = s3.postp def custom_postp(r, output): # Call standard postp if callable(standard_postp): output = standard_postp(r, output) if r.interactive and isinstance(output, dict): output["rheader"] = "" actions = [ dict(label=str(T("Open")), _class="action-btn", url=URL(c="pr", f="person", args=["[id]", "read"])) ] s3.actions = actions if "form" in output: output["form"].add_class("pr_person") elif "item" in output and hasattr(output["item"], "add_class"): output["item"].add_class("pr_person") return output s3.postp = custom_postp # Remove rheader attr["rheader"] = None return attr
def prep(r): if r.interactive or r.representation == "aadata": s3db.cms_configure_newsfeed_post_fields() if r.interactive: if len_series > 1: refresh = get_vars.get("refresh", None) if refresh == "datalist": # We must be coming from the News Feed page so can change the type on-the-fly field = table.series_id field.label = T("Type") field.readable = field.writable = True else: field = table.series_id row = db(stable.deleted == False).select(stable.id, limitby=(0, 1)).first() try: field.default = row.id except: # Prepop not done: expose field to show error field.label = T("Type") field.readable = field.writable = True else: field.readable = field.writable = False if r.method == "read": # Restore the label for the Location table.location_id.label = T("Location") elif r.method == "create": pass # @ToDo: deployment_setting #if not auth.s3_has_role("ADMIN"): # represent = S3Represent(lookup="cms_series", # translate=settings.get_L10n_translate_cms_series()) # field.requires = IS_ONE_OF(db, # "cms_series.id", # represent, # not_filterby="name", # not_filter_opts = ("Alert",), # ) #field = table.name #field.readable = field.writable = False #field = table.title #field.readable = field.writable = False field = table.avatar field.default = True #field.readable = field.writable = False field = table.replies field.default = False #field.readable = field.writable = False field = table.body field.label = T("Description") # Plain text not Rich from s3.s3widgets import s3_comments_widget field.widget = s3_comments_widget #table.comments.readable = table.comments.writable = False #if request.controller == "default": # # Don't override card layout for News Feed/Homepage # return True from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent # Filter from a Profile page? # If so, then default the fields we know location_id = get_vars.get("~.(location)", None) if location_id: table.location_id.default = location_id event_id = get_vars.get("~.(event)", None) if event_id: def create_onaccept(form): table = current.s3db.event_post table.insert(event_id=event_id, post_id=form.vars.id) s3db.configure( "cms_post", create_onaccept=create_onaccept, ) crud_fields = [ "date", "series_id", ] cappend = crud_fields.append if settings.get_cms_show_titles(): cappend("title") crud_fields.extend(( "body", "location_id", )) if not event_id and show_events: cappend( S3SQLInlineComponent( "event_post", # @ToDo: deployment_setting (use same one used to activate?) #label = T("Disaster(s)"), label=T("Disaster"), multiple=False, fields=[("", "event_id")], orderby="event_id$name", )) if org_field == "post_organisation.organisation_id": cappend( S3SQLInlineComponent( "post_organisation", label=T("Organization"), fields=[("", "organisation_id")], # @ToDo: deployment_setting multiple=False, )) if org_group_field == "post_organisation_group.group_id": cappend( S3SQLInlineComponent( "post_organisation_group", label=T(group_label), fields=[("", "group_id")], # @ToDo: deployment_setting multiple=False, )) if contact_field == "person_id": cappend("person_id") if settings.get_cms_show_attachments(): cappend( S3SQLInlineComponent( "document", name="file", label=T("Files"), fields=[ ("", "file"), #"comments", ], )) if settings.get_cms_show_links(): cappend( S3SQLInlineComponent( "document", name="url", label=T("Links"), fields=[ ("", "url"), #"comments", ], )) crud_form = S3SQLCustomForm(*crud_fields) # Return to List view after create/update/delete # We now do all this in Popups #url_next = URL(c="default", f="index", args="newsfeed") s3db.configure( "cms_post", #create_next = url_next, #delete_next = url_next, #update_next = url_next, crud_form=crud_form, # Don't include a Create form in 'More' popups listadd=False, ) elif r.representation == "xls": table.body.represent = None table.created_by.represent = s3base.s3_auth_user_represent_name #table.created_on.represent = datetime_represent utable = auth.settings.table_user utable.organisation_id.represent = s3db.org_organisation_represent list_fields = [ (T("Date"), "date"), #(T("Disaster"), "event_post.event_id"), (T("Type"), "series_id"), (T("Details"), "body"), ] lappend = list_fields.append # Which levels of Hierarchy are we using? gis = current.gis levels = gis.get_relevant_hierarchy_levels() hierarchy = gis.get_location_hierarchy() for level in levels: lappend((hierarchy[level], "location_id$%s" % level)) if contact_field: lappend((T("Contact"), contact_field)) if org_field: lappend((T("Organization"), org_field)) if org_group_field: lappend((T(group_label), org_group_field)) s3db.configure( "cms_post", list_fields=list_fields, ) elif r.representation == "plain": # Map Popups table.location_id.represent = s3db.gis_LocationRepresent(sep=" | ") table.created_by.represent = s3base.s3_auth_user_represent_name # Used by default popups series = table.series_id.represent(r.record.series_id) s3.crud_strings[ "cms_post"].title_display = "%(series)s Details" % dict( series=series) s3db.configure( "cms_post", popup_url="", ) table.avatar.readable = False table.body.label = "" table.expired.readable = False table.replies.readable = False table.created_by.readable = True table.created_by.label = T("Author") # Used by cms_post_popup #table.created_on.represent = datetime_represent elif r.representation == "geojson": r.table.age = Field.Method("age", cms_post_age) return True
def custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) else: result = True if r.interactive or r.representation == "aadata": from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent, S3SQLInlineComponentCheckbox s3db = current.s3db table = r.table tablename = "project_project" table.code.label = T("Project blurb (max. 100 characters)") table.code.max_length = 100 table.comments.label = T("How people can help") script = '''$('#project_project_code').attr('maxlength','100')''' s3.jquery_ready.append(script) crud_form = S3SQLCustomForm( "organisation_id", "name", "code", "description", "status_id", "start_date", "end_date", "calendar", #"drr.hfa", #"objectives", "human_resource_id", # Activities S3SQLInlineComponent( "location", label = T("Location"), fields = ["location_id"], ), # Partner Orgs S3SQLInlineComponent( "organisation", name = "partner", label = T("Partner Organizations"), fields = ["organisation_id", "comments", # NB This is labelled 'Role' in DRRPP ], filterby = dict(field = "role", options = "2" ) ), S3SQLInlineComponent( "document", name = "media", label = T("URLs (media, fundraising, website, social media, etc."), fields = ["document_id", "name", "url", "comments", ], filterby = dict(field = "name") ), S3SQLInlineComponentCheckbox( "activity_type", label = T("Categories"), field = "activity_type_id", cols = 3, # Filter Activity Type by Project filter = {"linktable": "project_activity_type_project", "lkey": "project_id", "rkey": "activity_type_id", }, ), #"budget", #"currency", "comments", ) from s3.s3filter import S3TextFilter, S3OptionsFilter, S3LocationFilter, S3DateFilter filter_widgets = [ S3TextFilter(["name", "code", "description", "organisation.name", "organisation.acronym", ], label=T("Name"), _class="filter-search", ), S3OptionsFilter("status_id", label=T("Status"), represent="%(name)s", cols=3, ), #S3OptionsFilter("theme_project.theme_id", # label=T("Theme"), # represent="%(name)s", # widget="multiselect", # #hidden=True, # ), S3LocationFilter("location.location_id", label=T("Location"), levels=["L1", "L2", "L3", "L4"], widget="multiselect", #hidden=True, ), # @ToDo: Widget to handle Start & End in 1! S3DateFilter("start_date", label=T("Start Date"), hide_time=True, #hidden=True, ), S3DateFilter("end_date", label=T("End Date"), hide_time=True, #hidden=True, ), ] list_fields = ["id", "name", "code", "organisation_id", "start_date", "end_date", (T("Locations"), "location.location_id"), ] s3db.configure(tablename, crud_form = crud_form, filter_widgets = filter_widgets, list_fields = list_fields, ) return result
def email_inbox(): """ RESTful CRUD controller for the Email Inbox - all Inbound Email Messages are visible here @ToDo: Filter to those which have been unable to be automatically processed as being responses to Alerts @ToDo: Filter to those coming into the specific account used for Deployments @ToDo: Provide a mechanism (Action button?) to link a mail manually to an Alert """ if not auth.s3_logged_in(): session.error = T("Requires Login!") redirect(URL(c="default", f="user", args="login")) tablename = "msg_email" table = s3db.msg_email table.inbound.readable = False table.channel_id.readable = False table.to_address.readable = False from s3.s3query import FS s3.filter = (FS("response.id") == None) & \ (FS("inbound") == True) from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent crud_form = S3SQLCustomForm("date", "subject", "from_address", "body", S3SQLInlineComponent( "attachment", name = "document_id", label = T("Attachments"), fields = ["document_id"], ), ) s3db.configure(tablename, crud_form = crud_form, editable = False, insertable = False, list_fields = ["id", "date", "from_address", "subject", "body", (T("Attachments"), "attachment.document_id"), ], ) # CRUD Strings s3.crud_strings[tablename] = Storage( title_list = T("View InBox"), title_update = T("Edit Message"), label_list_button = T("View InBox"), label_delete_button = T("Delete Message"), msg_record_modified = T("Message updated"), msg_record_deleted = T("Message deleted"), msg_list_empty = T("No Messages currently in InBox") ) def prep(r): # Decode subject and sender fields decode = current.msg.decode_email if r.id: s3db.msg_attachment.document_id.label = "" if r.component and r.component.alias == "select": if not r.method: r.method = "select" if r.method == "select": r.custom_action = s3db.deploy_response_select_mission represent = lambda string: decode(string) elif not r.method and r.representation in ("html", "aadata"): # Use custom data table method to allow bulk deletion r.method = "inbox" r.custom_action = s3db.deploy_Inbox() represent = lambda string: s3base.s3_datatable_truncate(decode(string)) table = r.resource.table table.subject.represent = represent table.from_address.represent = represent return True s3.prep = prep def postp(r, output): if r.interactive and r.record and not r.component: # Custom CRUD button for linking the message to mission authorised = auth.s3_has_permission("create", "deploy_response") if authorised: s3.rfooter = s3base.S3CRUD.crud_button( T("Link to Mission"), _href = URL(f="email_inbox", args = [r.id, "select"], ), _class = "action-btn link", ) return output s3.postp = postp return s3_rest_controller("msg", "email")
def custom_prep(r): if r.interactive: s3db = current.s3db table = s3db.cms_post field = table.series_id field.label = T("Type") field.readable = field.writable = True #field.requires = field.requires.other #field = table.name #field.readable = field.writable = False #field = table.title #field.readable = field.writable = False field = table.avatar field.default = True #field.readable = field.writable = False field = table.replies field.default = False #field.readable = field.writable = False field = table.location_id field.represent = location_represent field.requires = IS_NULL_OR(IS_LOCATION(level="L3")) field.widget = S3LocationAutocompleteWidget(level="L3") #field.requires = IS_NULL_OR(IS_LOCATION()) #field.widget = S3LocationSelectorWidget2() table.created_by.represent = s3_auth_user_represent_name field = table.body field.label = T("Text") field.widget = None #table.comments.readable = table.comments.writable = False # Filter from a Profile page?" event_id = current.request.get_vars.get("(event)", None) if event_id: crud_form = S3SQLCustomForm( "series_id", "body", "location_id", S3SQLInlineComponent( "document", name="file", label=T("Files"), fields=[ "file", #"comments", ], ), ) def create_onaccept(form): table = current.s3db.event_event_post table.insert(event_id=event_id, post_id=form.vars.id) s3db.configure( "cms_post", create_onaccept=create_onaccept, ) else: crud_form = S3SQLCustomForm( "series_id", "body", "location_id", S3SQLInlineComponent( "event_post", label=T("Disaster(s)"), fields=["event_id"], orderby="event_id$name", ), S3SQLInlineComponent( "document", name="file", label=T("Files"), fields=[ "file", #"comments", ], ), ) # Return to List view after create/update/delete url_next = URL(c="default", f="index", args=None) list_fields = [ "series_id", "location_id", "created_on", "body", "created_by", "created_by$organisation_id", "document.file", "event_post.event_id", ] s3db.configure( "cms_post", create_next=url_next, delete_next=url_next, update_next=url_next, crud_form=crud_form, list_fields=list_fields, ) crud_settings = current.response.s3.crud crud_settings.formstyle = "bootstrap" crud_settings.submit_button = T("Save changes") # Done already within Bootstrap formstyle (& anyway fails with this formstyle) #crud_settings.submit_style = "btn btn-primary" # Call standard prep # (Done afterwards to ensure type field gets hidden) if callable(standard_prep): result = standard_prep(r) if not result: return False return True
def customize_project_project(**attr): """ Customize project_project controller """ db = current.db s3db = current.s3db s3 = current.response.s3 tablename = "project_project" # Load normal model table = s3db[tablename] # Custom Components add_component = s3db.add_component add_component("project_drrpp", project_project=Storage(joinby="project_id", multiple=False)) add_component("project_output", project_project="project_id") add_component("doc_document", project_project=dict( name="file", joinby="doc_id", filterby="url", filterfor=["", None], )) add_component("doc_document", project_project=dict( name="url", joinby="doc_id", filterby="file", filterfor=["", None], )) # Custom CRUD Strings crud_strings = s3.crud_strings crud_strings.project_project.title_search = T("Project List") # Custom Fields table.name.label = T("Project Title") s3db.project_project.budget.label = T("Total Funding (USD)") location_id = s3db.project_location.location_id location_id.label = "" # Limit to just Countries location_id.requires = s3db.gis_country_requires # Use dropdown, not AC location_id.widget = None # In DRRPP this is a free field table = s3db.project_organisation table.comments.label = T("Role") table.comments.widget = SQLFORM.widgets.string.widget table.amount.label = T("Amount") table = s3db.doc_document table.file.widget = lambda field, value, download_url: \ SQLFORM.widgets.upload.widget(field, value, download_url, _size = 15) table.comments.widget = SQLFORM.widgets.string.widget # If not logged in, contact person is required logged_in = current.auth.is_logged_in() if not logged_in: table = s3db.project_drrpp table.focal_person.required = True table.email.required = True table.email.requires = IS_EMAIL() # Custom dataTable s3["dataTable_sDom"] = 'ripl<"dataTable_table"t>p' # Don't show export buttons for XLS/XML s3.formats = Storage(xls=None, xml=None) # Remove rheader attr["rheader"] = None # Only show 10 Project by default to improve load time attr["dt_lengthMenu"] = [[10, 50, -1], [10, 50, T("All")]] s3.dataTable_iDisplayLength = 10 # Custom PreP standard_prep = s3.prep def custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) if not result: return False if r.method == "review": list_fields = [ "id", "created_on", "modified_on", "name", "start_date", (T("Countries"), "location.location_id"), (T("Hazards"), "hazard.name"), (T("Lead Organization"), "organisation_id"), (T("Donors"), "donor.organisation_id"), ] s3db.configure(tablename, list_fields=list_fields) if r.interactive: # Don't show Update/Delete button on Search table if r.method == "search": s3db.configure(tablename, editable=False, deletable=False) # JS to show/hide Cook Island fileds s3.scripts.append("/%s/static/themes/DRRPP/js/drrpp.js" % current.request.application) if r.method == "read": table_pl = s3db.project_location table_l = s3db.gis_location countries = [ row.name for row in db((table_pl.project_id == r.record.id) & (table_pl.location_id == table_l.id)). select(table_l.name) ] if not ("Cook Islands" in countries and len(countries) == 1): s3db.project_drrpp.L1.readable = False s3db.project_drrpp.pifacc.readable = False s3db.project_drrpp.jnap.readable = False elif r.representation == "xls": # All readable Fields should be exported list_fields = [ "id", "name", "code", "description", "status_id", "start_date", "end_date", "drrpp.duration", (T("Countries"), "location.location_id"), "drrpp.L1", (T("Hazards"), "hazard.name"), (T("Themes"), "theme.name"), "objectives", "drrpp.activities", "output.name", "drr.hfa", "drrpp.rfa", "drrpp.pifacc", "drrpp.jnap", (T("Lead Organization"), "organisation_id"), (T("Partners"), "partner.organisation_id"), (T("Donors"), "donor.organisation_id"), "budget", "currency", "drrpp.focal_person", "drrpp.organisation_id", "drrpp.email", "url.url", "drrpp.parent_project", "comments", ] if logged_in: list_fields.extend([ "created_by", "created_on", "modified_by", "modified_on", ]) s3db.configure(tablename, list_fields=list_fields) return True s3.prep = custom_prep # Custom List Fields list_fields = [ "id", "name", "start_date", (T("Countries"), "location.location_id"), (T("Hazards"), "hazard.name"), (T("Lead Organization"), "organisation_id"), (T("Donors"), "donor.organisation_id"), ] # Custom Search Fields from s3.s3search import S3Search, S3SearchSimpleWidget, S3SearchOptionsWidget simple = [ S3SearchSimpleWidget( name="project_search_text_simple", label=T("Search Projects"), comment=T("Search for a Project by name, code, or description."), field=[ "name", "code", "description", "location.location_id", "hazard.name", "theme.name", ]), S3SearchOptionsWidget( name="project_search_status_simple", label=T("Status"), field="status_id", cols=4, ), ] project_hfa_opts = s3db.project_hfa_opts() hfa_options = {} #hfa_options = {None:NONE} To search NO HFA for key in project_hfa_opts.keys(): hfa_options[key] = "HFA %s" % key project_rfa_opts = s3db.project_rfa_opts() rfa_options = {} #rfa_options = {None:NONE} To search NO RFA for key in project_rfa_opts.keys(): rfa_options[key] = "RFA %s" % key project_pifacc_opts = s3db.project_pifacc_opts() pifacc_options = {} #pifacc_options = {None:NONE} To search NO pifacc for key in project_pifacc_opts.keys(): pifacc_options[key] = "PIFACC %s" % key project_jnap_opts = s3db.project_jnap_opts() jnap_options = {} #jnap_options = {None:NONE} To search NO jnap for key in project_jnap_opts.keys(): jnap_options[key] = "JNAP %s" % key advanced = [ S3SearchSimpleWidget( name="project_search_text_advanced", label=T("Search Projects"), comment=T("Search for a Project by name, code, or description."), field=[ "name", "code", "description", "location.location_id", "hazard.name", "theme.name", ]), S3SearchOptionsWidget( name="project_search_status_advanced", label=T("Status"), field="status_id", cols=4, ), S3SearchOptionsWidget(name="project_search_location", label=T("Country"), field="location.location_id", cols=3), #S3SearchOptionsWidget(name = "project_search_L1", # label = T("Cook Islands"), # field = "drrpp.L1", # cols = 3 # ), S3SearchOptionsWidget(name="project_search_hazard", label=T("Hazard"), field="hazard.id", options=s3db.project_hazard_opts, help_field=s3db.project_hazard_helps, cols=4), S3SearchOptionsWidget( name="project_search_theme", label=T("Theme"), field="theme.id", options=s3db.project_theme_opts, help_field=s3db.project_theme_helps, cols=4, # Don't group size=30), S3SearchOptionsWidget(name="project_search_hfa", label=T("HFA"), field="drr.hfa", options=hfa_options, help_field=project_hfa_opts, cols=5), S3SearchOptionsWidget(name="project_search_rfa", label=T("RFA"), field="drrpp.rfa", options=rfa_options, help_field=project_rfa_opts, cols=6), S3SearchOptionsWidget(name="project_search_pifacc", label=T("PIFACC"), field="drrpp.pifacc", options=pifacc_options, help_field=project_pifacc_opts, cols=6), S3SearchOptionsWidget(name="project_search_jnap", label=T("JNAP"), field="drrpp.jnap", options=jnap_options, help_field=project_jnap_opts, cols=6), S3SearchOptionsWidget(name="project_search_organisation_id", label=T("Lead Organisation"), field="organisation_id", cols=3), S3SearchOptionsWidget( name="project_search_partners", field="partner.organisation_id", label=T("Partners"), cols=3, ), S3SearchOptionsWidget( name="project_search_donors", field="donor.organisation_id", label=T("Donors"), cols=3, ) ] search_method = S3Search(simple=simple, advanced=advanced) # Custom Report Fields report_fields = [ "name", (T("Countries"), "location.location_id"), (T("Hazards"), "hazard.name"), (T("Themes"), "theme.name"), (T("HFA Priorities"), "drr.hfa"), (T("RFA Priorities"), "drrpp.rfa"), (T("Lead Organization"), "organisation_id"), (T("Partner Organizations"), "partner.organisation_id"), (T("Donors"), "donor.organisation_id"), ] # Report Settings for charts if "chart" in current.request.vars: crud_strings[tablename].title_report = T("Project Graph") report_fact_fields = [("project.name", "count")] report_fact_default = "project.name" else: crud_strings[tablename].title_report = T("Project Matrix") report_fact_fields = [(field, "count") for field in report_fields] report_fact_default = "theme.name" report_options = Storage(search=advanced, rows=report_fields, cols=report_fields, fact=report_fact_fields, defaults=Storage(rows="hazard.name", cols="location.location_id", fact=report_fact_default, aggregate="count", totals=True)) # Custom Crud Form from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent, S3SQLInlineComponentCheckbox crud_form = S3SQLCustomForm( "name", "code", "description", "status_id", "start_date", "end_date", "drrpp.duration", S3SQLInlineComponent("location", label=T("Countries"), fields=["location_id"], orderby="location_id$name", render_list=True), "drrpp.L1", S3SQLInlineComponentCheckbox( "hazard", label=T("Hazards"), field="hazard_id", option_help="comments", cols=4, ), S3SQLInlineComponentCheckbox( "theme", label=T("Themes"), field="theme_id", option_help="comments", cols=3, ), "objectives", "drrpp.activities", # Outputs S3SQLInlineComponent( "output", label=T("Outputs"), fields=["name", "status"], ), "drr.hfa", "drrpp.rfa", "drrpp.pifacc", "drrpp.jnap", "organisation_id", # Partner Orgs S3SQLInlineComponent( "organisation", name="partner", label=T("Partner Organizations"), fields=[ "organisation_id", "comments", # NB This is labelled 'Role' in DRRPP ], filterby=dict(field="role", options=[2, 9]), default={"role": 2}), # Donors S3SQLInlineComponent("organisation", name="donor", label=T("Donor(s)"), fields=[ "organisation_id", "amount", "currency", ], filterby=dict(field="role", options=[3]), default={"role": 3}), "budget", "drrpp.local_budget", "drrpp.local_currency", "drrpp.focal_person", "drrpp.organisation_id", "drrpp.email", # Files S3SQLInlineComponent("document", name="file", label=T("Files"), fields=["file", "comments"], filterby=dict( field="file", options="", invert=True, )), # Links S3SQLInlineComponent("document", name="url", label=T("Links"), fields=["url", "comments"], filterby=dict( field="url", options=None, invert=True, )), "drrpp.parent_project", "comments", ) s3db.configure( tablename, crud_form=crud_form, list_fields=list_fields, report_options=report_options, search_method=search_method, subheadings={ 1: "hazard", 2: "theme", 3: "objectives", 4: "drr_hfa", 5: "drrpp_rfa", 6: "drrpp_pifacc", 7: "drrpp_jnap", 8: "organisation_id", }, ) return attr
def custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) else: result = True if r.interactive or r.representation == "aadata": list_fields = [ "id", "name", "acronym", "organisation_type_id", (T("Services"), "service.name"), (T("Neighborhoods Served"), "location.name"), ] s3db.configure("org_organisation", list_fields=list_fields) if r.interactive: from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent, S3SQLInlineComponentMultiSelectWidget s3db.pr_address.comments.label = "" s3db.pr_contact.value.label = "" s3db.doc_document.url.label = "" crud_form = S3SQLCustomForm( "name", "acronym", "organisation_type_id", #S3SQLInlineComponentCheckbox( S3SQLInlineComponentMultiSelectWidget( "service", label=T("Services"), field="service_id", cols=4, ), #S3SQLInlineComponentCheckbox( S3SQLInlineComponentMultiSelectWidget( "group", label=T("Network"), field="group_id", cols=3, ), S3SQLInlineComponent( "address", label=T("Address"), multiple=False, # This is just Text - put into the Comments box for now # Ultimately should go into location_id$addr_street fields=["comments"], ), #S3SQLInlineComponentCheckbox( S3SQLInlineComponentMultiSelectWidget( "location", label=T("Neighborhoods Served"), field="location_id", filterby=dict(field="level", options="L4"), # @ToDo: GroupedCheckbox Widget or Hierarchical MultiSelectWidget cols=5, ), "phone", S3SQLInlineComponent("contact", name="phone2", label=T("Phone2"), multiple=False, fields=["value"], filterby=dict(field="contact_method", options="WORK_PHONE")), S3SQLInlineComponent("contact", name="email", label=T("Email"), multiple=False, fields=["value"], filterby=dict(field="contact_method", options="EMAIL")), "website", S3SQLInlineComponent("contact", name="rss", label=T("RSS"), multiple=False, fields=["value"], filterby=dict(field="contact_method", options="RSS")), S3SQLInlineComponent("document", name="iCal", label="iCAL", multiple=False, fields=[ "url", ], filterby=dict(field="name", options="iCal")), S3SQLInlineComponent("document", name="data", label=T("Data"), multiple=False, fields=[ "url", ], filterby=dict(field="name", options="Data")), S3SQLInlineComponent("contact", name="twitter", label=T("Twitter"), multiple=False, fields=["value"], filterby=dict(field="contact_method", options="TWITTER")), S3SQLInlineComponent("contact", name="facebook", label=T("Facebook"), multiple=False, fields=["value"], filterby=dict(field="contact_method", options="FACEBOOK")), "comments", ) from s3.s3filter import S3LocationFilter, S3OptionsFilter, S3TextFilter filter_widgets = [ S3TextFilter( ["name", "acronym"], label=T("Name"), _class="filter-search", ), S3OptionsFilter( "group_membership.group_id", label=T("Network"), represent="%(name)s", widget="multiselect", cols=3, #hidden=True, ), S3LocationFilter( "organisation_location.location_id", label=T("Neighborhood"), levels=["L3", "L4"], widget="multiselect", cols=3, #hidden=True, ), S3OptionsFilter( "service_organisation.service_id", label=T("Service"), represent="%(name)s", widget="multiselect", cols=3, #hidden=True, ), S3OptionsFilter( "organisation_type_id", label=T("Type"), represent="%(name)s", widget="multiselect", cols=3, #hidden=True, ), ] s3db.configure( "org_organisation", crud_form=crud_form, filter_widgets=filter_widgets, ) return result