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": s3db = current.s3db if r.interactive: from s3.s3filter import S3TextFilter, S3OptionsFilter, S3LocationFilter filter_widgets = [ S3TextFilter( [ "name", "code", "comments", "organisation_id$name", "organisation_id$acronym", "location_id$name", "location_id$L1", "location_id$L2", ], label=T("Name"), _class="filter-search", ), #S3OptionsFilter("office_type_id", # label=T("Type"), # represent="%(name)s", # widget="multiselect", # cols=3, # #hidden=True, # ), S3OptionsFilter( "organisation_id", label=T("Organization"), represent="%(name)s", widget="multiselect", cols=3, #hidden=True, ), S3LocationFilter( "location_id", label=T("Location"), levels=["L1", "L2"], widget="multiselect", cols=3, #hidden=True, ), ] s3db.configure( "org_office", #crud_form=crud_form, filter_widgets=filter_widgets, ) return result
def custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) if not result: return False if r.interactive or r.representation == "aadata": # Configure fields field = r.table.duration field.readable = field.writable = True if r.interactive: 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"], 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, ), ] current.s3db.configure("project_project", filter_widgets = filter_widgets, ) return True
def custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) if not result: return False if r.interactive: from s3.s3filter import S3TextFilter, S3OptionsFilter, S3LocationFilter filter_widgets = [ S3TextFilter(["project_id$name", "project_id$code", "project_id$description", "organisation_id$name", "organisation_id$acronym", ], label=T("Name"), _class="filter-search", ), S3OptionsFilter("role", label=T("Role"), #represent="%(name)s", widget="multiselect", cols=3, #hidden=True, ), S3OptionsFilter("project_id$theme_project.theme_id", label=T("Theme"), represent="%(name)s", widget="multiselect", cols=3, #hidden=True, ), S3LocationFilter("project_id$location.location_id", label=T("Location"), levels=["L1", "L2"], widget="multiselect", cols=3, #hidden=True, ), ] report_fields = ["project_id", "organisation_id", "role", "amount", "currency", ] report_options = Storage( rows=report_fields, cols=report_fields, fact=report_fields, defaults=Storage(rows = "organisation_id", cols = "currency", fact = "sum(amount)", totals = False ) ) current.s3db.configure("project_organisation", filter_widgets = filter_widgets, report_options = report_options, ) return True
def custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) if not result: return False if r.interactive: messages = current.messages from s3.s3filter import S3TextFilter, S3OptionsFilter, S3LocationFilter, S3DateFilter filter_widgets = [ S3TextFilter(["project_id$name", "project_id$code", "project_id$description", "location_id$name", "project_id$organisation.name", "project_id$organisation.acronym", ], label=T("Name"), _class="filter-search", ), S3OptionsFilter("project_id$status_id", label=T("Status"), represent="%(name)s", #widget="multiselect", cols=3, #hidden=True, ), S3OptionsFilter("project_id$theme_project.theme_id", label=T("Theme"), represent="%(name)s", widget="multiselect", cols=3, #hidden=True, ), S3LocationFilter("location_id", label=T("Location"), levels=["L1", "L2"], widget="multiselect", cols=3, #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, ), ] report_fields = [ #(messages.COUNTRY, "location_id$L0"), "location_id$L1", "location_id$L2", #"location_id$L3", #"location_id$L4", (messages.ORGANISATION, "project_id$organisation_id"), (T("Project"), "project_id"), #(T("Activity Types"), "activity_type.activity_type_id"), (T("Themes"), "project_id$theme.name"), ] report_options = Storage( rows=report_fields, cols=report_fields, fact=report_fields, defaults=Storage(rows="location_id$L2", #cols=(T("Themes"), "project_id$theme.name"), cols="project_id$theme.name", # T("Projects") fact="count(project_id$name)", totals=True ) ) current.s3db.configure("project_location", filter_widgets = filter_widgets, report_options = report_options, ) 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 _updates(): """ Custom Page - Filterable DataList of CMS Posts & a DataList of Events """ #if not current.auth.is_logged_in(): # current.auth.permission.fail() T = current.T s3db = current.s3db request = current.request response = current.response s3 = response.s3 current.deployment_settings.ui.customize_cms_post() list_layout = s3.render_posts filter_widgets = [ S3TextFilter( ["body"], label="", _class="filter-search", #_placeholder=T("Search").upper(), ), S3OptionsFilter( "series_id", label=T("Filter by Type"), represent="%(name)s", widget="multiselect", cols=3, hidden=True, ), S3LocationFilter( "location_id", label=T("Filter by Location"), levels=["L1", "L2", "L3"], widget="multiselect", cols=3, hidden=True, ), S3OptionsFilter( "created_by$organisation_id", label=T("Filter by Organization"), represent="%(name)s", widget="multiselect", cols=3, hidden=True, ), S3DateFilter( "created_on", label=T("Filter by Date"), hide_time=True, hidden=True, ), ] s3db.configure( "cms_post", # We use a custom Advanced widget filter_advanced=False, filter_formstyle=filter_formstyle, filter_submit=(T("SEARCH"), "btn btn-primary"), filter_widgets=filter_widgets, list_layout=list_layout, # Create form comes via AJAX in a Modal insertable=False, ) s3.dl_pagelength = 6 # 5 forces an AJAX call if "datalist_dl_post" in request.args: # DataList pagination or Ajax-deletion request request.args = ["datalist_f"] ajax = "list" elif "datalist_dl_filter" in request.args: # FilterForm options update request request.args = ["filter"] ajax = "filter" elif "validate.json" in request.args: ajax = True else: # Default request.args = ["datalist_f"] ajax = None def prep(r): if ajax == "list": r.representation = "dl" elif ajax == "filter": r.representation = "json" return True s3.prep = prep output = current.rest_controller("cms", "post", list_ajaxurl=URL(f="index", args="datalist_dl_post"), filter_ajax_url=URL( f="index", args="datalist_dl_filter", vars={})) if ajax == "list": # Don't override view if this is an Ajax-deletion request if not "delete" in request.get_vars: response.view = "plain.html" elif not ajax: # Set Title & View after REST Controller, in order to override output["title"] = T("News Feed") view = path.join(request.folder, "private", "templates", THEME, "views", "updates.html") try: # Pass view as file not str to work in compiled mode response.view = open(view, "rb") except IOError: from gluon.http import HTTP raise HTTP("404", "Unable to open Custom View: %s" % view) scripts = [] sappend = scripts.append # Style the Search TextFilter widget sappend( '''$('#post-cms_post_body-text-filter__row').addClass('input-append').append('<span class="add-on"><i class="icon-search"></i></span>')''' ) # Button to toggle Advanced Form sappend( '''$('#list-filter').append('<a class="accordion-toggle"><i class="icon-reorder"></i> %s</a>')''' % T("Advanced Search")) sappend( '''$('.accordion-toggle').click(function(){$('.advanced').toggle()})''' ) s3.jquery_ready.append('''\n'''.join(scripts)) # Latest 5 Disasters resource = s3db.resource("event_event") list_fields = [ "name", "event_type_id$name", "zero_hour", "closed", ] orderby = resource.get_config("list_orderby", ~resource.table.created_on) datalist, numrows, ids = resource.datalist(fields=list_fields, start=None, limit=5, listid="event_datalist", orderby=orderby, layout=render_events) # Render the list data = datalist.html() if numrows == 0: # Empty table or just no match? table = resource.table if "deleted" in table: available_records = current.db(table.deleted != True) else: available_records = current.db(table._id > 0) if available_records.select(table._id, limitby=(0, 1)).first(): msg = DIV(S3CRUD.crud_string(resource.tablename, "msg_no_match"), _class="empty") else: msg = DIV(S3CRUD.crud_string(resource.tablename, "msg_list_empty"), _class="empty") data.insert(1, msg) output["disasters"] = data return output
def newsfeed(): """ RESTful CRUD controller for display of posts as a filterable dataList (use with /datalist method) """ # Load Model table = s3db.cms_post stable = db.cms_series # Hide Posts linked to Modules and Maps & Expired Posts s3.filter = (FS("post_module.module") == None) & \ (FS("post_layer.layer_id") == None) & \ (FS("expired") != True) title_list = T("Latest Information") # Ensure that filtered views translate into options which update the Widget if "~.series_id$name" in get_vars: series_name = get_vars["~.series_id$name"] # Disabled as can change filters dynamically # @ToDo: Better Mechanism: Another field in cms_series? #if series_name == "Request": # title_list = T("Latest Requests") #elif series_name == "Offer": # title_list = T("Latest Offers") series = db(stable.name == series_name).select(stable.id, cache=s3db.cache, limitby=(0, 1)).first() if series: series_id = str(series.id) get_vars.pop("~.series_id$name") get_vars["~.series_id__belongs"] = series_id s3.crud_strings["cms_post"].title_list = title_list contact_field = settings.get_cms_person() org_field = settings.get_cms_organisation() org_group_field = settings.get_cms_organisation_group() show_events = settings.get_cms_show_events() hidden = not settings.get_cms_filter_open() from s3.s3filter import S3TextFilter, S3OptionsFilter, S3LocationFilter, S3DateFilter filter_widgets = [ S3TextFilter( ["body"], label=T("Search"), _class="filter-search", #_placeholder = T("Search").upper(), ), S3LocationFilter( "location_id", label=T("Filter by Location"), hidden=hidden, ), ] fappend = filter_widgets.append finsert = filter_widgets.insert if show_events: fappend( S3OptionsFilter( "event_post.event_id", label=T("Filter by Disaster"), hidden=hidden, )) if org_field: fappend( S3OptionsFilter( org_field, label=T("Filter by Organization"), # Can't use this for created_by as integer, use field.represent instead #represent = "%(name)s", hidden=hidden, )) if org_group_field: group_label = settings.get_org_groups() if group_label: fappend( S3OptionsFilter( org_group_field, label=T("Filter by %(type)s") % dict(type=T(group_label)), # Can't use this for created_by as integer, use field.represent instead #represent = "%(name)s", hidden=hidden, )) fappend( S3DateFilter( "date", label=T("Filter by Date"), hide_time=True, hidden=hidden, )) if settings.get_cms_show_tags(): finsert( 1, S3OptionsFilter( "tag_post.tag_id", label=T("Filter by Tag"), represent="%(name)s", hidden=hidden, )) if settings.get_cms_bookmarks() and auth.user: finsert( 1, S3OptionsFilter( "bookmark.user_id", label=T("Filter by Bookmark"), # Can't just use "" as this is then omitted from rendering options={ "*": T("All"), auth.user.id: T("My Bookmarks"), }, cols=2, multiple=False, hidden=hidden, )) notify_fields = [ (T("Date"), "date"), (T("Location"), "location_id"), ] len_series = db(stable.deleted == False).count() if len_series > 3: notify_fields.insert(0, (T("Type"), "series_id")) # Multiselect widget finsert( 1, S3OptionsFilter( "series_id", label=T("Filter by Type"), # We want translations #represent = "%(name)s", hidden=hidden, )) elif len_series > 1: notify_fields.insert(0, (T("Type"), "series_id")) # Checkboxes finsert( 1, S3OptionsFilter( "series_id", label=T("Filter by Type"), # We want translations #represent = "%(name)s", cols=2, hidden=hidden, )) else: # No Widget or notify_field pass nappend = notify_fields.append if org_field: nappend((T("Organization"), org_field)) if org_group_field: if isinstance(group_label, bool): group_label = T("Organisation Group") nappend((T(group_label), org_group_field)) if contact_field: nappend((T("Contact"), contact_field)) nappend((T("Description"), "body")) # @todo: allow configuration (?) filter_formstyle = settings.get_ui_formstyle() s3db.configure( "cms_post", # We could use a custom Advanced widget #filter_advanced = False, filter_formstyle=filter_formstyle, # No Submit button (done automatically) #filter_submit = (T("SEARCH"), "btn btn-primary"), filter_widgets=filter_widgets, # Default anyway now: #list_layout = s3db.cms_post_list_layout, # Create form comes via AJAX in a Modal #insertable = False, notify_fields=notify_fields, notify_template="notify_post", ) s3.dl_pagelength = 6 # 5 forces an AJAX call 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 s3.prep = prep def postp(r, output): if r.interactive: if r.method == "datalist" and r.representation != "dl": # Hide side menu current.menu.options = None response.view = s3base.S3CRUD._view(r, "cms/newsfeed.html") return output s3.postp = postp output = s3_rest_controller("cms", "post") return output
def homepage(): """ Custom Homepage - DataList of CMS Posts """ if not current.auth.is_logged_in(): return login() T = current.T s3db = current.s3db request = current.request response = current.response s3 = response.s3 current.deployment_settings.ui.customize_cms_post() list_layout = render_homepage_posts filter_widgets = [ S3TextFilter(["body"], label="", _class="filter-search", _placeholder=T("Search").upper()), S3OptionsFilter("series_id", label=T("Filter by Type"), represent="%(name)s", cols=3), S3OptionsFilter("location_id", label=T("Filter by Location"), represent="%(name)s", widget="multiselect", cols=3), S3OptionsFilter("created_by$organisation_id", label=T("Filter by Organization"), represent="%(name)s", widget="multiselect", cols=3), S3DateFilter("created_on", label=T("Filter by Date")), ] s3db.configure( "cms_post", filter_formstyle=filter_formstyle, filter_submit=(T("Filter Results"), "btn btn-primary"), filter_widgets=filter_widgets, list_layout=list_layout, ) s3.dl_pagelength = 6 # 5 forces an AJAX call if "datalist_dl_post" in request.args: ajax = True else: ajax = False def prep(r): if ajax: r.representation = "dl" return True s3.prep = prep request.args = ["datalist"] output = current.rest_controller("cms", "post", list_ajaxurl=URL(f="index", args="datalist_dl_post")) if ajax: response.view = "plain.html" else: form = output["form"] # Remove duplicate Submit button form[0][-1] = "" if form.errors: s3.jquery_ready.append('''$("#myModal").modal("show")''') # Set Title & View after REST Controller, in order to override output[ "title"] = response.title = current.deployment_settings.get_system_name( ) view = path.join(request.folder, "private", "templates", "CSN", "views", "index.html") try: # Pass view as file not str to work in compiled mode response.view = open(view, "rb") except IOError: from gluon.http import HTTP raise HTTP(404, "Unable to open Custom View: %s" % view) # Latest 5 Disasters resource = s3db.resource("event_event") list_fields = [ "name", "zero_hour", "closed", ] orderby = resource.get_config("list_orderby", ~resource.table.created_on) datalist, numrows, ids = resource.datalist( fields=list_fields, start=None, limit=5, list_id="event_datalist", orderby=orderby, layout=render_homepage_events) if numrows == 0: # Empty table or just no match? table = resource.table if "deleted" in table: available_records = current.db(table.deleted != True) else: available_records = current.db(table._id > 0) if available_records.select(table._id, limitby=(0, 1)).first(): msg = DIV(S3CRUD.crud_string(resource.tablename, "msg_no_match"), _class="empty") else: msg = DIV(S3CRUD.crud_string(resource.tablename, "msg_list_empty"), _class="empty") data = msg else: # Render the list dl = datalist.html() data = dl output["disasters"] = data return output
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 custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) if not result: return False if r.interactive or r.representation == "aadata": s3db.org_customize_org_resource_fields(r.method) # Configure fields #table.site_id.readable = table.site_id.readable = False location_field = table.location_id #location_field.label = T("District") from s3.s3filter import S3TextFilter, S3OptionsFilter filter_widgets = [ S3TextFilter([ "organisation_id$name", "location_id", "parameter_id$name", "comments", ], label=T("Search")), S3OptionsFilter( "parameter_id", label=T("Type"), widget="multiselect", ), ] s3db.configure("org_resource", filter_widgets=filter_widgets) # Filter from a Profile page? # If so, then default the fields we know get_vars = current.request.get_vars location_id = get_vars.get("~.(location)", None) organisation_id = get_vars.get("~.(organisation)", None) if organisation_id: org_field = table.organisation_id org_field.default = organisation_id org_field.readable = org_field.writable = False if location_id: location_field.default = location_id # We still want to be able to specify a precise location #location_field.readable = location_field.writable = False location_field.requires = IS_LOCATION_SELECTOR2(levels=levels) location_field.widget = S3LocationSelectorWidget2( levels=levels, show_address=True, show_map=True) # Don't add new Locations here location_field.comment = None # Return to Sumamry view after create/update/delete (unless done via Modal) url_next = URL(c="org", f="resource", args="summary") s3db.configure( "org_resource", create_next=url_next, delete_next=url_next, update_next=url_next, # Don't include a Create form in 'More' popups listadd=False if r.method == "datalist" else True, ) # This is awful in Popups & inconsistent in dataTable view (People/Documents don't have this & it breaks the styling of the main Save button) #s3.cancel = URL(c="org", f="resource") return True
def custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) if not result: return False if r.interactive or r.representation == "aadata": # Load normal Model s3db = current.s3db table = s3db.org_organisation ADD_ORGANISATION = T("New Stakeholder") s3.crud_strings["org_organisation"] = Storage( title_create=ADD_ORGANISATION, title_display=T("Stakeholder Details"), title_list=T("Stakeholders"), title_update=T("Edit Stakeholder"), title_search=T("Search Stakeholders"), subtitle_create=T("Add New Stakeholder"), label_list_button=T("List Stakeholders"), label_create_button=ADD_ORGANISATION, label_delete_button=T("Delete Stakeholder"), msg_record_created=T("Stakeholder added"), msg_record_modified=T("Stakeholder updated"), msg_record_deleted=T("Stakeholder deleted"), msg_list_empty=T("No Stakeholders currently registered")) list_fields = [ "id", "name", "logo", "phone", "website", ] if r.method == "datalist": # Stakeholder selection page # 2-column datalist, 6 rows per page s3.dl_pagelength = 12 s3.dl_rowsize = 2 from s3.s3filter import S3TextFilter, S3OptionsFilter filter_widgets = [ S3TextFilter([ "name", "acronym", "website", "comments", ], label=T("Search")), S3OptionsFilter( "organisation_type_id", label=T("Type"), widget="multiselect", ), ] s3db.configure("org_organisation", filter_widgets=filter_widgets) # Labels table.comments.label = T("Description") crud_form = S3SQLCustomForm("id", "name", "organisation_type_id", "logo", "phone", "website", "comments") # Return to List view after create/update/delete (unless done via Modal) url_next = URL(c="org", f="organisation", args="datalist") s3db.configure( "org_organisation", create_next=url_next, crud_form=crud_form, delete_next=url_next, # We want the Create form to be in a modal, not inline, for consistency #listadd = False, list_fields=list_fields, update_next=url_next, ) return True
def customise_org_facility_resource(r, tablename): """ Customise event_event resource - List Fields - Form - Filter - Report Runs after controller customisation But runs before prep """ s3db = current.s3db list_fields = [ "name", (T("Type"), "facility_type.name"), #"organisation_id", "location_id", "contact", "phone1", "email", "comments", ] from s3.s3filter import S3OptionsFilter, S3TextFilter filter_widgets = [ S3TextFilter( [ "name", "site_facility_type.facility_type_id", #"organisation_id", "location_id", "contact", "phone1", "email", "comments" ], label=T("Search"), ), S3OptionsFilter( "site_facility_type.facility_type_id", header=True, label=T("Type of Place"), ), #S3OptionsFilter("organisation_id", # header = True, # represent = "%(name)s", # ), ] report_fields = [ #"name", "site_facility_type.facility_type_id", "site_org_group.group_id", "location_id$L3", "organisation_id", ] report_options = Storage( rows=report_fields, cols=[], fact=[(T("Number of Facilities"), "count(name)")], defaults=Storage( rows="site_facility_type.facility_type_id", #cols="site_org_group.group_id", fact="count(name)", totals=True, chart="barchart:rows", table="collapse", )) from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponentMultiSelectWidget # Custom Crud Form crud_form = S3SQLCustomForm( "name", S3SQLInlineComponentMultiSelectWidget( "facility_type", #label = T("Type of Place"), field="facility_type_id", ), #"organisation_id", "location_id", "contact", "phone1", "email", "comments", ) s3db.configure( tablename, crud_form=crud_form, filter_widgets=filter_widgets, list_fields=list_fields, report_options=report_options, )
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 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
def custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) if not result: return False if r.interactive: from s3.s3filter import S3TextFilter, S3OptionsFilter, S3LocationFilter filter_widgets = [ S3TextFilter(["project_id$name", "project_id$code", "project_id$description", "project_id$organisation.name", "project_id$organisation.acronym", ], label=T("Name"), _class="filter-search", ), S3OptionsFilter("parameter_id", label=T("Beneficiary Type"), represent="%(name)s", widget="multiselect", cols=3, #hidden=True, ), S3OptionsFilter("project_id$theme_project.theme_id", label=T("Theme"), represent="%(name)s", widget="multiselect", cols=3, #hidden=True, ), S3LocationFilter("project_location_id$location_id", label=T("Location"), levels=["L1", "L2"], widget="multiselect", cols=3, #hidden=True, ), ] report_fields = ["project_location_id", (T("Beneficiary Type"), "parameter_id"), "project_id", (T("Year"), "year"), #"project_id$hazard.name", "project_id$theme.name", #(current.messages.COUNTRY, "location_id$L0"), "location_id$L1", "location_id$L2", "location_id$L3", "location_id$L4", ] report_options = Storage( rows=report_fields, cols=report_fields, fact=report_fields, defaults=Storage(rows="project_id", cols="parameter_id", fact="sum(value)", totals=True ) ) current.s3db.configure("project_organisation", filter_widgets = filter_widgets, report_options = report_options, ) return True
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 _newsfeed(): """ Custom Page - Filterable DataList of CMS Posts & a DataList of Events """ #if not current.auth.is_logged_in(): # current.auth.permission.fail() T = current.T s3db = current.s3db request = current.request response = current.response s3 = response.s3 # Ensure that filtered views translate into options which update the Widget get_vars = request.get_vars if "~.series_id$name" in get_vars: series_name = get_vars["~.series_id$name"] table = s3db.cms_series series = current.db(table.name == series_name).select( table.id, limitby=(0, 1)).first() if series: series_id = str(series.id) get_vars.pop("~.series_id$name") get_vars["~.series_id__belongs"] = series_id current.deployment_settings.ui.customize_cms_post() list_layout = s3.render_posts filter_widgets = [ S3TextFilter( ["body"], label="", _class="filter-search", #_placeholder=T("Search").upper(), ), S3OptionsFilter( "series_id", label=T("Filter by Type"), represent="%(name)s", widget="multiselect", hidden=True, ), S3LocationFilter( "location_id", label=T("Filter by Location"), levels=["L1", "L2", "L3"], widget="multiselect", hidden=True, ), S3OptionsFilter( "created_by$organisation_id", label=T("Filter by Organization"), # Can't use this for integers, use field.represent instead #represent="%(name)s", widget="multiselect", hidden=True, ), S3DateFilter( "created_on", label=T("Filter by Date"), hide_time=True, hidden=True, ), ] s3db.configure( "cms_post", # We use a custom Advanced widget filter_advanced=False, filter_formstyle=filter_formstyle, filter_submit=(T("SEARCH"), "btn btn-primary"), filter_widgets=filter_widgets, list_layout=list_layout, # Create form comes via AJAX in a Modal insertable=False, notify_fields=[ (T("Type"), "series_id"), (T("Date"), "date"), (T("Location"), "location_id"), (T("Description"), "body"), ], notify_template="notify_post", ) s3.dl_pagelength = 6 # 5 forces an AJAX call old_args = request.args if "datalist_dl_post" in old_args: # DataList pagination or Ajax-deletion request request.args = ["datalist_f"] ajax = "list" elif "datalist_dl_filter" in old_args: # FilterForm options update request request.args = ["filter"] ajax = "filter" elif "validate.json" in old_args: # Inline component validation request request.args = [] ajax = True elif current.auth.permission.format == "msg": # Subscription lookup request request.args = [] ajax = True else: # Default request.args = ["datalist_f"] ajax = None def prep(r): if ajax == "list": r.representation = "dl" elif ajax == "filter": r.representation = "json" return True s3.prep = prep output = current.rest_controller( "cms", "post", list_ajaxurl=URL(f="index", args="datalist_dl_post"), filter_ajax_url=URL(f="index", args="datalist_dl_filter", vars={}), ) request.args = old_args if ajax == "list": # Don't override view if this is an Ajax-deletion request if not "delete" in request.get_vars: response.view = "plain.html" elif not ajax: # Set Title & View after REST Controller, in order to override output["title"] = T("News Feed") view = path.join(request.folder, "private", "templates", THEME, "views", "newsfeed.html") try: # Pass view as file not str to work in compiled mode response.view = open(view, "rb") except IOError: from gluon.http import HTTP raise HTTP(404, "Unable to open Custom View: %s" % view) s3.js_global.append('''i18n.adv_search="%s"''' % T("Advanced Search")) s3.scripts.append("/%s/static/themes/%s/js/newsfeed.js" % (request.application, THEME)) # Latest 5 Disasters resource = s3db.resource("event_event") layout = render_events list_id = "event_datalist" limit = 5 orderby = "zero_hour desc" list_fields = [ "name", "event_type_id$name", "zero_hour", "closed", ] output["disasters"] = latest_records(resource, layout, list_id, limit, list_fields, orderby) return output
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.method in ("form", "lookup"): return True elif r.method == "summary": from s3.s3filter import S3TextFilter, S3OptionsFilter, S3LocationFilter settings.ui.filter_auto_submit = 750 settings.ui.report_auto_submit = 750 s3.crud_strings["hrm_human_resource"]["title_list"] = T( "Staff & Volunteers") filter_widgets = [ S3TextFilter( [ "person_id$first_name", "person_id$middle_name", "person_id$last_name", ], label=T("Name"), ), S3OptionsFilter( "type", label="", options=s3db.hrm_type_opts, hidden=True, ), S3OptionsFilter( "details.active", label="", options={ True: T("Active"), False: T("Inactive"), }, hidden=True, ), S3OptionsFilter( "organisation_id", widget="multiselect", filter=True, header="", hidden=True, ), S3OptionsFilter( "programme_hours.programme_id", widget="multiselect", hidden=True, ), S3LocationFilter( "location_id", label=T("Location"), widget="multiselect", levels=["L0", "L1", "L2", "L3"], hidden=True, ), S3OptionsFilter( "training.course_id", label=T("Training"), widget="multiselect", hidden=True, ), ] teams = settings.get_hrm_teams() if teams: if teams == "Teams": teams = "Team" elif teams == "Groups": teams = "Group" filter_widgets.append( S3OptionsFilter( "group_membership.group_id", label=T(teams), widget="multiselect", hidden=True, )) report_fields = [ "organisation_id", "person_id", "person_id$gender", "job_title_id", (T("Training"), "training.course_id"), "location_id$L1", "location_id$L2", "person_id$age_group", "person_id$education.level", ] report_options = Storage(rows=report_fields, cols=report_fields, fact=report_fields, defaults=Storage( rows="organisation_id", cols="training.course_id", fact="count(person_id)", totals=True)) s3db.configure( "hrm_human_resource", filter_widgets=filter_widgets, # Match staff list_fields=[ "id", "person_id", "job_title_id", "organisation_id", "department_id", "site_id", (T("Email"), "email.value"), (settings.get_ui_label_mobile_phone(), "phone.value"), ], # Needed for Age Group VirtualField to avoid extra DB calls report_fields=["person_id$date_of_birth"], report_options=report_options, summary=[ { "name": "table", "label": "Table", "widgets": [{ "method": "datatable" }] }, { "name": "report", "label": "Report", "widgets": [{ "method": "report2", "ajax_init": True }] }, { "name": "map", "label": "Map", "widgets": [{ "method": "map", "ajax_init": True }], }, ], ) s3.filter = None else: # Default to Volunteers type_filter = s3base.S3FieldSelector("type") == 2 r.resource.add_filter(type_filter) if r.interactive: if r.method == "create" and not r.component: redirect(URL(f="volunteer", args=args, vars=vars)) elif r.method == "delete": # Don't redirect pass elif r.id: # Redirect to person controller vars = {"human_resource.id": r.id, "group": "volunteer"} redirect(URL(f="person", vars=vars)) return True
def customize_project_location(**attr): """ Customize project_location controller """ s3db = current.s3db s3 = current.response.s3 # Load normal model table = s3db.project_location # Custom Components s3db.add_component("project_drrpp", project_project=Storage(joinby="project_id", multiple=False)) # Custom CRUD Strings s3.crud_strings.project_location.title_map = T("Project Map") # Custom Search Filters from s3.s3filter import S3TextFilter, S3OptionsFilter, S3LocationFilter filter_widgets = [ S3TextFilter( [ "project_id$name", "project_id$code", "project_id$description", #"location_id$name", #"project_id$organisation.name", #"project_id$organisation.acronym", ], label=T("Search Projects"), _class="filter-search", ), S3OptionsFilter( "project_id$status_id", label=T("Status"), represent="%(name)s", #widget="multiselect", cols=3, #hidden=True, ), S3LocationFilter( "location_id", label=T("Country"), levels=["L0"], #widget="multiselect", cols=3, hidden=True, ), S3OptionsFilter( "project_id$hazard_project.hazard_id", label=T("Hazard"), represent="%(name)s", #widget="multiselect", cols=4, hidden=True, ), S3OptionsFilter( "project_id$theme_project.theme_id", label=T("Theme"), represent="%(name)s", #widget="multiselect", cols=4, hidden=True, ), S3OptionsFilter( "project_id$drr.hfa", label=T("HFA"), #represent="%(name)s", #widget="multiselect", cols=5, hidden=True, ), S3OptionsFilter( "project_id$drrpp.rfa", label=T("RFA"), #represent="%(name)s", #widget="multiselect", cols=6, hidden=True, ), S3OptionsFilter( "project_id$organisation_id", label=T("Lead Organization"), represent="%(name)s", #widget="multiselect", cols=3, hidden=True, ), S3OptionsFilter( "project_id$partner.organisation_id", label=T("Partners"), represent="%(name)s", #widget="multiselect", cols=3, hidden=True, ), S3OptionsFilter( "project_id$donor.organisation_id", label=T("Donors"), represent="%(name)s", #widget="multiselect", cols=3, hidden=True, ), ] s3db.configure( "project_location", filter_widgets=filter_widgets, # Add CSS to default class better than patching #map_submit=(T("Search"), "search-button"), map_advanced=(T("Advanced Search"), T("Simple Search")), ) return attr
def newsfeed(): """ RESTful CRUD controller for display of posts as a filterable dataList """ # Load Model table = s3db.cms_post title_list = T("Latest Information") # Hide Posts linked to Modules & Expired Posts FS = s3base.S3FieldSelector s3.filter = (FS("post_module.module") == None) & (FS("expired") != True) # Ensure that filtered views translate into options which update the Widget get_vars = request.get_vars if "~.series_id$name" in get_vars: series_name = get_vars["~.series_id$name"] # Disabled as can change filters dynamically # @ToDo: Better Mechanism: Another field in cms_series? #if series_name == "Request": # title_list = T("Latest Requests") #elif series_name == "Offer": # title_list = T("Latest Offers") stable = s3db.cms_series series = db(stable.name == series_name).select(stable.id, limitby=(0, 1)).first() if series: series_id = str(series.id) get_vars.pop("~.series_id$name") get_vars["~.series_id__belongs"] = series_id s3.crud_strings["cms_post"].title_list = title_list # Which levels of Hierarchy are we using? hierarchy = gis.get_location_hierarchy() levels = hierarchy.keys() if len(settings.get_gis_countries()) == 1: levels.remove("L0") # @ToDo: deployment_setting #org_field = "created_by$organisation_id" org_field = "post_organisation.organisation_id" # @ToDo: deployment_setting #contact_field = "created_by" #table.created_by.represent = s3_auth_user_represent_name contact_field = "person_id" from s3.s3filter import S3TextFilter, S3OptionsFilter, S3LocationFilter, S3DateFilter filter_widgets = [ S3TextFilter( ["body"], label=T("Search"), _class="filter-search", #_placeholder=T("Search").upper(), ), S3LocationFilter( "location_id", label=T("Filter by Location"), levels=levels, widget="multiselect", hidden=True, ), S3OptionsFilter( org_field, label=T("Filter by Organization"), # Can't use this for created_by as integer, use field.represent instead #represent="%(name)s", widget="multiselect", hidden=True, ), S3DateFilter( "date", label=T("Filter by Date"), hide_time=True, hidden=True, ), ] if settings.get_cms_show_tags(): filter_widgets.insert( 1, S3OptionsFilter( "tag_post.tag_id", label=T("Filter by Tag"), represent="%(name)s", widget="multiselect", hidden=True, )) if settings.get_cms_bookmarks() and auth.user: filter_widgets.insert( 1, S3OptionsFilter( "bookmark.user_id", label=T("Filter by Bookmark"), # Can't just use "" as this is then omitted from rendering options={ "*": T("All"), auth.user.id: T("My Bookmarks"), }, hidden=True, multiple=False, )) len_series = db(s3db.cms_series.deleted == False).count() if len_series > 3: # Multiselect widget filter_widgets.insert( 1, S3OptionsFilter( "series_id", label=T("Filter by Type"), # We want translations #represent="%(name)s", widget="multiselect", hidden=True, )) elif len_series > 1: # Checkboxes filter_widgets.insert( 1, S3OptionsFilter( "series_id", label=T("Filter by Type"), # We want translations #represent="%(name)s", cols=2, hidden=True, )) else: # No Widget pass s3db.configure( "cms_post", # We could use a custom Advanced widget #filter_advanced = False, filter_formstyle=filter_formstyle, # No Submit button (done automatically) #filter_submit = (T("SEARCH"), "btn btn-primary"), filter_widgets=filter_widgets, list_layout=s3db.cms_render_posts, # Create form comes via AJAX in a Modal #insertable = False, notify_fields=[ (T("Type"), "series_id"), (T("Date"), "date"), (T("Location"), "location_id"), (T("Organization"), org_field), (T("Contact"), contact_field), (T("Description"), "body"), ], notify_template="notify_post", ) s3.dl_pagelength = 6 # 5 forces an AJAX call 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 s3.prep = prep def postp(r, output): if r.interactive: if r.method == "datalist" and r.representation != "dl": # Hide side menu current.menu.options = None response.view = s3base.S3CRUD._view(r, "cms/newsfeed.html") return output s3.postp = postp output = s3_rest_controller( "cms", "post", hide_filter=False, ) return output
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": s3db = current.s3db list_fields = ["id", "name", "acronym", "organisation_type_id", (T("Clusters"), "sector.name"), "country", "website" ] s3db.configure("org_organisation", list_fields=list_fields) if r.interactive: from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponentCheckbox crud_form = S3SQLCustomForm( "name", "acronym", "organisation_type_id", "region_id", "country", S3SQLInlineComponentCheckbox( "sector", label = T("Clusters"), field = "sector_id", cols = 3, ), "phone", "website", "year", "logo", "comments", ) from s3.s3filter import S3TextFilter, S3OptionsFilter, S3LocationFilter filter_widgets = [ S3TextFilter(["name", "acronym"], label=T("Name"), _class="filter-search", ), S3OptionsFilter("organisation_type_id", label=T("Type"), represent="%(name)s", widget="multiselect", cols=3, #hidden=True, ), S3OptionsFilter("sector_organisation.sector_id", label=T("Cluster"), represent="%(name)s", widget="multiselect", cols=3, #hidden=True, ), S3OptionsFilter("project_organisation.project_id$theme_project.theme_id", label=T("Theme"), represent="%(name)s", widget="multiselect", cols=3, #hidden=True, ), S3LocationFilter("project_organisation.project_id$location.location_id", label=T("Location"), levels=["L1", "L2"], widget="multiselect", cols=3, #hidden=True, ), ] s3db.configure("org_organisation", crud_form=crud_form, filter_widgets = filter_widgets, ) return result
def _newsfeed(): """ Custom Page - Filterable DataList of CMS Posts & a DataList of Events """ #if not current.auth.is_logged_in(): # current.auth.permission.fail() T = current.T s3db = current.s3db request = current.request response = current.response s3 = response.s3 # Ensure that filtered views translate into options which update the Widget if "~.series_id$name" in request.get_vars: series_name = request.vars["~.series_id$name"] table = s3db.cms_series series = current.db(table.name == series_name).select( table.id, limitby=(0, 1)).first() if series: series_id = str(series.id) request.get_vars.pop("~.series_id$name") request.get_vars["~.series_id__belongs"] = series_id current.deployment_settings.ui.customize_cms_post() list_layout = s3.render_posts filter_widgets = [ S3TextFilter( ["body"], label="", _class="filter-search", #_placeholder=T("Search").upper(), ), S3OptionsFilter( "series_id", label=T("Filter by Type"), represent="%(name)s", widget="multiselect", hidden=True, ), S3LocationFilter( "location_id", label=T("Filter by Location"), levels=["L1", "L2", "L3"], widget="multiselect", hidden=True, ), S3OptionsFilter( "created_by$organisation_id", label=T("Filter by Organization"), # Can't use this for integers, use field.represent instead #represent="%(name)s", widget="multiselect", hidden=True, ), S3DateFilter( "created_on", label=T("Filter by Date"), hide_time=True, hidden=True, ), ] s3db.configure( "cms_post", # We use a custom Advanced widget filter_advanced=False, filter_formstyle=filter_formstyle, filter_submit=(T("SEARCH"), "btn btn-primary"), filter_widgets=filter_widgets, list_layout=list_layout, # Create form comes via AJAX in a Modal insertable=False, notify_fields=[ (T("Type"), "series_id"), (T("Date"), "date"), (T("Location"), "location_id"), (T("Description"), "body"), ], notify_template="notify_post", ) s3.dl_pagelength = 6 # 5 forces an AJAX call old_args = request.args if "datalist_dl_post" in old_args: # DataList pagination or Ajax-deletion request request.args = ["datalist_f"] ajax = "list" elif "datalist_dl_filter" in old_args: # FilterForm options update request request.args = ["filter"] ajax = "filter" elif "validate.json" in old_args: # Inline component validation request request.args = [] ajax = True elif current.auth.permission.format == "msg": # Subscription lookup request request.args = [] ajax = True else: # Default request.args = ["datalist_f"] ajax = None def prep(r): if ajax == "list": r.representation = "dl" elif ajax == "filter": r.representation = "json" return True s3.prep = prep output = current.rest_controller("cms", "post", list_ajaxurl=URL(f="index", args="datalist_dl_post"), filter_ajax_url=URL( f="index", args="datalist_dl_filter", vars={})) request.args = old_args if ajax == "list": # Don't override view if this is an Ajax-deletion request if not "delete" in request.get_vars: response.view = "plain.html" elif not ajax: # Set Title & View after REST Controller, in order to override output["title"] = T("News Feed") view = path.join(request.folder, "private", "templates", THEME, "views", "newsfeed.html") try: # Pass view as file not str to work in compiled mode response.view = open(view, "rb") except IOError: from gluon.http import HTTP raise HTTP(404, "Unable to open Custom View: %s" % view) scripts = [] sappend = scripts.append # Style the Search TextFilter widget sappend( '''$('#post-cms_post_body-text-filter__row').addClass('input-append').append('<span class="add-on"><i class="icon-search"></i></span>')''' ) # Button to toggle Advanced Form sappend( '''$('#list-filter').append('<a class="accordion-toggle"><i class="icon-reorder"></i> %s</a>')''' % T("Advanced Search")) # Toggle doesn't work directly when removing 'hide' & requires a 2nd click to open without this sappend( '''$('.accordion-toggle').click(function(){var a=$('.advanced');if(a.hasClass('hide')){a.removeClass('hide').show()}else{a.toggle()}})''' ) s3.jquery_ready.append('''\n'''.join(scripts)) # Latest 5 Disasters # resource = s3db.resource("event_event") # layout = render_events # list_id = "event_datalist" # limit = 5 # orderby = "start_date desc" # list_fields = ["name", # "event_type_id$name", # "start_date", # "closed", # ] # output["disasters"] = latest_records(resource, layout, list_id, limit, list_fields, orderby) return output
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": if not r.component: s3db = current.s3db table = r.table table.department_id.readable = table.department_id.writable = False table.end_date.readable = table.end_date.writable = False list_fields = ["id", "person_id", "job_title_id", "organisation_id", (T("Groups"), "person_id$group_membership.group_id"), "site_id", #"site_contact", (T("Email"), "email.value"), (settings.get_ui_label_mobile_phone(), "phone.value"), ] from s3.s3filter import S3TextFilter, S3OptionsFilter, S3LocationFilter filter_widgets = [ S3TextFilter(["person_id$first_name", "person_id$middle_name", "person_id$last_name", ], label=T("Name"), ), S3OptionsFilter("organisation_id", widget="multiselect", filter=True, header="", hidden=True, ), S3LocationFilter("location_id", label = T("Location"), widget="multiselect", levels=["L1", "L2", "L3", "L4"], hidden=True, ), S3OptionsFilter("site_id", widget="multiselect", hidden=True, ), S3OptionsFilter("training.course_id", label = T("Training"), widget="multiselect", hidden=True, ), S3OptionsFilter("group_membership.group_id", label = T("Team"), widget="multiselect", hidden=True, ), ] s3db.configure("hrm_human_resource", list_fields=list_fields, filter_widgets=filter_widgets, ) return result