예제 #1
0
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")
예제 #2
0
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)
예제 #3
0
    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)
예제 #4
0
    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
예제 #5
0
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)
예제 #6
0
    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)
예제 #7
0
    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
예제 #8
0
    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,
        )
예제 #9
0
    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 = ""
예제 #10
0
        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
예제 #11
0
    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
예제 #12
0
        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
예제 #13
0
파일: po.py 프로젝트: nursix/eden
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
예제 #14
0
파일: dvi.py 프로젝트: sahana/eden
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,
    )
예제 #15
0
    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
예제 #16
0
    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
예제 #17
0
    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
예제 #18
0
    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
예제 #19
0
파일: helpers.py 프로젝트: sahana/eden
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
예제 #20
0
    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
예제 #21
0
    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)
예제 #22
0
    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
예제 #23
0
    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
예제 #24
0
파일: po.py 프로젝트: nursix/eden
 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
예제 #25
0
    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,
                )