def job_title(): """ Job Titles Controller """ table = s3db.hrm_job_title s3.crud_strings["hrm_job_title"] = Storage( label_create=T("Add Position"), title_display=T("Position Details"), title_list=T("Positions"), title_update=T("Edit Position"), label_list_button=T("List Positions"), label_delete_button=T("Remove Position"), msg_record_created=T("Position added"), msg_record_modified=T("Position updated"), msg_record_deleted=T("Position removed"), msg_list_empty=T("No Positions currently registered"), ) def prep(r): # Default / Hide type f = table.type f.default = 4 # Deployment f.readable = f.writable = False # Positions are never org-specific f = table.organisation_id f.readable = f.writable = False if r.representation == "xls": # Export format should match Import format current.messages["NONE"] = "" #f.represent = \ # s3db.org_OrganisationRepresent(acronym = False, # parent = False) #f.label = None table.comments.label = None table.comments.represent = lambda v: v or "" return True s3.prep = prep s3.filter = FS("type").belongs((4, )) if not auth.s3_has_role("ADMIN"): s3.filter &= auth.filter_by_root_org(table) return s3_rest_controller("hrm")
def template(): """ RESTful CRUD controller """ from s3 import FS s3.filter = FS("master") == "dc_response" def prep(r): if r.record and r.component_name == "question": # If the template has responses then we should make the Questions read-only # @ToDo: Allow Editing unanswered questions? rtable = s3db.dc_response query = (rtable.template_id == r.id) & \ (rtable.deleted == False) if db(query).select(rtable.id, limitby=(0, 1) ): s3db.configure("dc_question", deletable = False, editable = False, ) # Add JS scripts_append = s3.scripts.append if s3.debug: scripts_append("/%s/static/scripts/tag-it.js" % appname) scripts_append("/%s/static/scripts/S3/s3.dc_question.js" % appname) else: scripts_append("/%s/static/scripts/tag-it.min.js" % appname) scripts_append("/%s/static/scripts/S3/s3.dc_question.min.js" % appname) # Add CSS s3.stylesheets.append("plugins/jquery.tagit.css") # Open in native controller to access Translations tabs s3db.configure("dc_question", linkto = lambda record_id: URL(f="question", args=[record_id, "read"]), linkto_update = lambda record_id: URL(f="question", args=[record_id, "update"]), ) return True s3.prep = prep return s3_rest_controller(rheader = s3db.dc_rheader)
def testTypeOfLookupTableSingleUnresolvable(self): """ Test resolution of __typeof queries, for field in lookup table, with unresolvable value """ db = current.db uids = self.uids resource = current.s3db.resource("test_hierarchy_reference") # Test with field in hierarchy table, with wildcard, no match expr = FS("test_hierarchy_id$name").typeof("Type 1-3*") query = expr.query(resource) table = db.test_hierarchy expected_query = table.id.belongs(set()) self.assertEquivalent(query, expected_query)
def customise_cap_alert_controller(**attr): s3 = current.response.s3 auth = current.auth if not auth.user: # For notifications for group r = current.request if not r.function == "public": if r.get_vars.format == "msg": # This is called by notification # The request from web looks like r.extension s3.filter = (FS("scope") != "Private") else: auth.permission.fail() # Custom prep standard_prep = s3.prep def custom_prep(r): # Call standard prep if callable(standard_prep): result = standard_prep(r) else: result = True if r.representation == "msg": # Notification table = r.table table.scope.represent = None table.status.represent = None table.msg_type.represent = None itable = current.s3db.cap_info itable.severity.represent = None itable.urgency.represent = None itable.certainty.represent = None return result s3.prep = custom_prep return attr
def group(): """ RESTful CRUD controller """ from s3 import FS s3.filter = (FS("group.system") == False) # do not show system groups # Modify list_fields for the component tab table = s3db.pr_group_membership s3db.configure( "pr_group_membership", list_fields=["id", "person_id", "group_head", "comments"], ) from s3db.pr import pr_rheader rheader = lambda r: \ pr_rheader(r, tabs = [(T("Group Details"), None), (T("Address"), "address"), (T("Contact Data"), "contact"), (T("Members"), "group_membership") ]) return s3_rest_controller(rheader=rheader)
def testFilteringLeafOnly(self): """ Test filtering of the tree with leafonly=True """ uids = self.uids h = S3Hierarchy("test_hierarchy", filter = FS("type") == "D", leafonly = True) # Check nodes nodes = h.nodes expected = ["HIERARCHY2", "HIERARCHY2-1", "HIERARCHY2-1-2"] self.assertEqual(len(nodes), len(expected)) self.assertTrue(all(uids[uid] in nodes for uid in expected)) # Check consistency for node in nodes.values(): for child_id in node["s"]: self.assertTrue(child_id in nodes) parent_id = node["p"] if parent_id: self.assertTrue(parent_id in nodes)
def __call__(self): """ Main entry point, configuration """ logged_in = current.auth.s3_logged_in() if logged_in: fn = "alert" else: fn = "public" T = current.T s3db = current.s3db request = current.request output = {} # Map ftable = s3db.gis_layer_feature query = (ftable.controller == "cap") & \ (ftable.function == fn) layer = current.db(query).select(ftable.layer_id, limitby=(0, 1) ).first() try: layer_id = layer.layer_id except: from s3 import s3_debug s3_debug("Cannot find Layer for Map") layer_id = None feature_resources = [{"name" : T("Alerts"), "id" : "search_results", "layer_id" : layer_id, "tablename" : "cap_alert", "url" : URL(c="cap", f=fn, extension="geojson"), # We activate in callback after ensuring URL is updated for current filter status "active" : False, }] _map = current.gis.show_map(callback='''S3.search.s3map()''', catalogue_layers=True, collapsed=True, feature_resources=feature_resources, save=False, search=True, toolbar=True, ) output["_map"] = _map # Filterable List of Alerts # - most recent first resource = s3db.resource("cap_alert") # Don't show Templates resource.add_filter(FS("is_template") == False) if not logged_in: # Only show Public Alerts resource.add_filter(FS("scope") == "Public") # Only show Alerts which haven't expired resource.add_filter(FS("info.expires") >= request.utcnow) list_id = "cap_alert_datalist" list_fields = ["msg_type", "info.headline", "area.name", #"info.description", "info.sender_name", "info.priority", "status", "scope", "info.event_type_id", "info.severity", "info.certainty", "info.urgency", "sent", ] # Order with most recent Alert first orderby = "cap_info.expires desc" datalist, numrows, ids = resource.datalist(fields = list_fields, #start = None, limit = None, list_id = list_id, orderby = orderby, layout = s3db.cap_alert_list_layout ) ajax_url = URL(c="cap", f=fn, args="datalist.dl", vars={"list_id": list_id}) output[list_id] = datalist.html(ajaxurl = ajax_url, pagesize = None, ) # @ToDo: Options are currently built from the full-set rather than the filtered set filter_widgets = [#S3LocationFilter("location.location_id", # label=T("Location"), # levels=("L0",), # widget="multiselect", # ), S3OptionsFilter("info.priority", #label=T("Priority"), ), S3OptionsFilter("info.event_type_id", #label=T("Event Type"), ), S3OptionsFilter("scope", #label=T("Scope"), ), S3DateFilter("info.expires", label = "", #label=T("Expiry Date"), hide_time=True, ), ] filter_form = S3FilterForm(filter_widgets, ajax=True, submit=True, url=ajax_url, ) output["alert_filter_form"] = filter_form.html(resource, request.get_vars, list_id) # Filterable News Feed # - most recent first resource = s3db.resource("cms_post") # Only show News posts (differentiate from e.g. online user guide) resource.add_filter(FS("series_id$name") == "News") list_id = "cms_post_datalist" list_fields = [#"series_id", "location_id", "date", "body", #"created_by", #"created_by$organisation_id", #"document.file", ] # Order with most recent Post first orderby = "cms_post.date desc" datalist, numrows, ids = resource.datalist(fields = list_fields, #start = None, limit = 5, list_id = list_id, orderby = orderby, # @ToDo: Custom layout with more button to expand content block layout = s3db.cms_post_list_layout ) ajax_url = URL(c="cms", f="post", args="datalist.dl", vars={"list_id": list_id}) output[list_id] = datalist.html(ajaxurl = ajax_url, pagesize = 5 ) # Truncate body #from s3 import s3_trunk8 #s3_trunk8(lines=8) #filter_widgets = [#S3LocationFilter("location_id", # # label="", # # levels=("L0",), # # widget="multiselect", # # ), # # @ToDo: Source (Series? Tag?) # #S3OptionsFilter(), # ] #filter_form = S3FilterForm(filter_widgets, # ajax=True, # submit=True, # url=ajax_url, # ) #output["news_filter_form"] = filter_form.html(resource, request.get_vars, list_id) # Title and view output["title"] = current.deployment_settings.get_system_name() self._view(THEME, "index.html") s3 = current.response.s3 # Custom CSS s3.stylesheets.append("../themes/SAMBRO/style.css") # Custom JS s3.scripts.append("/%s/static/themes/SAMBRO/js/homepage.js" % request.application) return output
def customise_req_site_needs_resource(r, tablename): if r.tablename == "req_site_needs": table = r.table field = table.site_id field.label = current.T("Facility") field.readable = field.writable = True # Allow only facilities which do not have a req_site_needs # yet (single component), and filter out obsolete facilities from s3 import IS_ONE_OF, FS dbset = current.db(table.id == None) left = table.on(table.site_id == current.s3db.org_site.id) field.requires = IS_ONE_OF( dbset, "org_site.site_id", field.represent, left=left, not_filterby="obsolete", not_filter_opts=(True, ), orderby="org_site.name", sort=True, ) if not r.record: query = FS("site_id$obsolete") != True r.resource.add_filter(query) # Allow adding of facilities in popup from s3layouts import S3PopupLink field.comment = S3PopupLink( c="org", f="facility", vars={ "child": "site_id", "parent": "site_needs", }, title=T("Add New Facility"), ) # Filters from s3 import S3LocationFilter, S3TextFilter filter_widgets = [ S3TextFilter( [ "site_id$name", "vol_details", "goods_details", ], label=T("Search"), ), S3LocationFilter("site_id$location_id", ), ] # List fields list_fields = [ (T("Facility"), "site_id$name"), "site_id$location_id", ("%s?" % T("Volunteers"), "vol"), (T("Help Wanted"), "vol_details"), ("%s?" % T("Donations"), "goods"), (T("Donations Needed"), "goods_details"), "modified_on", ] current.s3db.configure( "req_site_needs", filter_widgets=filter_widgets, list_fields=list_fields, )
def ns_only(tablename, fieldname = "organisation_id", required = True, branches = True, updateable = True, limit_filter_opts = True, hierarchy = True, ): """ Function to configure an organisation_id field to be restricted to just NS/Branch @param required: Field is mandatory @param branches: Include Branches @param updateable: Limit to Orgs which the user can update @param limit_filter_opts: Also limit the Filter options @param hierarchy: Use the hierarchy widget (unsuitable for use in Inline Components) NB If limit_filter_opts=True, apply in customise_xx_controller inside prep, after standard_prep is run """ # Lookup organisation_type_id for Red Cross db = current.db s3db = current.s3db ttable = s3db.org_organisation_type try: type_id = db(ttable.name == "Red Cross / Red Crescent").select(ttable.id, limitby=(0, 1), cache = s3db.cache, ).first().id except: # No IFRC prepop done - skip (e.g. testing impacts of CSS changes in this theme) return # Load standard model f = s3db[tablename][fieldname] if limit_filter_opts: # Find the relevant filter widget & limit it's options filter_widgets = s3db.get_config(tablename, "filter_widgets") filter_widget = None if filter_widgets: from s3 import FS, S3HierarchyFilter for w in filter_widgets: if isinstance(w, S3HierarchyFilter) and \ w.field == "organisation_id": filter_widget = w break if filter_widget is not None: selector = FS("organisation_organisation_type.organisation_type_id") filter_widget.opts["filter"] = (selector == type_id) # Label if branches: f.label = T("National Society / Branch") #f.label = T("Branch") else: f.label = T("National Society") # Requires # Filter by type ltable = db.org_organisation_organisation_type rows = db(ltable.organisation_type_id == type_id).select(ltable.organisation_id) filter_opts = [row.organisation_id for row in rows] auth = current.auth s3_has_role = auth.s3_has_role Admin = s3_has_role("ADMIN") if branches: if Admin: parent = True else: # @ToDo: Set the represent according to whether the user can see resources of just a single NS or multiple # @ToDo: Consider porting this into core user = auth.user if user: realms = user.realms #delegations = user.delegations if realms: parent = True else: parent = False else: parent = True else: # Keep the represent function as simple as possible parent = False # Exclude branches btable = s3db.org_organisation_branch rows = db((btable.deleted != True) & (btable.branch_id.belongs(filter_opts))).select(btable.branch_id) filter_opts = list(set(filter_opts) - set(row.branch_id for row in rows)) organisation_represent = s3db.org_OrganisationRepresent represent = organisation_represent(parent=parent) f.represent = represent from s3 import IS_ONE_OF requires = IS_ONE_OF(db, "org_organisation.id", represent, filterby = "id", filter_opts = filter_opts, updateable = updateable, orderby = "org_organisation.name", sort = True) if not required: from gluon import IS_EMPTY_OR requires = IS_EMPTY_OR(requires) f.requires = requires if parent and hierarchy: # Use hierarchy-widget from s3 import FS, S3HierarchyWidget # No need for parent in represent (it's a hierarchy view) node_represent = organisation_represent(parent=False) # Filter by type # (no need to exclude branches - we wouldn't be here if we didn't use branches) selector = FS("organisation_organisation_type.organisation_type_id") f.widget = S3HierarchyWidget(lookup="org_organisation", filter=(selector == type_id), represent=node_represent, multiple=False, leafonly=False, ) else: # Dropdown not Autocomplete f.widget = None # Comment if (Admin or s3_has_role("ORG_ADMIN")): # Need to do import after setting Theme from s3layouts import S3PopupLink from s3 import S3ScriptItem add_link = S3PopupLink(c = "org", f = "organisation", vars = {"organisation_type.name":"Red Cross / Red Crescent"}, label = T("Create National Society"), title = T("National Society"), ) comment = f.comment if not comment or isinstance(comment, S3PopupLink): f.comment = add_link elif isinstance(comment[1], S3ScriptItem): # Don't overwrite scripts f.comment[0] = add_link else: f.comment = add_link else: # Not allowed to add NS/Branch f.comment = ""
def prep(r): SURPLUS_MEALS = "SURPLUS-MEALS" T = current.T db = current.db s3db = current.s3db resource = r.resource # Set default SURPLUS_MEALS event type ttable = s3db.dvr_case_event_type query = (ttable.code == SURPLUS_MEALS) & \ (ttable.deleted != True) event_type = db(query).select( ttable.id, limitby=(0, 1), ).first() if not event_type: r.error(400, "No event type with code %s defined" % SURPLUS_MEALS) event_type_id = event_type.id # Filter to SURPLUS_MEALS events without person_id query = (FS("type_id") == event_type_id) & \ (FS("person_id") == None) resource.add_filter(query) # Configure fields table = resource.table field = table.person_id field.default = None field.readable = field.writable = False field = table.type_id field.default = event_type_id field.readable = field.writable = False field = table.date field.readable = field.writable = True field = table.quantity field.default = 0 # Override IS_EMPTY_OR field.requires = IS_INT_IN_RANGE(0, None) field.readable = field.writable = True field = table.modified_by field.readable = True registered_by = (T("Registered by"), "modified_by") if r.interactive: # Custom CRUD form crud_form = S3SQLCustomForm( "date", "quantity", registered_by, "comments", ) # Custom filter widgets filter_widgets = [ S3TextFilter( [ "created_by$email", "comments", ], label=T("Search"), ), S3DateFilter("date"), ] resource.configure( crud_form=crud_form, filter_widgets=filter_widgets, ) # Turn off filter manager current.deployment_settings.search.filter_manager = False # Custom list fields list_fields = [ "date", "quantity", registered_by, "comments", ] # URL of the list view list_url = URL(args=[controller], vars={}) s3.datatable_ajax_source = list_url resource.configure( insertable=True, list_fields=list_fields, # Fix redirects: create_next=list_url, update_next=list_url, delete_next=list_url, ) # Custom CRUD strings T = current.T s3.crud_strings["dvr_case_event"] = Storage( label_create=T("Register Surplus Meals Quantity"), title_display=T("Surplus Meals Quantity"), title_list=T("Surplus Meals"), title_update=T("Edit Surplus Meals Quantity"), label_list_button=T("List Surplus Meals"), label_delete_button=T("Delete Entry"), msg_record_created=T("Entry added"), msg_record_modified=T("Entry updated"), msg_record_deleted=T("Entry deleted"), msg_list_empty=T("No Surplus Meals currently registered"), ) return True
def __call__(self): output = {} T = current.T request = current.request s3 = current.response.s3 # Check logged in and permissions auth = current.auth roles = current.session.s3.roles system_roles = auth.get_system_roles() AUTHENTICATED = system_roles.AUTHENTICATED # Login/Registration forms self_registration = current.deployment_settings.get_security_self_registration( ) registered = False login_form = None login_div = None register_form = None register_div = None if AUTHENTICATED not in roles: # This user isn't yet logged-in if request.cookies.has_key("registered"): # This browser has logged-in before registered = True if self_registration is True: # Provide a Registration box on front page register_form = auth.register() register_div = DIV(H3(T("Register")), P(XML(T("If you would like to help, then please %(sign_up_now)s") % \ dict(sign_up_now=B(T("sign-up now")))))) if request.env.request_method == "POST": post_script = \ '''$('#register_form').removeClass('hide') $('#login_form').addClass('hide')''' else: post_script = "" register_script = \ '''$('#register-btn').attr('href','#register') $('#login-btn').attr('href','#login') %s $('#register-btn').click(function(){ $('#register_form').removeClass('hide') $('#login_form').addClass('hide') }) $('#login-btn').click(function(){ $('#register_form').addClass('hide') $('#login_form').removeClass('hide') })''' % post_script s3.jquery_ready.append(register_script) # Provide a login box on front page auth.messages.submit_button = T("Login") login_form = auth.login(inline=True) login_div = DIV(H3(T("Login")), P(XML(T("Registered users can %(login)s to access the system") % \ dict(login=B(T("login")))))) output["self_registration"] = self_registration output["registered"] = registered output["login_div"] = login_div output["login_form"] = login_form output["register_div"] = register_div output["register_form"] = register_form # Latest 4 Events and Requests s3db = current.s3db layout = s3db.cms_post_list_layout list_id = "latest_events" limit = 4 list_fields = [ "series_id", "location_id", "date", "body", "created_by", "created_by$organisation_id", "document.file", "event_post.event_id", ] resource = s3db.resource("cms_post") resource.add_filter(FS("series_id$name") == "Event") # Only show Future Events resource.add_filter(resource.table.date >= request.now) # Order with next Event first orderby = "date" output["latest_events"] = latest_records(resource, layout, list_id, limit, list_fields, orderby) list_id = "latest_reqs" resource = s3db.resource("req_req") s3db.req_customise_req_fields() list_fields = s3db.get_config("req_req", "list_fields") layout = s3db.req_req_list_layout resource.add_filter(FS("cancel") != True) # Order with most recent Request first orderby = "date desc" output["latest_reqs"] = latest_records(resource, layout, list_id, limit, list_fields, orderby) # Site Activity Log resource = s3db.resource("s3_audit") resource.add_filter(FS("~.method") != "delete") orderby = "s3_audit.timestmp desc" list_fields = [ "id", "method", "user_id", "tablename", "record_id", ] #current.deployment_settings.ui.customise_s3_audit() db = current.db db.s3_audit.user_id.represent = s3_auth_user_represent_name list_id = "log" datalist, numrows, ids = resource.datalist(fields=list_fields, start=None, limit=4, list_id=list_id, orderby=orderby, layout=s3.render_log) # Placeholder filter_form = DIV(_class="filter_form") if numrows == 0: # Empty table or just no match? from s3 import S3CRUD table = resource.table if "deleted" in table: available_records = db(table.deleted != True) else: available_records = 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 ajaxurl = URL(c="default", f="audit", args="datalist_f.dl") popup_url = URL(c="default", f="audit", args="datalist.popup") dl = datalist.html( ajaxurl=ajaxurl, pagesize=4, popup_url=popup_url, popup_title=T("Updates"), ) data = dl if auth.s3_logged_in() and auth.user.org_group_id: # Add a Filter filter_widgets = [ S3OptionsFilter( "user_id$org_group_id", label="", # Can't just use "" as this is then omitted from rendering options={ "*": T("All"), org_group_id: T("My Community"), }, multiple=False, ), ] filter_submit_url = URL(c="default", f="index") filter_ajax_url = URL(c="default", f="audit", args=["filter.options"]) filter_form = S3FilterForm(filter_widgets, filter_manager=False, formstyle=filter_formstyle, clear=False, submit=True, ajax=True, url=filter_submit_url, ajaxurl=filter_ajax_url, _class="filter-form", _id="%s-filter-form" % list_id) filter_form = filter_form.html( resource, request.get_vars, target=list_id, ) output["updates"] = data output["filter_form"] = filter_form # Add JavaScript appname = request.application debug = s3.debug scripts_append = s3.scripts.append if debug: # Infinite Scroll doesn't make sense here, but currently required by dataLists.js scripts_append("/%s/static/scripts/jquery.infinitescroll.js" % appname) scripts_append("/%s/static/scripts/jquery.viewport.js" % appname) scripts_append("/%s/static/scripts/S3/s3.dataLists.js" % appname) else: scripts_append("/%s/static/scripts/S3/s3.dataLists.min.js" % appname) self._view(THEME, "index.html") return output
def prep(r): # Call standard prep result = standard_prep(r) if callable(standard_prep) else True s3db = current.s3db auth = current.auth #settings = current.deployment_settings # Add invite-method for ORG_GROUP_ADMIN role from .helpers import rlpptm_InviteUserOrg s3db.set_method( "org", "organisation", method="invite", action=rlpptm_InviteUserOrg, ) resource = r.resource get_vars = r.get_vars mine = get_vars.get("mine") if mine == "1": # Filter to managed orgs managed_orgs = auth.get_managed_orgs() if managed_orgs is True: query = None elif managed_orgs is None: query = FS("id") == None else: query = FS("pe_id").belongs(managed_orgs) if query: resource.add_filter(query) else: # Filter by org_group_membership org_group_id = get_vars.get("g") if org_group_id: if isinstance(org_group_id, list): query = FS("group.id").belongs(org_group_id) else: query = FS("group.id") == org_group_id resource.add_filter(query) if not r.component: if r.interactive: from s3 import S3SQLCustomForm, \ S3SQLInlineComponent, \ S3SQLInlineLink crud_fields = [ "name", "acronym", # TODO Activate after correct type prepop #S3SQLInlineLink( # "organisation_type", # field = "organisation_type_id", # search = False, # label = T("Type"), # multiple = settings.get_org_organisation_types_multiple(), # widget = "multiselect", # ), #"country", S3SQLInlineComponent( "contact", fields=[("", "value")], filterby={ "field": "contact_method", "options": "EMAIL", }, label=T("Email"), multiple=False, name="email", ), "phone", #"website", #"year", "logo", "comments", ] if auth.s3_has_role("ORG_GROUP_ADMIN"): crud_fields.insert( 0, S3SQLInlineLink( "group", field="group_id", label=T("Organisation Group"), multiple=False, )) r.resource.configure( crud_form=S3SQLCustomForm(*crud_fields), ) return result
def index(): """ Module's Home Page """ # Page title module_name = settings.modules[c].get("name_nice") response.title = module_name output = {"module_name": module_name} # Extract summary information from s3 import FS define_resource = s3db.resource # => Number of households total_households = define_resource("po_household").count() # => Number of referrals total_referrals = define_resource("po_organisation_household").count() # => Number of agencies involved # This version shows all agencies for all Branches (only master query is filtered) #filter = (FS("organisation_id") == s3db.po_organisation_household.organisation_id) #total_agencies = define_resource("po_referral_organisation", # filter=filter).count(distinct=True) total_agencies = define_resource("po_organisation_household").select(fields=["organisation_id"]) total_agencies = len({o["po_organisation_household.organisation_id"] for o in total_agencies.rows}) # => Number of follow ups (broken down into pending/completed) # Option 1 # Minimum Time: 0.042s # Maximum Time: 0.103s # Mean Time: 0.047s # Option 2 # Minimum Time: 0.002s # Maximum Time: 0.03s # Mean Time: 0.002s #rows = define_resource("po_household_followup").select(fields=["completed"], # as_rows=True) #follow_ups_pending, follow_ups_completed = 0, 0 #for row in rows: # if row.completed: # follow_ups_completed += 1 # else: # follow_ups_pending += 1 filter = (FS("completed") == False) follow_ups_pending = define_resource("po_household_followup", filter=filter).count() filter = (FS("completed") == True) follow_ups_completed = define_resource("po_household_followup", filter=filter).count() total_follow_ups = follow_ups_pending + follow_ups_completed # => Number of attempted visits # @ToDo: Support sum() in S3Resource areas = define_resource("po_area").select(fields=["attempted_visits"], as_rows=True) total_attempted_visits = 0 for row in areas: attempted_visits = row.attempted_visits if attempted_visits: total_attempted_visits += attempted_visits # Summary output["summary"] = DIV(DIV(LABEL("%s: " % T("Total Households Visited")), SPAN(total_households), _class="po-summary-info", ), DIV(LABEL("%s: " % T("Attempted Visits")), SPAN(total_attempted_visits), _class="po-summary-info", ), DIV(LABEL("%s: " % T("Follow-ups")), SPAN(total_follow_ups), SPAN("(%s %s, %s %s)" % (follow_ups_completed, T("completed"), follow_ups_pending, T("pending"), ) ), _class="po-summary-info", ), DIV(LABEL("%s: " % T("Total Referrals Made")), SPAN(total_referrals), _class="po-summary-info", ), DIV(LABEL("%s: " % T("Agencies Involved")), SPAN(total_agencies), _class="po-summary-info", ), _class="po-summary", ) # Map of areas covered ftable = s3db.gis_layer_feature query = (ftable.controller == "po") & \ (ftable.function == "area") layer = db(query).select(ftable.layer_id, limitby=(0, 1)).first() if layer: # We can take advantage of per-feature styling layer_id = layer.layer_id areas = {"name": T("Areas Covered"), "id": "areas", "active": True, "layer_id": layer_id, } else: # All features will be styled the same areas = {"name": T("Areas Covered"), "id": "areas", "active": True, "tablename": "po_area", "url": "area.geojson", "style": '{"fill":"2288CC"}', "opacity": 0.5, } map_wrapper = gis.show_map(feature_resources=(areas,), #catalogue_layers = True, collapsed = True, ) #map_wrapper["_style"] = "width:100%" output["map"] = map_wrapper return output
def person(): """ Missing Persons Registry (Match Finder) """ table = s3db.pr_person s3.crud_strings["pr_person"].update( title_display=T("Missing Person Details"), title_list=T("Missing Persons"), label_list_button=T("List Missing Persons"), msg_list_empty=T("No Persons found"), msg_no_match=T("No Persons currently reported missing")) s3db.configure( "pr_group_membership", list_fields=["id", "group_id", "group_head", "comments"], ) s3db.configure( "pr_person", deletable=False, editable=False, listadd=False, list_fields=[ "id", "first_name", "middle_name", "last_name", "picture", "gender", "age_group" ], ) def prep(r): if not r.id and not r.method and not r.component: body_id = r.get_vars.get("match", None) body = db(db.dvi_body.id == body_id).select(db.dvi_body.pe_label, limitby=(0, 1)).first() label = body and body.pe_label or "#%s" % body_id if body_id: query = dvi_match_query(body_id) r.resource.add_filter(query) s3.crud_strings["pr_person"].update( #subtitle_list = T("Candidate Matches for Body %s" % label), msg_no_match=T("No matching records found")) return True s3.prep = prep # @ToDo: Add to crud_fields field = s3db.pr_person_details.missing.default = True table.age_group.readable = True table.age_group.writable = True # Show only missing persons in list views if len(request.args) == 0: from s3 import FS s3.filter = (FS("person_details.missing") == True) mpr_tabs = [ (T("Missing Report"), "missing_report"), (T("Person Details"), None), (T("Physical Description"), "physical_description"), (T("Images"), "image"), (T("Identity"), "identity"), (T("Address"), "address"), (T("Contact Data"), "contact"), (T("Journal"), "note"), ] rheader = lambda r: s3db.pr_rheader(r, tabs=mpr_tabs) return s3_rest_controller( "pr", "person", main="first_name", extra="last_name", rheader=rheader, )
def __call__(self): response = current.response s3 = response.s3 s3db = current.s3db output = {} self._view(THEME, "index.html") # Map # Enable Layers by default callback = '''S3.gis.show_map() var layer,layers=S3.gis.maps.default_map.layers for(var i=0,len=layers.length;i<len;i++){ layer=layers[i] layer_name=layer.name if((layer_name=='Alerts')||(layer_name=='Incidents')||(layer_name=='Tasks')){layer.setVisibility(true)}}''' gis = current.gis #config = gis.get_config() #config.zoom = 8 map = gis.show_map(width=600, height=600, callback=callback, catalogue_layers=True, collapsed=True, save=False, ) output["map"] = map # Alerts Data List resource = s3db.resource("cms_post") # Only show Alerts #resource.add_filter(FS("series_id$name").belongs(["Alert"])) #resource.add_filter(FS("post.series_id") != None) # Only show Open Alerts resource.add_filter(FS("expired") == False) # Only show Alerts which are linked to Open Incidents or not linked to any Incident resource.add_filter((FS("incident.closed") == False) | (FS("incident.id") == None)) list_id = "cms_post_datalist" list_fields = [#"series_id", "location_id", "date", "body", "created_by", "created_by$organisation_id", "document.file", "event_post.event_id", "event_post.incident_id", ] # Order with most recent Alert first orderby = "cms_post.date desc" datalist, numrows, ids = resource.datalist(fields = list_fields, #start = None, limit = 5, list_id = list_id, orderby = orderby, layout = s3db.cms_post_list_layout ) ajax_url = URL(c="cms", f="post", args="datalist.dl", vars={"list_id": list_id}) output[list_id] = datalist.html(ajaxurl = ajax_url, pagesize = 5 ) # Incidents Data List resource = s3db.resource("event_incident") # Only show Open Incidents resource.add_filter(FS("closed") == False) list_id = "event_incident_datalist" list_fields = ["name", "location_id", "date", "modified_by", "organisation_id", "comments", ] # Order with most recent Incident first orderby = "event_incident.date desc" datalist, numrows, ids = resource.datalist(fields = list_fields, #start = None, limit = 5, list_id = list_id, orderby = orderby, layout = s3db.event_incident_list_layout ) ajax_url = URL(c="event", f="incident", args="datalist.dl", vars={"list_id": list_id}) output[list_id] = datalist.html(ajaxurl = ajax_url, pagesize = 5 ) # Tasks Data List resource = s3db.resource("project_task") # Only show Active Tasks active_statuses = s3db.project_task_active_statuses resource.add_filter(FS("status").belongs(active_statuses)) # Only show Tasks which are linked to Open Incidents or not linked to any Incident resource.add_filter((FS("incident.incident_id$closed") == False) | (FS("incident.id") == None)) list_id = "project_task_datalist" list_fields = ["name", "description", "comments", "location_id", "priority", "status", "date_due", "pe_id", "task_project.project_id", #"organisation_id$logo", "modified_by", "source_url" ] # Order with most urgent Task first orderby = "project_task.date_due asc" datalist, numrows, ids = resource.datalist(fields = list_fields, #start = None, limit = 5, list_id = list_id, orderby = orderby, layout = s3db.project_task_list_layout ) ajax_url = URL(c="project", f="task", args="datalist.dl", vars={"list_id": list_id}) output[list_id] = datalist.html(ajaxurl = ajax_url, pagesize = 5 ) # MCOP RSS News Feed #s3.external_stylesheets.append("//www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.css") s3.scripts.append("//www.google.com/jsapi?key=notsupplied-wizard") s3.scripts.append("//www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.js") # feedCycleTime: milliseconds before feed is reloaded (5 minutes) s3.js_global.append( """ function LoadDynamicFeedControl(){ var feeds=[{title:'News', url:'http://psmcop.org/?feed=rss2'}] var options={ feedCycleTime:300000, numResults:5, stacked:true, horizontal:false, } new GFdynamicFeedControl(feeds,'feed-control',options); } google.load('feeds','1'); google.setOnLoadCallback(LoadDynamicFeedControl); """ ) # Data Buttons # Description of available data from s3db.cms import S3CMS resource_content = S3CMS.resource_content for item in response.menu: item["cms"] = resource_content(module = item["c"], resource = item["f"]) return output
def __call__(self): T = current.T db = current.db s3db = current.s3db auth = current.auth s3 = current.response.s3 #crud_strings = s3.crud_strings # Internal & External Users see different pages internal = auth.s3_logged_in() output = {"internal": internal, } # Map ltable = s3db.gis_layer_feature layers = db(ltable.name.belongs(("Offices", "Response Areas"))).select(ltable.layer_id, ltable.name ) offices = None response_areas = None for layer in layers: if layer.name == "Offices": offices = layer.layer_id elif layer.name == "Response Areas": response_areas = layer.layer_id feature_resources = [{"name": T("SCP Offices"), "active": True, "layer_id": offices, }, {"name": T("SCP Response Areas"), "active": True, "layer_id": response_areas, }, ] output["map"] = current.gis.show_map(feature_resources = feature_resources, ) # DataTables s3.no_formats = True # Open Events tablename = "event_event" resource = s3db.resource(tablename) resource.add_filter(FS("~.closed") == False) list_fields = ["name", "event_location.location_id", ] if internal: list_fields.insert(1, (T("Category"), "event_tag.value")) start = None limit = 5 orderby = "event_event.start_date" # Get the data table self._datatable(output, resource, list_fields, start, limit, orderby, ) if internal: # Pending Activities tablename = "project_activity" resource = s3db.resource(tablename) resource.add_filter(FS("~.date") > current.request.utcnow) resource.add_filter(FS("organisation.name") == SAVE) list_fields = [#"date", (T("Response"), "event.event_id"), "name", "location_id", "status_id", ] start = None limit = 5 orderby = "project_activity.date" # Get the data table self._datatable(output, resource, list_fields, start, limit, orderby, ) # Allow editing of page content from browser using CMS module system_roles = auth.get_system_roles() ADMIN = system_roles.ADMIN in current.session.s3.roles table = s3db.cms_post if internal: title = "Announcements" else: title = "Contacts" item = db(table.title == title).select(table.body, table.id, limitby=(0, 1)).first() if item: if ADMIN: item = DIV(XML(item.body), BR(), A(T("Edit"), _href=URL(c="cms", f="post", args=[item.id, "update"]), _class="action-btn")) else: item = DIV(XML(item.body)) elif ADMIN: if s3.crud.formstyle == "bootstrap": _class = "btn" else: _class = "action-btn" item = A(T("Edit"), _href=URL(c="cms", f="post", args="create", vars={"module": module, "resource": resource }), _class="%s cms-edit" % _class) else: item = "" output["cms"] = item self._view(THEME, "index.html") return output
def __call__(self): """ The userstats controller """ # Require ORG_GROUP_ADMIN auth = current.auth if not auth.s3_has_role("ORG_GROUP_ADMIN"): auth.permission.fail() from s3 import S3CRUD, s3_get_extension, s3_request request = current.request args = request.args # Create an S3Request r = s3_request( "org", "organisation", c="default", f="index/%s" % args[0], args=args[1:], extension=s3_get_extension(request), ) # Filter to root organisations resource = r.resource resource.add_filter(FS("id").belongs(self.root_orgs)) # Configure field methods from gluon import Field table = resource.table table.total_accounts = Field.Method("total_accounts", self.total_accounts) table.active_accounts = Field.Method("active_accounts", self.active_accounts) table.disabled_accounts = Field.Method("disabled_accounts", self.disabled_accounts) table.active30 = Field.Method("active30", self.active30) # Labels for field methods T = current.T TOTAL = T("Total User Accounts") ACTIVE = T("Active") DISABLED = T("Inactive") ACTIVE30 = T("Logged-in Last 30 Days") # Configure list_fields list_fields = ( "id", "name", (TOTAL, "total_accounts"), (ACTIVE, "active_accounts"), (DISABLED, "disabled_accounts"), (ACTIVE30, "active30"), ) # Configure form from s3 import S3SQLCustomForm, S3SQLVirtualField crud_form = S3SQLCustomForm( "name", S3SQLVirtualField( "total_accounts", label=TOTAL, ), S3SQLVirtualField( "active_accounts", label=ACTIVE, ), S3SQLVirtualField( "disabled_accounts", label=DISABLED, ), S3SQLVirtualField( "active30", label=ACTIVE30, ), ) # Configure read-only resource.configure( insertable=False, editable=False, deletable=False, crud_form=crud_form, filter_widgets=None, list_fields=list_fields, ) output = r(rheader=self.rheader) if isinstance(output, dict): output["title"] = T("User Statistics") # URL to open the resource open_url = resource.crud._linkto(r, update=False)("[id]") # Add action button for open action_buttons = S3CRUD.action_buttons action_buttons( r, deletable=False, copyable=False, editable=False, read_url=open_url, ) return output
def __call__(self): response = current.response output = {} s3 = response.s3 # Slick slider # Only 1 image currently, so enable if/when we need this if s3.debug: s3.scripts.append("/%s/static/scripts/slick.js" % current.request.application) else: s3.scripts.append("/%s/static/scripts/slick.min.js" % current.request.application) script = ''' $(document).ready(function(){ $('#title-image').slick({ autoplay:true, autoplaySpeed:5000, speed:1000, fade:true, cssEase:'linear' }); });''' s3.jquery_ready.append(script) # Latest 4 Requests s3db = current.s3db list_id = "latest_reqs" layout = s3db.req_req_list_layout limit = 4 resource = s3db.resource("req_req") s3db.req_customise_req_fields() list_fields = s3db.get_config("req_req", "list_fields") from s3 import FS resource.add_filter(FS("cancel") != True) # Order with most recent first orderby = "date desc" output["latest_reqs"] = latest_records(resource, layout, list_id, limit, list_fields, orderby) # Latest 4 Offers list_id = "latest_offers" layout = s3db.req_commit_list_layout #limit = 4 resource = s3db.resource("req_commit") s3db.req_customise_commit_fields() list_fields = s3db.get_config("req_commit", "list_fields") resource.add_filter(FS("cancel") != True) # Order with most recent first #orderby = "date desc" output["latest_offers"] = latest_records(resource, layout, list_id, limit, list_fields, orderby) # What We Do #table = s3db.cms_post #ltable = s3db.cms_post_module #query = (ltable.module == "default") & \ # (ltable.resource == "index") & \ # (ltable.post_id == table.id) & \ # (table.deleted != True) #item = current.db(query).select(table.id, # table.body, # limitby=(0, 1)).first() #if item: # what_we_do = DIV(XML(item.body)) # if current.auth.s3_has_role("ADMIN"): # if s3.crud.formstyle == "bootstrap": # _class = "btn" # else: # _class = "action-btn" # what_we_do.append(A(current.T("Edit"), # _href=URL(c="cms", f="post", # args=[item.id, "update"], # vars={"module": "default", # "resource": "index", # }), # _class="%s cms-edit" % _class)) #else: # what_we_do = DIV() # if current.auth.s3_has_role("ADMIN"): # if s3.crud.formstyle == "bootstrap": # _class = "btn" # else: # _class = "action-btn" # what_we_do.append(A(current.T("Edit"), # _href=URL(c="cms", f="post", # args=["create"], # vars={"module": "default", # "resource": "index", # }), # _class="%s cms-edit" % _class)) #output["what_we_do"] = what_we_do s3.stylesheets.append("../themes/MAVC/homepage.css") self._view(THEME, "index.html") return output
def get_offer_filters(person_id=None): """ Get filters for br_assistance_offer matching a person's current needs @param person_id: the person ID @returns: S3ResourceQuery to apply to an br_assistance_offer resource, or None, if matching is not possible # TODO move client-side """ db = current.db auth = current.auth s3db = current.s3db if not person_id: person_id = auth.s3_logged_in_person() if not person_id: return None # Lookup all current needs of the person atable = s3db.br_case_activity ltable = s3db.gis_location ptable = s3db.pr_person stable = s3db.br_case_activity_status today = current.request.utcnow.date() join = [ptable.on(ptable.id == atable.person_id), stable.on((stable.id == atable.status_id) & \ (stable.is_closed == False)), ] left = ltable.on(ltable.id == atable.location_id) query = (atable.person_id == person_id) & \ (atable.need_id != None) & \ (atable.location_id != None) & \ ((atable.date == None) | (atable.date <= today)) & \ ((atable.end_date == None) | (atable.end_date >= today)) & \ (atable.deleted == False) rows = db(query).select( atable.need_id, atable.location_id, ltable.name, #ltable.parent, ltable.level, ltable.path, ptable.pe_id, join=join, left=left, ) gis = current.gis get_neighbours = gis.get_neighbours get_parents = gis.get_parents filters, exclude_provider = None, None for row in rows: # Provider to exclude person = row.pr_person exclude_provider = person.pe_id activity = row.br_case_activity # Match by need query = FS("~.need_id") == activity.need_id # Match by Location # - include exact match if Need is at an Lx # - include all higher level Lx # - include all adjacent lowest-level Lx location_id = activity.location_id location = row.gis_location level = location.level if level: # Lx location (the normal case) location_ids = [location_id] # Include all parent Lx parents = get_parents(location_id, feature=location, ids_only=True) if parents: location_ids += parents # Include all adjacent Lx of the same level neighbours = get_neighbours(location_id) if neighbours: location_ids += neighbours else: # Specific address location_ids = [] # Include all parent Lx parents = get_parents(location_id, feature=location, ids_only=True) if parents: location_ids = parents # Include all adjacent Lx of the immediate ancestor Lx neighbours = get_neighbours(parents[0]) if neighbours: location_ids += neighbours # Lookup the immediate ancestor's level q = (ltable.id == parents[0]) & (ltable.deleted == False) row = db(q).select(ltable.level, limitby=(0, 1)).first() if row: level = row.level if location_ids and level and level < "L4": # Include all child Lx of the match locations below level # TODO make this recursive to include grandchildren etc. too q = (ltable.parent.belongs(location_ids)) & \ (ltable.level != None) & \ (ltable.level > level) & \ (ltable.deleted == False) children = db(q).select(ltable.id) location_ids += [c.id for c in children] if location_ids: if len(location_ids) == 1: q = FS("~.location_id") == list(location_ids)[0] else: q = FS("~.location_id").belongs(location_ids) query = (query & q) if query else q else: continue filters = (filters | query) if filters else query if not filters: # Show no results if the user has no needs reported return FS("id").belongs(set()) # Exclude the person's own offers if exclude_provider: filters &= FS("~.pe_id") != exclude_provider return filters
def _update_sync(self, resource, filters, selected_repository_id, properties): """ Update synchronization settings @param resource: available resources config @param filters: filter applied on the resource @param selected_repository_id: repository that is under current selection @param properties: comment field of the pr_subscription; used to store the ids of FTP Sync """ db = current.db s3db = current.s3db auth = current.auth user_id = auth.user.id utcnow = current.request.utcnow if properties: old_repository_id = properties["repository_id"] if old_repository_id != selected_repository_id: # Update properties["repository_id"] = selected_repository_id else: # First Run properties = {"repository_id": selected_repository_id} old_repository_id = selected_repository_id # Sync Task sync_task_table = s3db.sync_task # Check if task already exists query = (sync_task_table.deleted != True) & \ (sync_task_table.owned_by_user == user_id) & \ (sync_task_table.repository_id == old_repository_id) row = db(query).select(sync_task_table.id, sync_task_table.repository_id, limitby=(0, 1)).first() if row: old_sync_id = properties["sync_task_id"] # Check if update? if row.repository_id != selected_repository_id: # Update db(sync_task_table.repository_id == old_repository_id).\ update(repository_id = selected_repository_id) sync_task_id = properties["sync_task_id"] = row.id else: # First Run sync_task_data = {"repository_id": selected_repository_id, "resource_name": resource, "mode": 2, #Push "strategy": ["create"], # Alert updates are done # as extra info elements "representation": "cap", "multiple_file": True, "last_push": utcnow, # since used for notifications, # so don't send old alerts } sync_task_id = sync_task_table.insert(**sync_task_data) auth.s3_set_record_owner(sync_task_table, sync_task_id) old_sync_id = properties["sync_task_id"] = sync_task_id # Sync Resource Filter # Remove Old Filter and create new query = (FS("task_id") == old_sync_id) s3db.resource("sync_resource_filter", filter=query).delete() # Normally a filter looks like this # [["priority__belongs","24,3"],[u'location_id$L0__belongs', u'Nepal'], # [u'location_id$L1__belongs', u'Central']] # Get only those that have value and ignore null one filters = json.loads(filters) filters = [filter_ for filter_ in filters if filter_[1] is not None] sync_resource_filter_table = s3db.sync_resource_filter if len(filters) > 0: for filter_ in filters: # Get the prefix prefix = str(filter_[0]).strip("[]") # Get the value for prefix values = str(filter_[1]) # Set the Components if prefix in ["event_type_id__belongs", "priority__belongs", "language__belongs"]: component = "info" else: component = "area_location" filter_string = "%s.%s=%s" % (component, prefix, values) resource_filter_data = {"task_id": sync_task_id, "tablename": resource, "filter_string": filter_string, "modified_on": utcnow, } resource_filter_id = sync_resource_filter_table. \ insert(**resource_filter_data) row = db(sync_resource_filter_table.id == resource_filter_id).\ select(limitby=(0, 1)).first() auth.s3_set_record_owner(sync_resource_filter_table, resource_filter_id) s3db.onaccept(sync_resource_filter_table, row) return properties
def apply_method(self, r, **attr): """ Entry point for REST API @param r: the request (S3Request) @param attr: REST controller parameters """ if r.record and r.representation in ("html", "aadata"): T = current.T db = current.db s3db = current.s3db auth = current.auth is_admin = auth.s3_has_role("ADMIN") accessible = auth.s3_accessible_query # Profile widgets profile_widgets = [] add_widget = profile_widgets.append dt_row_actions = self.dt_row_actions from s3 import FS # Organisations widget = { "label": T("My Organizations"), "icon": "organisation", "insert": False, "tablename": "org_organisation", "type": "datatable", "actions": dt_row_actions("org", "organisation"), "list_fields": [ "name", (T("Type"), "organisation_organisation_type.organisation_type_id"), "phone", (T("Email"), "email.value"), "website", ], } if not is_admin: otable = s3db.org_organisation rows = db(accessible("update", "org_organisation")).select(otable.id) organisation_ids = [row.id for row in rows] widget["filter"] = FS("id").belongs(organisation_ids) add_widget(widget) # Facilities widget = { "label": T("My Facilities"), "icon": "facility", "insert": False, "tablename": "org_facility", "type": "datatable", "actions": dt_row_actions("org", "facility"), "list_fields": [ "name", "code", "site_facility_type.facility_type_id", "organisation_id", "location_id", ], } if not is_admin: ftable = s3db.org_facility rows = db(accessible("update", "org_facility")).select(ftable.id) facility_ids = [row.id for row in rows] widget["filter"] = FS("id").belongs(facility_ids) add_widget(widget) # Networks (only if user can update any records) widget_filter = None if not is_admin: gtable = s3db.org_group rows = db(accessible("update", "org_group")).select(gtable.id) group_ids = [row.id for row in rows] if group_ids: widget_filter = FS("id").belongs(group_ids) if is_admin or widget_filter: widget = { "label": T("My Networks"), "icon": "org-network", "insert": False, "tablename": "org_group", "filter": widget_filter, "type": "datatable", "actions": dt_row_actions("org", "group"), } add_widget(widget) # Groups (only if user can update any records) widget_filter = None if not is_admin: gtable = s3db.pr_group rows = db(accessible("update", "pr_group")).select(gtable.id) group_ids = [row.id for row in rows] if group_ids: widget_filter = FS("id").belongs(group_ids) if is_admin or widget_filter: widget = { "label": T("My Groups"), "icon": "group", "insert": False, "tablename": "pr_group", "filter": widget_filter, "type": "datatable", "actions": dt_row_actions("hrm", "group"), "list_fields": [ (T("Network"), "group_team.org_group_id"), "name", "description", (T("Chairperson"), "chairperson"), ], } add_widget(widget) # CMS Content from gluon.html import A, DIV, H2, TAG item = None title = T("Dashboard") if current.deployment_settings.has_module("cms"): name = "Dashboard" ctable = s3db.cms_post query = (ctable.name == name) & (ctable.deleted != True) row = db(query).select(ctable.id, ctable.title, ctable.body, limitby=(0, 1)).first() get_vars = { "page": name, "url": URL(args="dashboard", vars={}), } if row: title = row.title if is_admin: item = DIV( XML(row.body), DIV( A( T("Edit"), _href=URL( c="cms", f="post", args=[row.id, "update"], vars=get_vars, ), _class="action-btn", ), _class="cms-edit", ), ) else: item = DIV(XML(row.body)) elif is_admin: item = DIV( DIV( A( T("Edit"), _href=URL( c="cms", f="post", args="create", vars=get_vars, ), _class="action-btn", ), _class="cms-edit", )) # Rheader if r.representation == "html": profile_header = DIV( DIV( DIV(A( T("Personal Profile"), _href=URL(c="default", f="person"), _class="action-btn", ), _class="dashboard-links right", _style="padding:0.5rem 0;"), H2(title), _class="medium-6 columns end", ), _class="row", ) if item: # Append CMS content profile_header = TAG[""]( profile_header, DIV( DIV( item, _class="medium-12 columns", ), _class="row", ), ) else: profile_header = None # Configure profile tablename = r.tablename s3db.configure( tablename, profile_cols=2, profile_header=profile_header, profile_widgets=profile_widgets, ) # Render profile from s3 import S3Profile profile = S3Profile() profile.tablename = tablename profile.request = r output = profile.profile(r, **attr) if r.representation == "html": output["title"] = \ current.response.title = T("Personal Dashboard") return output else: raise HTTP(501, current.ERROR.BAD_METHOD)
def __call__(self): T = current.T db = current.db s3db = current.s3db request = current.request response = current.response s3 = response.s3 output = {} output["title"] = response.title = current.deployment_settings.get_system_name() # Map auth = current.auth is_logged_in = auth.is_logged_in() callback = None if is_logged_in: # Show the User's Coalition's Polygon org_group_id = auth.user.org_group_id if org_group_id: # Lookup Coalition Name table = s3db.org_group row = db(table.id == org_group_id).select(table.name, limitby=(0, 1) ).first() if row: callback = '''S3.gis.show_map(); var layer,layers=S3.gis.maps.default_map.layers; for(var i=0,len=layers.length;i<len;i++){ layer=layers[i]; if(layer.name=='%s'){layer.setVisibility(true)}}''' % row.name if not callback: # Show all Coalition Polygons callback = '''S3.gis.show_map(); var layer,layers=S3.gis.maps.default_map.layers; for(var i=0,len=layers.length;i<len;i++){ layer=layers[i]; if(layer.name=='All Coalitions'){layer.setVisibility(true)}} ''' gis = current.gis config = gis.get_config() config.zoom = 8 map = gis.show_map(width=770, height=295, callback=callback, catalogue_layers=True, collapsed=True, save=False, ) output["map"] = map # Description of available data from s3db.cms import S3CMS for item in response.menu: item["cms"] = S3CMS.resource_content(module = item["c"], resource = item["f"]) # Site Activity Log resource = s3db.resource("s3_audit") resource.add_filter(FS("~.method") != "delete") orderby = "s3_audit.timestmp desc" list_fields = ["id", "method", "timestmp", "user_id", "tablename", "record_id", ] #current.deployment_settings.ui.customise_s3_audit() db.s3_audit.user_id.represent = s3_auth_user_represent_name list_id = "log" datalist, numrows, ids = resource.datalist(fields=list_fields, start=None, limit=4, list_id=list_id, orderby=orderby, layout=s3.render_log) # Placeholder filter_form = DIV(_class="filter_form") if numrows == 0: # Empty table or just no match? from s3 import S3CRUD table = resource.table if "deleted" in table: available_records = db(table.deleted != True) else: available_records = 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 ajaxurl = URL(c="default", f="audit", args="datalist_f.dl") popup_url = URL(c="default", f="audit", args="datalist.popup") dl = datalist.html(ajaxurl=ajaxurl, pagesize=4, popup_url=popup_url, popup_title=T("Updates"), ) data = dl if is_logged_in and org_group_id: # Add a Filter filter_widgets = [S3OptionsFilter("user_id$org_group_id", label = "", # Can't just use "" as this is then omitted from rendering options = {"*": T("All"), org_group_id: T("My Community"), }, cols = 2, multiple = False, ), ] filter_submit_url = URL(c="default", f="index") filter_ajax_url = URL(c="default", f="audit", args=["filter.options"]) filter_form = S3FilterForm(filter_widgets, filter_manager = False, formstyle = filter_formstyle, clear = False, submit = True, ajax = True, url = filter_submit_url, ajaxurl = filter_ajax_url, _class = "filter-form", _id = "%s-filter-form" % list_id ) filter_form = filter_form.html(resource, request.get_vars, target=list_id, ) output["updates"] = data output["filter_form"] = filter_form # Add JavaScript appname = request.application debug = s3.debug scripts_append = s3.scripts.append if debug: # Infinite Scroll doesn't make sense here, but currently required by dataLists.js scripts_append("/%s/static/scripts/jquery.infinitescroll.js" % appname) scripts_append("/%s/static/scripts/jquery.viewport.js" % appname) scripts_append("/%s/static/scripts/S3/s3.dataLists.js" % appname) else: scripts_append("/%s/static/scripts/S3/s3.dataLists.min.js" % appname) self._view(THEME, "index.html") return output
def prep(r): # @todo: limit organisation types? # @todo: hide unwanted form fields? # Filter for just referral agencies query = FS("organisation_id:po_referral_organisation.id") != None r.resource.add_filter(query) # Create referral_organisation record onaccept onaccept = s3db.get_config("org_organisation", "onaccept") s3db.configure( "org_organisation", onaccept=(onaccept, s3db.po_organisation_onaccept), ) # Filter households to areas served (if any areas defined) # @todo: suppress this filter per deployment setting if r.record and r.component_name == "organisation_household": atable = s3db.po_organisation_area query = (atable.organisation_id == r.id) & \ (atable.deleted != True) rows = db(query).select(atable.area_id) if rows: area_ids = [row.area_id for row in rows] area_ids.append(None) table = r.component.table table.household_id.requires.set_filter( filterby="area_id", filter_opts=area_ids, ) elif not r.component: list_fields = [ "name", "name", (T("Type"), "organisation_organisation_type.organisation_type_id"), (T("Areas"), "organisation_area.area_id"), "website", ] s3db.configure( "org_organisation", list_fields=list_fields, ) if r.interactive: # Adapt CRUD Strings s3.crud_strings["org_organisation"].update({ "label_create": T("Create Agency"), "title_list": T("Referral Agencies"), "title_display": T("Agency Details"), "title_update": T("Edit Agency Details"), "label_delete_button": T("Delete Agency"), }) if r.component_name == "area": s3.crud_strings["po_organisation_area"].update({ "label_create": T("Add Area"), }) return True
def prep(r): if not r.record: query = (FS("followup_date") <= datetime.datetime.utcnow().date()) & \ (FS("completed") != True) r.resource.add_filter(query) return True
def customise_cms_post_resource(r, tablename): db = current.db s3db = current.s3db table = s3db.cms_post table.priority.readable = table.priority.writable = True table.series_id.readable = table.series_id.writable = True table.status_id.readable = table.status_id.writable = True method = r.method if method in ("create", "update"): # Custom Form from s3 import S3SQLCustomForm, S3SQLInlineComponent crud_fields = [ (T("Type"), "series_id"), (T("Priority"), "priority"), (T("Status"), "status_id"), (T("Title"), "title"), (T("Text"), "body"), (T("Location"), "location_id"), # Tags are added client-side S3SQLInlineComponent( "document", name="file", label=T("Files"), fields=[ ("", "file"), #"comments", ], ), ] if r.tablename != "event_incident": if r.tablename == "event_event": from gluon import IS_EMPTY_OR from s3 import IS_ONE_OF itable = s3db.event_incident query = (itable.event_id == r.id) & \ (itable.closed == False) & \ (itable.deleted == False) set = db(query) f = s3db.event_post.incident_id f.requires = IS_EMPTY_OR( IS_ONE_OF(set, "event_incident.id", f.represent, orderby="event_incident.name", sort=True)) crud_fields.insert( 0, S3SQLInlineComponent( "incident_post", fields=[("", "incident_id")], label=T("Incident"), multiple=False, )) crud_form = S3SQLCustomForm(*crud_fields) # Client support for Tags appname = r.application s3 = current.response.s3 scripts_append = s3.scripts.append if s3.debug: scripts_append("/%s/static/scripts/tag-it.js" % appname) else: scripts_append("/%s/static/scripts/tag-it.min.js" % appname) scripts_append("/%s/static/themes/WACOP/js/update_tags.js" % appname) if method == "create": s3.jquery_ready.append('''wacop_update_tags("")''') elif method == "update": ttable = s3db.cms_tag ltable = s3db.cms_tag_post if r.tablename == "cms_post": post_id = r.id else: post_id = r.component.id query = (ltable.post_id == post_id) & \ (ltable.tag_id == ttable.id) tags = db(query).select(ttable.name) tags = [tag.name for tag in tags] tags = ",".join(tags) s3.jquery_ready.append('''wacop_update_tags("%s")''' % tags) # Processing Tags default = s3db.get_config(tablename, "onaccept") if isinstance(default, list): onaccept = default onaccept.append(cms_post_onaccept) else: onaccept = [default, cms_post_onaccept] s3db.configure( tablename, crud_form=crud_form, onaccept=onaccept, ) elif method in ("custom", "datalist", "filter"): # dataList configuration from templates.WACOP.controllers import cms_post_list_layout s3 = current.response.s3 s3.dl_no_header = True s3db.configure( tablename, list_fields=[ "series_id", "priority", "status_id", "date", "title", "body", "created_by", "tag.name", "document.file", "comment.id", #"comment.body", # Extra fields come in unsorted, so can't match up to records #"comment.created_by", #"comment.created_on", ], list_layout=cms_post_list_layout, orderby="cms_post.date desc", ) if method in ("custom", "filter"): # Filter Widgets from s3 import S3DateFilter, \ S3LocationFilter, \ S3OptionsFilter, \ S3TextFilter if method == "filter": # Apply filter_vars get_vars = r.get_vars for k, v in get_vars.iteritems(): # We only expect a maximum of 1 of these, no need to append from s3 import FS s3.filter = (FS(k) == v) date_filter = S3DateFilter( "date", # If we introduce an end_date on Posts: #["date", "end_date"], label="", #hide_time = True, slider=True, ) date_filter.input_labels = { "ge": "Start Time/Date", "le": "End Time/Date" } from templates.WACOP.controllers import text_filter_formstyle filter_widgets = [ S3TextFilter( [ "body", ], formstyle=text_filter_formstyle, label=T("Search"), _placeholder=T("Enter search term…"), ), S3OptionsFilter( "series_id", label="", noneSelectedText="Type", # T() added in widget no_opts="", ), S3OptionsFilter( "priority", label="", noneSelectedText="Priority", # T() added in widget no_opts="", ), S3OptionsFilter( "status_id", label="", noneSelectedText="Status", # T() added in widget no_opts="", ), S3OptionsFilter( "created_by$organisation_id", label="", noneSelectedText="Source", # T() added in widget no_opts="", ), S3OptionsFilter( "tag_post.tag_id", label="", noneSelectedText="Tag", # T() added in widget no_opts="", ), date_filter, ] if r.tablename == "event_event" or \ (method == "filter" and get_vars.get("event_post.event_id")): # Event Profile filter_widgets.insert( 1, S3OptionsFilter( "incident_post.incident_id", label="", noneSelectedText="Incident", # T() added in widget no_opts="", )) user = current.auth.user if user: filter_widgets.insert( 1, S3OptionsFilter( "bookmark.user_id", label="", options={ "*": T("All"), user.id: T("My Bookmarks"), }, cols=2, multiple=False, table=False, )) s3db.configure( tablename, filter_widgets=filter_widgets, )