def get_gis_all_levels(self, level=None): all_levels = self.gis.get("all_levels") if not all_levels: L0 = self.get_gis_locations_hierarchy("L0") L1 = self.get_gis_locations_hierarchy("L1") L2 = self.get_gis_locations_hierarchy("L2") L3 = self.get_gis_locations_hierarchy("L3") L4 = self.get_gis_locations_hierarchy("L4") T = self.T all_levels = OrderedDict([ ("L0", L0), ("L1", L1), ("L2", L2), ("L3", L3), ("L4", L4), ("L5", T("Neighbourhood")), ("GR", T("Location Group")), ("XX", T("Imported")), ]) if level: try: return all_levels[level] except: return level else: return all_levels
def sort_dict_by_values(adict): """ Sort a dict by value and return an OrderedDict - used by modules/eden/irs.py """ return OrderedDict(sorted(adict.items(), key=lambda item: item[1]))
def get_auth_access_levels(self): """ Access levels for the Role Manager UI """ T = current.T return self.auth.get( "access_levels", OrderedDict([("reader", "Reader"), ("data_entry", "Data Entry"), ("editor", "Editor"), ("super", "Super Editor")]))
def get_gis_default_location_hierarchy(self): location_hierarchy = self.gis.get("location_hierarchy", None) if not location_hierarchy: location_hierarchy = OrderedDict([ ("L0", current.T("Country")), ("L1", current.T("Province")), ("L2", current.T("District")), ("L3", current.T("Town")), ("L4", current.T("Village")), #("L5", current.T("Neighbourhood")), ]) return location_hierarchy
def get_auth_role_modules(self): """ Which modules are includes in the Role Manager - to assign discrete permissions to via UI """ T = current.T return self.auth.get( "role_modules", OrderedDict([("staff", "Staff"), ("vol", "Volunteers"), ("member", "Members"), ("inv", "Warehouses"), ("asset", "Assets"), ("project", "Projects"), ("survey", "Assessments"), ("irs", "Incidents")]))
def get_cap_languages(self): """ Languages for cap info. This gets filled in the drop-down for selecting languages. These values should conform to RFC 3066. For a full list of languages and their codes, see: http://www.i18nguy.com/unicode/language-identifiers.html """ return self.cap.get( "languages", OrderedDict([("ar", "العربية"), ("en", "English"), ("fr", "Français"), ("pt", "Português"), ("ru", "русский"), ("es", "Español")]))
def get_gis_locations_hierarchy(self, level=None): locations_hierarchy = self.gis.get("locations_hierarchy") if not locations_hierarchy: T = self.T locations_hierarchy = OrderedDict([ ("L0", T("Country")), ("L1", T("Province")), ("L2", T("District")), ("L3", T("Town")), ("L4", T("Village")), #("L5", T("Neighbourhood")), ]) if level: try: return locations_hierarchy[level] except: return level else: return locations_hierarchy
def get_L10n_languages(self): return self.L10n.get("languages", OrderedDict([ ("ar", "العربية"), ("zh-cn", "中文 (简体)"), ("zh-tw", "中文 (繁體)"), ("en", "English"), ("fr", "Français"), ("de", "Deutsch"), ("el", "ελληνικά"), ("it", "Italiano"), ("ja", "日本語"), ("ko", "한국어"), ("pt", "Português"), ("pt-br", "Português (Brasil)"), ("ru", "русский"), ("es", "Español"), ("tl", "Tagalog"), ("ur", "اردو"), ("vi", "Tiếng Việt"), ]))
settings.base.system_name = T("Resource Management System") settings.base.system_name_short = T("RMS") # ----------------------------------------------------------------------------- # Theme (folder to use for views/layout.html) settings.base.theme = "IFRC" settings.gis.map_height = 600 settings.gis.map_width = 854 # Display Resources recorded to Admin-Level Locations on the map # @ToDo: Move into gis_config? settings.gis.display_L0 = True # ----------------------------------------------------------------------------- # L10n (Localization) settings settings.L10n.languages = OrderedDict([ ("en-gb", "English"), ("es", "Español"), ]) # Default Language settings.L10n.default_language = "en-gb" # Default timezone for users settings.L10n.utc_offset = "UTC +0700" # Number formats (defaults to ISO 31-0) # Decimal separator for numbers (defaults to ,) settings.L10n.decimal_separator = "." # Thousands separator for numbers (defaults to space) settings.L10n.thousands_separator = "," # Unsortable 'pretty' date format settings.L10n.date_format = T("%d-%b-%y") settings.L10n.datetime_format = T("%d-%b-%Y %H:%M:%S") # Make last name in person/user records mandatory settings.L10n.mandatory_lastname = True
#settings.base.theme = "EUROSHA" # Auth settings # Do new users need to verify their email address? settings.auth.registration_requires_verification = True # Do new users need to be approved by an administrator prior to being able to login? settings.auth.registration_requires_approval = True # Uncomment this to request the Organisation when a user registers settings.auth.registration_requests_organisation = True settings.auth.role_modules = OrderedDict([ ("transport", "Airports and Seaports"), ("hms", "Hospitals"), ("org", "Organizations, Offices, and Facilities"), ("inv", "Warehouses"), ("staff", "Staff"), ("vol", "Volunteers"), ("project", "Projects"), ("asset", "Assets"), ("vehicle", "Vehicles"), ]) # L10n settings settings.L10n.languages = OrderedDict([ ("en", "English"), ("fr", "French"), ]) # Default timezone for users settings.L10n.utc_offset = "UTC +0100" # Number formats (defaults to ISO 31-0) # Decimal separator for numbers (defaults to ,)
settings.modules = OrderedDict([ # Core modules which shouldn't be disabled ("default", Storage( name_nice = T("Home"), restricted = False, # Use ACLs to control access to this module access = None, # All Users (inc Anonymous) can see this module in the default menu & access the controller module_type = None # This item is not shown in the menu )), ("admin", Storage( name_nice = T("Administration"), #description = "Site Administration", restricted = True, access = "|1|", # Only Administrators can see this module in the default menu & access the controller module_type = None # This item is handled separately for the menu )), ("appadmin", Storage( name_nice = T("Administration"), #description = "Site Administration", restricted = True, module_type = None # No Menu )), ("errors", Storage( name_nice = T("Ticket Viewer"), #description = "Needed for Breadcrumbs", restricted = False, module_type = None # No Menu )), ("sync", Storage( name_nice = T("Synchronization"), #description = "Synchronization", restricted = True, access = "|1|", # Only Administrators can see this module in the default menu & access the controller module_type = None # This item is handled separately for the menu )), ("translate", Storage( name_nice = T("Translation Functionality"), #description = "Selective translation of strings based on module.", module_type = None, )), # Uncomment to enable internal support requests #("support", Storage( # name_nice = T("Support"), # #description = "Support Requests", # restricted = True, # module_type = None # This item is handled separately for the menu # )), ("gis", Storage( name_nice = T("Map"), #description = "Situation Awareness & Geospatial Analysis", restricted = True, module_type = 6, # 6th item in the menu )), ("pr", Storage( name_nice = T("Person Registry"), #description = "Central point to record details on People", restricted = True, access = "|1|", # Only Administrators can see this module in the default menu (access to controller is possible to all still) module_type = 10 )), ("org", Storage( name_nice = T("Organizations"), #description = 'Lists "who is doing what & where". Allows relief agencies to coordinate their activities', restricted = True, module_type = 1 )), # All modules below here should be possible to disable safely ("hrm", Storage( name_nice = T("Staff"), #description = "Human Resources Management", restricted = True, module_type = 2, )), ("vol", Storage( name_nice = T("Volunteers"), #description = "Human Resources Management", restricted = True, module_type = 2, )), ("cms", Storage( name_nice = T("Content Management"), #description = "Content Management System", restricted = True, module_type = 10, )), ("doc", Storage( name_nice = T("Documents"), #description = "A library of digital resources, such as photos, documents and reports", restricted = True, module_type = 10, )), ("msg", Storage( name_nice = T("Messaging"), #description = "Sends & Receives Alerts via Email & SMS", restricted = True, # The user-visible functionality of this module isn't normally required. Rather it's main purpose is to be accessed from other modules. module_type = None, )), ("supply", Storage( name_nice = T("Supply Chain Management"), #description = "Used within Inventory Management, Request Management and Asset Management", restricted = True, module_type = None, # Not displayed )), ("inv", Storage( name_nice = T("Warehouses"), #description = "Receiving and Sending Items", restricted = True, module_type = 4 )), #("proc", Storage( # name_nice = T("Procurement"), # #description = "Ordering & Purchasing of Goods & Services", # restricted = True, # module_type = 10 # )), ("asset", Storage( name_nice = T("Assets"), #description = "Recording and Assigning Assets", restricted = True, module_type = 5, )), # Vehicle depends on Assets ("vehicle", Storage( name_nice = T("Vehicles"), #description = "Manage Vehicles", restricted = True, module_type = 10, )), ("req", Storage( name_nice = T("Requests"), #description = "Manage requests for supplies, assets, staff or other resources. Matches against Inventories where supplies are requested.", restricted = True, module_type = 10, )), ("project", Storage( name_nice = T("Projects"), #description = "Tracking of Projects, Activities and Tasks", restricted = True, module_type = 2 )), ("survey", Storage( name_nice = T("Surveys"), #description = "Create, enter, and manage surveys.", restricted = True, module_type = 5, )), ("cr", Storage( name_nice = T("Shelters"), #description = "Tracks the location, capacity and breakdown of victims in Shelters", restricted = True, module_type = 10 )), ("hms", Storage( name_nice = T("Hospitals"), #description = "Helps to monitor status of hospitals", restricted = True, module_type = 10 )), ("irs", Storage( name_nice = T("Incidents"), #description = "Incident Reporting System", restricted = True, module_type = 10 )), ("dvi", Storage( name_nice = T("Disaster Victim Identification"), #description = "Disaster Victim Identification", restricted = True, module_type = 10, #access = "|DVI|", # Only users with the DVI role can see this module in the default menu & access the controller #audit_read = True, # Can enable Audit for just an individual module here #audit_write = True )), ("dvr", Storage( name_nice = T("Disaster Victim Registry"), #description = "Allow affected individuals & households to register to receive compensation and distributions", restricted = True, module_type = 10, )), ("transport", Storage( name_nice = T("Transport"), restricted = True, module_type = 10, )), #("mpr", Storage( # name_nice = T("Missing Person Registry"), # #description = "Helps to report and search for missing persons", # restricted = True, # module_type = 10, # )), #("stats", Storage( # name_nice = T("Statistics"), # #description = "Manages statistics", # restricted = True, # module_type = None, # )), #("vulnerability", Storage( # name_nice = T("Vulnerability"), # #description = "Manages vulnerability indicators", # restricted = True, # module_type = 10, # )), #("event", Storage( # name_nice = T("Events"), # #description = "Activate Events (e.g. from Scenario templates) for allocation of appropriate Resources (Human, Assets & Facilities).", # restricted = True, # module_type = 10, # )), #("scenario", Storage( # name_nice = T("Scenarios"), # #description = "Define Scenarios for allocation of appropriate Resources (Human, Assets & Facilities).", # restricted = True, # module_type = 10, # )), #("fire", Storage( # name_nice = T("Fire Stations"), # #description = "Fire Station Management", # restricted = True, # module_type = 1, # )), #("flood", Storage( # name_nice = T("Flood Warnings"), # #description = "Flood Gauges show water levels in various parts of the country", # restricted = True, # module_type = 10 # )), #("member", Storage( # name_nice = T("Members"), # #description = "Membership Management System", # restricted = True, # module_type = 10, # )), #("patient", Storage( # name_nice = T("Patient Tracking"), # #description = "Tracking of Patients", # restricted = True, # module_type = 10 # )), #("security", Storage( # name_nice = T("Security"), # #description = "Security Management System", # restricted = True, # module_type = 10, # )), # These are specialist modules #("cap", Storage( # name_nice = T("CAP"), # #description = "Create & broadcast CAP alerts", # restricted = True, # module_type = 10, #)), # Requires RPy2 & PostgreSQL #("climate", Storage( # name_nice = T("Climate"), # #description = "Climate data portal", # restricted = True, # module_type = 10, #)), #("delphi", Storage( # name_nice = T("Delphi Decision Maker"), # #description = "Supports the decision making of large groups of Crisis Management Experts by helping the groups create ranked list.", # restricted = False, # module_type = 10, # )), # @ToDo: Rewrite in a modern style #("budget", Storage( # name_nice = T("Budgeting Module"), # #description = "Allows a Budget to be drawn up", # restricted = True, # module_type = 10 # )), # @ToDo: Port these Assessments to the Survey module #("building", Storage( # name_nice = T("Building Assessments"), # #description = "Building Safety Assessments", # restricted = True, # module_type = 10, # )), # Deprecated by Surveys module # - depends on CR, IRS & Impact #("assess", Storage( # name_nice = T("Assessments"), # #description = "Rapid Assessments & Flexible Impact Assessments", # restricted = True, # module_type = 10, # )), #("impact", Storage( # name_nice = T("Impacts"), # #description = "Used by Assess", # restricted = True, # module_type = None, # )), #("ocr", Storage( # name_nice = T("Optical Character Recognition"), # #description = "Optical Character Recognition for reading the scanned handwritten paper forms.", # restricted = False, # module_type = 10 # )), ])
class SampleTable(object): # Samples always have places and time (periods) # This format is used for daily data and monthly aggregated data. # Performance matters, and we have lots of data, # so unnecessary bytes are shaved as follows: # 1. Sample tables don't need an id - the time and place is the key # 2. The smallest interval is one day, so time_period as smallint (65536) # instead of int, allows a 179 year range, from 1950 to 2129. # Normally we'll be dealing with months however, where this is # even less of an issue. # 3. The value field type can be real, int, smallint, decimal etc. # Double is overkill for climate data. # Take care with decimal though - calculations may be slower. # These tables are not web2py tables as we don't want web2py messing with # them. The database IO is done directly to postgres for speed. # We don't want web2py messing with or complaining about the schemas. # It is likely we will need spatial database extensions i.e. PostGIS. # May be better to cluster places by region. __date_mapper = { "daily": daily, "monthly": monthly } __objects = {} __names = OrderedDict() @staticmethod def with_name(name): return SampleTable.__names[name] __by_ids = {} @staticmethod def with_id(id): SampleTable_by_ids = SampleTable.__by_ids return SampleTable_by_ids[id] @staticmethod def name_exists(name, error): if name in SampleTable.__names: return True else: error( "Available data sets are: %s" % SampleTable.__names.keys() ) return False @staticmethod def matching( parameter_name, sample_type_code ): try: return SampleTable.__objects[(parameter_name, sample_type_code)] except KeyError: pass #print SampleTable.__objects.keys() @staticmethod def add_to_client_config_dict(config_dict): data_type_option_names = [] for SampleTableType in sample_table_types: data_type_option_names.append(SampleTableType.__name__) parameter_names = [] for name, sample_table in SampleTable.__names.iteritems(): if sample_table.date_mapping_name == "monthly": parameter_names.append(name) config_dict.update( data_type_option_names = data_type_option_names, parameter_names = parameter_names ) def __init__( sample_table, db, name, # please change to parameter_name date_mapping_name, field_type, units_name, grid_size, sample_type = None, sample_type_code = None, id = None ): parameter_name = name assert units_name in units_in_out.keys(), \ "units must be one of %s" % units_in_out.keys() assert sample_type is None or sample_type in sample_table_types assert (sample_type is not None) ^ (sample_type_code is not None), \ "either parameters sample_type or sample_type_code must be set" sample_table_type = sample_type or sample_table_types_by_code[sample_type_code] if id is not None: if id in SampleTable.__by_ids: # other code shouldn't be creating SampleTables that already # exist. Or, worse, different ones with the same id. raise Exception( "SampleTable %i already exists. " "Use SampleTable.with_id(%i) instead." % (id, id) ) #return SampleTable.__by_ids[id] else: sample_table.set_id(id) SampleTable.__by_ids[id] = sample_table sample_table.type = sample_table_type sample_table.units_name = units_name sample_table.parameter_name = parameter_name sample_table.date_mapping_name = date_mapping_name sample_table.date_mapper = SampleTable.__date_mapper[date_mapping_name] sample_table.field_type = field_type sample_table.grid_size = grid_size sample_table.db = db SampleTable.__objects[ (parameter_name, sample_table.type.code) ] = sample_table SampleTable.__names["%s %s" % ( sample_table.type.__name__, parameter_name )] = sample_table def __repr__(sample_table): return '%s %s' % ( sample_table.type.__name__, sample_table.parameter_name ) def __str__(sample_table): return '"%s"' % repr(sample_table) @staticmethod def table_name(id): return "climate_sample_table_%i" % id def set_id(sample_table,id): sample_table.id = id sample_table.table_name = SampleTable.table_name(id) def find( sample_table, found, not_found ): db = sample_table.db existing_table_query = db( (db.climate_sample_table_spec.name == sample_table.parameter_name) & (db.climate_sample_table_spec.sample_type_code == sample_table.type.code) ) existing_table = existing_table_query.select().first() if existing_table is None: not_found() else: found( existing_table_query, SampleTable.table_name(existing_table.id), ) def create(sample_table, use_table_name): def create_table(): db = sample_table.db sample_table.set_id( db.climate_sample_table_spec.insert( sample_type_code = sample_table.type.code, name = sample_table.parameter_name, units = sample_table.units_name, field_type = sample_table.field_type, date_mapping = sample_table.date_mapping_name, grid_size = sample_table.grid_size ) ) db.executesql( """ CREATE TABLE %(table_name)s ( place_id integer NOT NULL, time_period smallint NOT NULL, value %(field_type)s NOT NULL, CONSTRAINT %(table_name)s_primary_key PRIMARY KEY (place_id, time_period), CONSTRAINT %(table_name)s_place_id_fkey FOREIGN KEY (place_id) REFERENCES climate_place (id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE ); """ % sample_table.__dict__ ) use_table_name(sample_table.table_name) def complain_that_table_already_exists( query, existing_table_name ): raise Exception( "Table for %s %s already exists as '%s'" % ( sample_table.type.__name__, sample_table.parameter_name, existing_table_name ) ) return sample_table.find( not_found = create_table, found = complain_that_table_already_exists ) def create_indices(sample_table): db = sample_table.db for field in ( "time_period", "place_id", "value" ): db.executesql( "CREATE INDEX %(table_name)s_%(field)s__idx " "on %(table_name)s(%(field)s);" % dict( sample_table.__dict__, field = field ) ) use_table_name(sample_table.table_name) def drop(sample_table, use_table_name): db = sample_table.db def complain_that_table_does_not_exist(): raise Exception( "%s %s table not found" % ( sample_table.sample_type_name, sample_table.parameter_name, ) ) def delete_table( existing_table_query, existing_table_name, ): existing_table_query.delete() db.executesql( "DROP TABLE %s;" % existing_table_name ) db.commit() use_table_name(existing_table_name) return sample_table.find( not_found = complain_that_table_does_not_exist, found = delete_table ) def clear(sample_table): sample_table.db.executesql( "TRUNCATE TABLE %s;" % sample_table.table_name ) def insert_values(sample_table, values): sql = "INSERT INTO %s (time_period, place_id, value) VALUES %s;" % ( sample_table.table_name, ",".join(values) ) try: sample_table.db.executesql(sql) except: print sql raise def pull_real_time_data(sample_table): import_sql = ( "SELECT AVG(value), station_id, obstime " "FROM weather_data_nepal " "WHERE parameter = 'T' " "GROUP BY station_id, obstime" "ORDER BY station_id, obstime;" ) sample_table.cldb.executesql( import_sql ) def csv_data( sample_table, place_id, date_from, date_to ): sample_table_id = sample_table.id date_mapper = sample_table.date_mapper start_date_number = date_mapper.date_to_time_period(date_from) end_date_number = date_mapper.date_to_time_period(date_to) data = [ "date,"+sample_table.units_name ] for record in db.executesql( "SELECT * " "FROM climate_sample_table_%(sample_table_id)i " "WHERE time_period >= %(start_date_number)i " "AND place_id = %(place_id)i " "AND time_period <= %(end_date_number)i" "ORDER BY time_period ASC;" % locals() ): place_id, time_period, value = record date_format = { monthly: "%Y-%m", daily: "%Y-%m-%d" }[date_mapper] data.append( ",".join(( date_mapper.to_date(time_period).strftime(date_format), str(value) )) ) data.append("") return "\n".join(data) def get_available_years( sample_table ): years = [] for (year,) in db.executesql( "SELECT sub.year FROM (" "SELECT (((time_period + %(start_month_0_indexed)i) / 12) + %(start_year)i)" " AS year " "FROM climate_sample_table_%(sample_table_id)i " ") as sub GROUP BY sub.year;" % dict( start_year = start_year, start_month_0_indexed = start_month_0_indexed, sample_table_id = sample_table.id ) ): years.append(year) return years
def config(settings): """ Template settings for DRR Project Portal http://eden.sahanafoundation.org/wiki/Deployments/DRRProjectPortal """ T = current.T # Base Settings # Pre-Populate settings.base.prepopulate += ("DRRPP", "default/users") settings.base.system_name = T("DRR Project Portal") settings.base.system_name_short = T("DRRPP") # Theme (folder to use for views/layout.html) settings.base.theme = "DRRPP" # ============================================================================= # Auth Settings # Security Policy settings.security.policy = 6 # Realm settings.security.map = True # Do new users need to verify their email address? settings.auth.registration_requires_verification = True # Do new users need to be approved by an administrator prior to being able to login? settings.auth.registration_requires_approval = True # Uncomment this to request the Organisation when a user registers settings.auth.registration_requests_organisation = True settings.auth.registration_pending = \ """Registration awaiting approval from Administrator or Organisation Contact. A confirmation email will be sent to you once approved. For enquiries contact %s""" % settings.get_mail_approver() # Record Approval settings.auth.record_approval = True settings.auth.record_approval_required_for = ( "org_organisation", "project_project", "project_framework", ) # ============================================================================= # L10n Settings settings.L10n.languages = OrderedDict([ ("en-gb", "English"), ]) settings.L10n.default_language = "en-gb" # Default timezone for users settings.L10n.utc_offset = "+0700" # Number formats (defaults to ISO 31-0) # Decimal separator for numbers (defaults to ,) settings.L10n.decimal_separator = "." # Thousands separator for numbers (defaults to space) settings.L10n.thousands_separator = "," # Unsortable 'pretty' date format #settings.L10n.date_format = "%d-%b-%Y" # ============================================================================= # Finance Settings settings.fin.currencies = { "EUR": "Euros", # Needed for IFRC RMS interop "PHP": "Philippine Pesos", # Needed for IFRC RMS interop "CHF": "Swiss Francs", # Needed for IFRC RMS interop "USD": "United States Dollars", "NZD": "New Zealand Dollars", } # ============================================================================= # GIS Settings # Theme settings.gis.map_height = 600 settings.gis.map_width = 960 # container_12 # Display Resources recorded to Admin-Level Locations on the map # @ToDo: Move into gis_config? settings.gis.display_L0 = True # Deployment only covers Asia-Pacific settings.gis.countries = [ "AF", "AU", "BD", "BN", "CK", "CN", "FJ", "FM", "HK", "ID", "IN", "JP", "KH", "KI", "KP", "KR", "LA", "MH", "MM", "MN", "MV", "MY", "NP", "NZ", "PG", "PH", "PK", "PW", "SB", "SG", "SL", "TH", "TL", "TO", "TV", "TW", "VN", "VU", "WS" ] # Resources which can be directly added to the main map settings.gis.poi_create_resources = None # ============================================================================= # Organisation Settings # Enable the use of Organisation Branches # RMS-compatibility settings.org.branches = True # ============================================================================= # Project Settings # Uncomment this to use settings suitable for a global/regional organisation (e.g. DRR) settings.project.mode_3w = True # Uncomment this to use DRR (Disaster Risk Reduction) extensions settings.project.mode_drr = True # Uncomment this to use Codes for projects settings.project.codes = True # Uncomment this to call project locations 'Communities' #settings.project.community = True # Uncomment this to enable Hazards in 3W projects settings.project.hazards = True # Uncomment this to create a project_location for each country which is a project is implemented in # - done via Custom Form instead #settings.project.locations_from_countries = True # Uncomment this to use multiple Budgets per project #settings.project.multiple_budgets = True # Uncomment this to use multiple Organisations per project settings.project.multiple_organisations = True # Uncomment this to disable Sectors in projects settings.project.sectors = False # Uncomment this to enable Themes in 3W projects settings.project.themes = True # Uncomment this to customise # Links to Filtered Components for Donors & Partners settings.project.organisation_roles = { 1: T("Lead Organization"), 2: T("Partner Organization"), 3: T("Donor"), #4: T("Customer"), # T("Beneficiary")? #5: T("Supplier"), 9: T("Partner Organization" ), # Needed for IFRC RMS interop ("Partner National Society") } # ============================================================================= # UI Settings # Enable this for a UN-style deployment settings.ui.cluster = True settings.ui.hide_report_options = False settings.ui.hide_report_filter_options = True # Uncomment to restrict the export formats available settings.ui.export_formats = ["xls", "xml"] # Uncomment to include an Interim Save button on CRUD forms settings.ui.interim_save = True # Uncomment to disable responsive behavior of datatables # - Disabled until tested settings.ui.datatables_responsive = False # ----------------------------------------------------------------------------- # Formstyle def formstyle_row(id, label, widget, comment, hidden=False): if hidden: hide = "hide" else: hide = "" row = DIV( DIV(label, _id=id + "_label", _class="w2p_fl"), DIV(widget, _id=id + "_widget", _class="w2p_fw"), DIV(comment, _id=id + "_comment", _class="w2p_fc"), _id=id, _class="w2p_r %s" % hide, ) return row # ----------------------------------------------------------------------------- def formstyle(self, xfields): """ Use new Web2Py formstyle to generate form using DIVs & CSS CSS can then be used to create MUCH more flexible form designs: - Labels above vs. labels to left - Multiple Columns @ToDo: Requires further changes to code to use """ form = DIV() for id, a, b, c, in xfields: form.append(formstyle_row(id, a, b, c)) return form settings.ui.formstyle_row = formstyle_row #settings.ui.formstyle = formstyle # Breaks e.g. org/organisation/create settings.ui.formstyle = formstyle_row # ----------------------------------------------------------------------------- def customise_project_project_controller(**attr): db = current.db s3db = current.s3db s3 = current.response.s3 tablename = "project_project" # Load normal model table = s3db[tablename] # Custom Components s3db.add_components( tablename, project_drrpp={ "joinby": "project_id", "multiple": False, }, project_output="project_id", doc_document=( # Files { "name": "file", "joinby": "doc_id", "filterby": "url", "filterfor": ("", None), }, # Links { "name": "url", "joinby": "doc_id", "filterby": "file", "filterfor": ("", None), }, ), ) # Custom Fields table.name.label = T("Project Title") s3db.project_project.budget.label = T("Total Funding (USD)") location_id = s3db.project_location.location_id location_id.label = "" # Limit to just Countries location_id.requires = s3db.gis_country_requires # Use dropdown, not AC location_id.widget = None # In DRRPP this is a free field table = s3db.project_organisation table.comments.label = T("Role") table.comments.widget = SQLFORM.widgets.string.widget table.amount.label = T("Amount") table = s3db.doc_document table.file.widget = lambda field, value, download_url: \ SQLFORM.widgets.upload.widget(field, value, download_url, _size = 15) table.comments.widget = SQLFORM.widgets.string.widget # If not logged in, contact person is required logged_in = current.auth.is_logged_in() if not logged_in: table = s3db.project_drrpp table.focal_person.required = True table.email.required = True table.email.requires = IS_EMAIL() # Custom dataTable s3["dataTable_dom"] = 'ripl<"dataTable_table"t>p' # Don't show export buttons for XLS/XML s3.formats = Storage(xls=None, xml=None) # Remove rheader attr["rheader"] = None # Only show 10 Project by default to improve load time attr["dt_lengthMenu"] = [[10, 50, -1], [10, 50, T("All")]] s3.dataTable_pageLength = 10 # Custom PreP standard_prep = s3.prep def custom_prep(r): resource = r.resource # Call standard prep if callable(standard_prep): result = standard_prep(r) if not result: return False # Customise list_fields if r.method == "review": list_fields = [ "id", "created_on", "modified_on", "name", "start_date", (T("Countries"), "location.location_id"), (T("Hazards"), "hazard.name"), (T("Lead Organization"), "organisation_id"), (T("Donors"), "donor.organisation_id"), ] elif r.representation == "xls": # All readable Fields should be exported list_fields = [ "id", "name", "code", "description", "status_id", "start_date", "end_date", "drrpp.duration", (T("Countries"), "location.location_id"), "drrpp.L1", (T("Hazards"), "hazard.name"), (T("Themes"), "theme.name"), "objectives", "drrpp.activities", "output.name", "drr.hfa", "drrpp.rfa", "drrpp.pifacc", "drrpp.jnap", (T("Lead Organization"), "organisation_id"), (T("Partners"), "partner.organisation_id"), (T("Donors"), "donor.organisation_id"), "budget", "currency", "drrpp.focal_person", "drrpp.organisation_id", "drrpp.email", "url.url", "drrpp.parent_project", "comments", ] if logged_in: list_fields.extend([ "created_by", "created_on", "modified_by", "modified_on", ]) else: list_fields = [ "id", "name", "start_date", (T("Countries"), "location.location_id"), (T("Hazards"), "hazard.name"), (T("Lead Organization"), "organisation_id"), (T("Donors"), "donor.organisation_id"), ] resource.configure(list_fields=list_fields) # Customise report_options if r.method == "report": report_fields = [ "name", (T("Countries"), "location.location_id"), (T("Hazards"), "hazard.name"), (T("Themes"), "theme.name"), (T("HFA Priorities"), "drr.hfa"), (T("RFA Priorities"), "drrpp.rfa"), (T("Lead Organization"), "organisation_id"), (T("Partner Organizations"), "partner.organisation_id"), (T("Donors"), "donor.organisation_id"), ] # Report Settings for charts if "chart" in r.get_vars and r.representation != "json": s3.crud_strings[tablename].title_report = T( "Project Graph") report_fact_default = "count(id)" report_facts = [(T("Number of Projects"), "count(id)")] show_table = False else: s3.crud_strings[tablename].title_report = T( "Project Matrix") report_fact_default = "count(id)" report_facts = [ (T("Number of Projects"), "count(id)"), (T("Number of Countries"), "count(location.location_id)"), (T("Number of Hazards"), "count(hazard.id)"), (T("Number of Themes"), "count(theme.id)"), (T("Number of HFA Priorities"), "count(drr.hfa)"), (T("Number of RFA Priorities"), "count(drrpp.rfa)"), (T("Number of Lead Organizations"), "count(organisation_id)"), (T("Number of Partner Organizations"), "count(partner.organisation_id)"), (T("Number of Donors"), "count(donor.organisation_id)"), ] show_table = True report_options = Storage(rows=report_fields, cols=report_fields, fact=report_facts, defaults=Storage( rows="hazard.name", cols="location.location_id", fact=report_fact_default, totals=True, table=show_table, )) resource.configure(report_options=report_options) current.deployment_settings.ui.hide_report_options = True if r.interactive: # Don't show Update/Delete button on Search table if r.method is None and not r.id: resource.configure(editable=False, deletable=False) # JS to show/hide Cook Island fields s3.scripts.append("/%s/static/themes/DRRPP/js/drrpp.js" % current.request.application) if r.method == "read": table_pl = s3db.project_location table_l = s3db.gis_location countries = [ row.name for row in db((table_pl.project_id == r.record.id) & (table_pl.location_id == table_l.id)). select(table_l.name) ] if not ("Cook Islands" in countries and len(countries) == 1): s3db.project_drrpp.L1.readable = False s3db.project_drrpp.pifacc.readable = False s3db.project_drrpp.jnap.readable = False # Filter Options project_hfa_opts = s3db.project_hfa_opts() hfa_options = dict( (key, "HFA %s" % key) for key in project_hfa_opts) #hfa_options[None] = NONE # to search NO HFA project_rfa_opts = s3db.project_rfa_opts() rfa_options = dict( (key, "RFA %s" % key) for key in project_rfa_opts) #rfa_options[None] = NONE # to search NO RFA project_pifacc_opts = s3db.project_pifacc_opts() pifacc_options = dict( (key, "PIFACC %s" % key) for key in project_pifacc_opts) #pifacc_options[None] = NONE # to search NO PIFACC project_jnap_opts = s3db.project_jnap_opts() jnap_options = dict( (key, "JNAP %s" % key) for key in project_jnap_opts) #jnap_options[None] = NONE # to search NO JNAP # Filter widgets from s3 import S3TextFilter, S3OptionsFilter, s3_get_filter_opts filter_widgets = [ S3TextFilter(["name", "code", "description", "location.location_id", "hazard.name", "theme.name", ], label = T("Search Projects"), comment = T("Search for a Project by name, code, or description."), ), S3OptionsFilter("status_id", label = T("Status"), cols = 4, ), S3OptionsFilter("location.location_id", label = T("Country"), cols = 3, hidden = True, ), #S3OptionsFilter("drrpp.L1", # label = T("Cook Islands"), # cols = 3, # hidden = True, # ), S3OptionsFilter("hazard.id", label = T("Hazard"), options = lambda: \ s3_get_filter_opts("project_hazard", translate=True), help_field = s3db.project_hazard_help_fields, cols = 4, hidden = True, ), S3OptionsFilter("theme.id", label = T("Theme"), options = lambda: \ s3_get_filter_opts("project_theme", translate=True), help_field = s3db.project_theme_help_fields, cols = 4, # Don't group size = None, hidden = True, ), S3OptionsFilter("drr.hfa", label = T("HFA"), options = hfa_options, help_field = project_hfa_opts, cols = 5, hidden = True, ), S3OptionsFilter("drrpp.rfa", label = T("RFA"), options = rfa_options, help_field = project_rfa_opts, cols = 6, hidden = True, ), S3OptionsFilter("drrpp.pifacc", label = T("PIFACC"), options = pifacc_options, help_field = project_pifacc_opts, cols = 6, hidden = True, ), S3OptionsFilter("drrpp.jnap", label = T("JNAP"), options = jnap_options, help_field = project_jnap_opts, cols = 6, hidden = True, ), S3OptionsFilter("organisation_id", label = T("Lead Organization"), cols = 3, hidden = True, ), S3OptionsFilter("partner.organisation_id", label = T("Partners"), cols = 3, hidden = True, ), S3OptionsFilter("donor.organisation_id", label = T("Donors"), cols = 3, hidden = True, ) ] resource.configure(filter_widgets=filter_widgets) return True s3.prep = custom_prep # Custom Crud Form from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent, S3SQLInlineComponentCheckbox crud_form = S3SQLCustomForm( "name", "code", "description", "status_id", "start_date", "end_date", "drrpp.duration", S3SQLInlineComponent("location", label=T("Countries"), fields=["location_id"], orderby="location_id$name", render_list=True), "drrpp.L1", S3SQLInlineComponentCheckbox( "hazard", label=T("Hazards"), field="hazard_id", option_help="comments", cols=4, ), S3SQLInlineComponentCheckbox( "theme", label=T("Themes"), field="theme_id", option_help="comments", cols=3, ), "objectives", "drrpp.activities", # Outputs S3SQLInlineComponent( "output", label=T("Outputs"), fields=["name", "status"], ), "drr.hfa", "drrpp.rfa", "drrpp.pifacc", "drrpp.jnap", "organisation_id", # Partner Orgs S3SQLInlineComponent( "organisation", name="partner", label=T("Partner Organizations"), fields=[ "organisation_id", "comments", # NB This is labelled 'Role' in DRRPP ], filterby=dict(field="role", options=[2, 9]), default={"role": 2}), # Donors S3SQLInlineComponent("organisation", name="donor", label=T("Donor(s)"), fields=[ "organisation_id", "amount", "currency", ], filterby=dict(field="role", options=[3]), default={"role": 3}), "budget", "drrpp.local_budget", "drrpp.local_currency", "drrpp.focal_person", "drrpp.organisation_id", "drrpp.email", # Files S3SQLInlineComponent("document", name="file", label=T("Files"), fields=["file", "comments"], filterby=dict( field="file", options="", invert=True, )), # Links S3SQLInlineComponent("document", name="url", label=T("Links"), fields=["url", "comments"], filterby=dict( field="url", options=None, invert=True, )), "drrpp.parent_project", "comments", ) s3db.configure( tablename, crud_form=crud_form, subheadings={ 1: "hazard", 2: "theme", 3: "objectives", 4: "drr_hfa", 5: "drrpp_rfa", 6: "drrpp_pifacc", 7: "drrpp_jnap", 8: "organisation_id", }, ) return attr settings.customise_project_project_controller = customise_project_project_controller # ----------------------------------------------------------------------------- def customise_project_framework_controller(**attr): s3db = current.s3db s3 = current.response.s3 # Load normal model table = s3db.project_framework # Custom CRUD Strings s3.crud_strings.project_framework.title_list = \ T("Policies & Strategies List") # Custom PreP standard_prep = s3.prep def custom_prep(r): # Call standard prep if callable(standard_prep): output = standard_prep(r) else: output = True if r.interactive: # Don't show Update/Delete button on List View if r.method is None: s3db.configure( "project_framework", deletable=False, editable=False, insertable=False, ) return output s3.prep = custom_prep return attr settings.customise_project_framework_controller = customise_project_framework_controller # ----------------------------------------------------------------------------- def customise_project_location_controller(**attr): s3db = current.s3db s3 = current.response.s3 # Load normal model table = s3db.project_location # Custom Components s3db.add_components( "project_project", project_drrpp={ "joinby": "project_id", "multiple": False, }, ) # Custom CRUD Strings s3.crud_strings.project_location.title_map = T("Project Map") # Custom Search Filters from s3.s3filter import S3TextFilter, S3OptionsFilter, S3LocationFilter filter_widgets = [ S3TextFilter( [ "project_id$name", "project_id$code", "project_id$description", #"location_id$name", #"project_id$organisation.name", #"project_id$organisation.acronym", ], label=T("Search Projects"), _class="filter-search", ), S3OptionsFilter( "project_id$status_id", label=T("Status"), widget="groupedpts", #widget = "multiselect", cols=3, #hidden=True, ), S3LocationFilter( "location_id", label=T("Country"), levels=("L0", ), widget="groupedpts", #widget = "multiselect", cols=3, hidden=True, ), S3OptionsFilter( "project_id$hazard_project.hazard_id", label=T("Hazard"), widget="groupedpts", #widget = "multiselect", cols=4, hidden=True, ), S3OptionsFilter( "project_id$theme_project.theme_id", label=T("Theme"), widget="groupedpts", #widget = "multiselect", cols=4, hidden=True, ), S3OptionsFilter( "project_id$drr.hfa", label=T("HFA"), widget="groupedpts", #widget = "multiselect", cols=5, hidden=True, ), S3OptionsFilter( "project_id$drrpp.rfa", label=T("RFA"), widget="groupedpts", #widget = "multiselect", cols=6, hidden=True, ), S3OptionsFilter( "project_id$organisation_id", label=T("Lead Organization"), represent="%(name)s", widget="groupedpts", #widget = "multiselect", cols=3, hidden=True, ), S3OptionsFilter( "project_id$partner.organisation_id", label=T("Partners"), represent="%(name)s", widget="groupedpts", #widget = "multiselect", cols=3, hidden=True, ), S3OptionsFilter( "project_id$donor.organisation_id", label=T("Donors"), represent="%(name)s", widget="groupedpts", #widget = "multiselect", cols=3, hidden=True, ), ] s3db.configure( "project_location", filter_widgets=filter_widgets, # Add CSS to default class better than patching #map_submit = (T("Search"), "search-button"), map_advanced=(T("Advanced Search"), T("Simple Search")), ) return attr settings.customise_project_location_controller = customise_project_location_controller # ----------------------------------------------------------------------------- def customise_pr_person_controller(**attr): """ Customise pr_person controller @todo: SavedSearch deprecated, re-implement with saved filters / S3Notify """ s3db = current.s3db # Load normal model table = s3db.pr_person # Custom CRUD Strings current.response.s3.crud_strings.pr_person.title_display = T("My Page") # Customise saved search #table = s3db.pr_saved_search #table.url.label = T("Display Search") # #def url_represent(url): # return TAG[""]( # A(T("List"), # _href = url, # _class = "action-btn" # ), # A(T("Matrix"), # # @ToDo: Fix for S3Search deprecation # _href = url.replace("search", "report"), # _class = "action-btn" # ), # A(T("Chart"), # # @ToDo: Fix for S3Search deprecation # _href = url.replace("search", "report?chart=breakdown%3Arows"), # _class = "action-btn" # ), # A(T("Map"), # # @ToDo: Fix for S3Search deprecation # _href = url.replace("project/search", "location/map"), # _class = "action-btn" # ) # ) #table.url.represent = url_represent # #s3db.configure("pr_saved_search", # list_fields = ["name", # "url", # ] # ) # #attr["rheader"] = H3(T("Saved Searches")) return attr settings.customise_pr_person_controller = customise_pr_person_controller # ----------------------------------------------------------------------------- def customise_org_organisation_controller(**attr): """ Customise org_organisation controller to just show Name field """ s3 = current.response.s3 # Custom PreP standard_prep = s3.prep def custom_prep(r): # Call standard prep if callable(standard_prep): output = standard_prep(r) else: output = True if r.interactive and r.method == "create": table = current.s3db.org_organisation for field in table: if field.name != "name": field.readable = field.writable = False return output s3.prep = custom_prep return attr settings.customise_org_organisation_controller = customise_org_organisation_controller # ============================================================================= # Enabled Modules settings.modules = OrderedDict([ # Core modules which shouldn't be disabled ( "default", Storage( name_nice=T("Home"), restricted=False, # Use ACLs to control access to this module access= None, # All Users (inc Anonymous) can see this module in the default menu & access the controller module_type=None # This item is not shown in the menu )), ( "admin", Storage( name_nice=T("Administration"), #description = "Site Administration", restricted=True, access= "|1|", # Only Administrators can see this module in the default menu & access the controller module_type=None # This item is handled separately for the menu )), ( "appadmin", Storage( name_nice=T("Administration"), #description = "Site Administration", restricted=True, module_type=None # No Menu )), ( "errors", Storage( name_nice=T("Ticket Viewer"), #description = "Needed for Breadcrumbs", restricted=False, module_type=None # No Menu )), ( "sync", Storage( name_nice=T("Synchronization"), #description = "Synchronization", restricted=True, access= "|1|", # Only Administrators can see this module in the default menu & access the controller module_type=None # This item is handled separately for the menu )), ( "gis", Storage( name_nice=T("Map"), #description = "Situation Awareness & Geospatial Analysis", restricted=True, module_type=3, # 6th item in the menu )), ( "pr", Storage( name_nice=T("Person Registry"), #description = "Central point to record details on People", restricted=True, access= "|1|", # Only Administrators can see this module in the default menu (access to controller is possible to all still) module_type=None)), ( "org", Storage( name_nice=T("Organizations"), #description = 'Lists "who is doing what & where". Allows relief agencies to coordinate their activities', restricted=True, module_type=2)), # All modules below here should be possible to disable safely ( "hrm", Storage( name_nice=T("Staff"), #description = "Human Resources Management", restricted=True, module_type=None, )), ( "doc", Storage( name_nice=T("Documents"), #description = "A library of digital resources, such as photos, documents and reports", restricted=True, module_type=None, )), ( "msg", Storage( name_nice=T("Messaging"), #description = "Sends & Receives Alerts via Email & SMS", restricted=True, # The user-visible functionality of this module isn't normally required. Rather it's main purpose is to be accessed from other modules. module_type=None, )), ( "project", Storage( name_nice=T("Projects"), #description = "Tracking of Projects, Activities and Tasks", restricted=True, module_type=1)), # Stats required if using beneficiary model #("stats", Storage( # name_nice = T("Statistics"), # #description = "Manages statistics", # restricted = True, # module_type = None, # )), ])
settings.base.system_name_short = T("Sahana Sunflower") # Set this to True to use Content Delivery Networks to speed up Internet-facing sites settings.base.cdn = False # L10n settings settings.L10n.languages = OrderedDict([ ("ar", "العربية"), ("zh-cn", "中文 (简体)"), ("zh-tw", "中文 (繁體)"), ("en", "English"), ("fr", "Français"), ("de", "Deutsch"), ("el", "ελληνικά"), ("it", "Italiano"), ("ja", "日本語"), ("ko", "한국어"), ("pt", "Português"), ("pt-br", "Português (Brasil)"), ("ru", "русский"), ("es", "Español"), ("tl", "Tagalog"), ("ur", "اردو"), ("vi", "Tiếng Việt"), ]) # Default language for Language Toolbar (& GIS Locations in future) settings.L10n.default_language = "en" # Display the language toolbar settings.L10n.display_toolbar = True # Default timezone for users settings.L10n.utc_offset = "UTC +0000"
settings.modules = OrderedDict([ # Core modules which shouldn't be disabled ( "default", Storage( name_nice=T("Home"), restricted=False, # Use ACLs to control access to this module access= None, # All Users (inc Anonymous) can see this module in the default menu & access the controller module_type=None # This item is not shown in the menu )), ( "admin", Storage( name_nice=T("Administration"), #description = "Site Administration", restricted=True, access= "|1|", # Only Administrators can see this module in the default menu & access the controller module_type=None # This item is handled separately for the menu )), ( "appadmin", Storage( name_nice=T("Administration"), #description = "Site Administration", restricted=True, module_type=None # No Menu )), ( "errors", Storage( name_nice=T("Ticket Viewer"), #description = "Needed for Breadcrumbs", restricted=False, module_type=None # No Menu )), ( "sync", Storage( name_nice=T("Synchronization"), #description = "Synchronization", restricted=True, access= "|1|", # Only Administrators can see this module in the default menu & access the controller module_type=None # This item is handled separately for the menu )), ( "gis", Storage( name_nice=T("Map"), #description = "Situation Awareness & Geospatial Analysis", restricted=True, module_type=6, # 6th item in the menu )), ( "pr", Storage( name_nice=T("Person Registry"), #description = "Central point to record details on People", restricted=True, access= "|1|", # Only Administrators can see this module in the default menu (access to controller is possible to all still) module_type=10)), ( "org", Storage( name_nice=T("Organizations"), #description = 'Lists "who is doing what & where". Allows relief agencies to coordinate their activities', restricted=True, module_type=10)), # All modules below here should be possible to disable safely ( "hrm", Storage( name_nice=T("Staff"), #description = "Human Resources Management", restricted=True, module_type=10, )), #("cms", Storage( # name_nice = T("Content Management"), # #description = "Content Management System", # restricted = True, # module_type = 10, # )), ( "doc", Storage( name_nice=T("Documents"), #description = "A library of digital resources, such as photos, documents and reports", restricted=True, module_type=10, )), ( "msg", Storage( name_nice=T("Messaging"), #description = "Sends & Receives Alerts via Email & SMS", restricted=True, # The user-visible functionality of this module isn't normally required. Rather it's main purpose is to be accessed from other modules. module_type=None, )), ( "supply", Storage( name_nice=T("Supply Chain Management"), #description = "Used within Inventory Management, Request Management and Asset Management", restricted=True, module_type=None, # Not displayed )), ( "inv", Storage( name_nice=T("Warehouse"), #description = "Receiving and Sending Items", restricted=True, module_type=1)), #("proc", Storage( # name_nice = T("Procurement"), # #description = "Ordering & Purchasing of Goods & Services", # restricted = True, # module_type = 10 # )), ( "asset", Storage( name_nice=T("Assets"), #description = "Recording and Assigning Assets", restricted=True, module_type=10, )), # Vehicle depends on Assets #("vehicle", Storage( # name_nice = T("Vehicles"), # #description = "Manage Vehicles", # restricted = True, # module_type = 10, # )), ( "req", Storage( name_nice=T("Requests"), #description = "Manage requests for supplies, assets, staff or other resources. Matches against Inventories where supplies are requested.", restricted=True, module_type=2, )), #("project", Storage( # name_nice = T("Projects"), # #description = "Tracking of Projects, Activities and Tasks", # restricted = True, # module_type = 10 # )), #("survey", Storage( # name_nice = T("Surveys"), # #description = "Create, enter, and manage surveys.", # restricted = True, # module_type = 10, # )), #("cr", Storage( # name_nice = T("Shelters"), # #description = "Tracks the location, capacity and breakdown of victims in Shelters", # restricted = True, # module_type = 10 # )), #("hms", Storage( # name_nice = T("Hospitals"), # #description = "Helps to monitor status of hospitals", # restricted = True, # module_type = 10 # )), #("irs", Storage( # name_nice = T("Incidents"), # #description = "Incident Reporting System", # restricted = False, # module_type = 10 # )), ])
to_date = day_number_to_date ) class Observed(object): code = "O" Observed.__name__ = "Observed Station" class Gridded(object): code = "G" Gridded.__name__ = "Observed Gridded" class Projected(object): code = "P" sample_table_types = (Observed, Gridded, Projected) sample_table_types_by_code = OrderedDict() for SampleTableType in sample_table_types: sample_table_types_by_code[SampleTableType.code] = SampleTableType class SampleTable(object): # Samples always have places and time (periods) # This format is used for daily data and monthly aggregated data. # Performance matters, and we have lots of data, # so unnecessary bytes are shaved as follows: # 1. Sample tables don't need an id - the time and place is the key # 2. The smallest interval is one day, so time_period as smallint (65536) # instead of int, allows a 179 year range, from 1950 to 2129. # Normally we'll be dealing with months however, where this is # even less of an issue.
class SampleTable(object): # Samples always have places and time (periods) # This format is used for daily data and monthly aggregated data. # Performance matters, and we have lots of data, # so unnecessary bytes are shaved as follows: # 1. Sample tables don't need an id - the time and place is the key # 2. The smallest interval is one day, so time_period as smallint (65536) # instead of int, allows a 179 year range, from 1950 to 2129. # Normally we'll be dealing with months however, where this is # even less of an issue. # 3. The value field type can be real, int, smallint, decimal etc. # Double is overkill for climate data. # Take care with decimal though - calculations may be slower. # These tables are not web2py tables as we don't want web2py messing with # them. The database IO is done directly to postgres for speed. # We don't want web2py messing with or complaining about the schemas. # It is likely we will need spatial database extensions i.e. PostGIS. # May be better to cluster places by region. __types = OrderedDict() for SampleTableType in SampleTableTypes: __types[SampleTableType.code] = SampleTableType __date_mapper = {"daily": daily, "monthly": monthly} __objects = {} __names = OrderedDict() @staticmethod def with_name(name): return SampleTable.__names[name] @staticmethod def name_exists(name, error): if name in SampleTable.__names: return True else: error("Available data sets are: %s" % SampleTable.__names.keys()) return False @staticmethod def matching( parameter_name, sample_type_code, ): return SampleTable.__objects[(parameter_name, sample_type_code)] @staticmethod def add_to_client_config_dict(config_dict): data_type_option_names = [] for SampleTableType in SampleTableTypes: data_type_option_names.append(SampleTableType.__name__) config_dict.update(data_type_option_names=data_type_option_names, parameter_names=SampleTable.__names.keys()) def __init__(sample_table, db, name, sample_type, date_mapper, field_type, units, id=None): sample_table.type = sample_type sample_table.db = db sample_table.name = name sample_table.date_mapper = date_mapper sample_table.field_type = field_type assert units in units_in_out.keys(), \ "units must be one of %s" % units_in_out.keys() sample_table.units = units if id is not None: sample_table.set_id(id) def __str__(sample_table): return '"%s %s"' % (sample_table.type.__name__, sample_table.name) def set_id(sample_table, id): sample_table.id = id sample_table.table_name = "climate_sample_table_%i" % id def find(sample_table, found, not_found): db = sample_table.db existing_table_query = db( (db.climate_sample_table_spec.name == sample_table.parameter_name) & (db.climate_sample_table_spec.sample_type_code == sample_type_code)) existing_table = existing_table_query.select().first() if existing_table is None: not_found() else: found( existing_table_query, sample_table_id(existing_table.id), ) def create(sample_table, use_table_name): def create_table(): db = sample_table.db sample_table.set_id( db.climate_sample_table_spec.insert( sample_type_code=sample_table.sample_type_code, name=sample_table.parameter_name, units=sample_table.units_name, field_type=sample_table.value_type)) db.executesql(""" CREATE TABLE %(table_name)s ( place_id integer NOT NULL, time_period smallint NOT NULL, value %(field_type)s NOT NULL, CONSTRAINT %(table_name)s_primary_key PRIMARY KEY (place_id, time_period), CONSTRAINT %(table_name)s_place_id_fkey FOREIGN KEY (place_id) REFERENCES climate_place (id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE ); """ % sample_table.__dict__) for field in ("time_period", "place_id", "value"): db.executesql("CREATE INDEX %(table_name)s_%(field)s__idx " "on %(table_name)s(%(field)s);" % dict(sample_table.__dict__, field=field)) use_table_name(sample_table.table_name) def complain_that_table_already_exists(query, existing_table_name): raise Exception("Table for %s %s already exists as '%s'" % (sample_table.sample_type_name, sample_table.parameter_name, existing_table_name)) return sample_table.find(not_found=create_table, found=complain_that_table_already_exists) def drop(sample_table, use_table_name): db = sample_table.db def complain_that_table_does_not_exist(): raise Exception("%s %s table not found" % ( sample_table.sample_type_name, sample_table.parameter_name, )) def delete_table( existing_table_query, existing_table_name, ): existing_table_query.delete() db.executesql("DROP TABLE %s;" % existing_table_name) db.commit() use_table_name(existing_table_name) return sample_table.find(not_found=complain_that_table_does_not_exist, found=delete_table) def clear(sample_table): sample_table.db.executesql("TRUNCATE TABLE %s;" % sample_table.table_name) def insert_values(sample_table, values): sample_table.db.executesql( "INSERT INTO %s (time_period, place_id, value) VALUES %s;" % (sample_table.table_name, ",".join(values)))
def _options(self, resource): T = current.T EMPTY = T("None") NOOPT = T("No options available") attr = self.attr opts = self.opts # Which levels should we display? # Lookup the appropriate labels from the GIS configuration hierarchy = current.gis.get_location_hierarchy() levels = OrderedDict() if "levels" in opts: for level in opts["levels"]: levels[level] = hierarchy.get(level, level) else: # @ToDo: Do this dynamically from the data? for level in hierarchy: levels[level] = hierarchy.get(level, level) # Pass to data_element self.levels = levels if "label" not in opts: opts["label"] = T("Filter by Location") ftype = "reference gis_location" default = (ftype, levels.keys(), opts.get("no_opts", NOOPT)) # Resolve the field selector field_name = self.field rfield = S3ResourceField(resource, field_name) field = rfield.field if not field or rfield.ftype[:len(ftype)] != ftype: # must be a real reference to gis_location return default fields = [field_name] + ["%s$%s" % (field_name, l) for l in levels] # Find the options rows = resource.select(fields=fields, start=None, limit=None, virtual=False) # No options? if not rows: return default # Intialise Options Storage & Hierarchy hierarchy = {} first = True for level in levels: if first: hierarchy[level] = {} _level = level first = False levels[level] = {"label" : levels[level], "options" : [], } # Store the options & hierarchy for row in rows: if "gis_location" in row: _row = row.gis_location parent = None grandparent = None greatgrandparent = None greatgreatgrandparent = None greatgreatgreatgrandparent = None i = 0 for level in levels: v = _row[level] if v: if v not in levels[level]["options"]: levels[level]["options"].append(v) if i == 0: if v not in hierarchy[_level]: hierarchy[_level][v] = {} parent = v elif i == 1: if v not in hierarchy[_level][parent]: hierarchy[_level][parent][v] = {} grandparent = parent parent = v elif i == 2: if v not in hierarchy[_level][grandparent][parent]: hierarchy[_level][grandparent][parent][v] = {} greatgrandparent = grandparent grandparent = parent parent = v elif i == 3: if v not in hierarchy[_level][greatgrandparent][grandparent][parent]: hierarchy[_level][greatgrandparent][grandparent][parent][v] = {} greatgreatgrandparent = greatgrandparent greatgrandparent = grandparent grandparent = parent parent = v i += 1 # Inject the Location Hierarchy hierarchy = "S3.location_filter_hierarchy=%s" % json.dumps(hierarchy) current.response.s3.js_global.append(hierarchy) return (ftype, levels, None)
settings.modules = OrderedDict([ # Core modules which shouldn't be disabled ( "default", Storage( name_nice=T("Home"), restricted=False, # Use ACLs to control access to this module access= None, # All Users (inc Anonymous) can see this module in the default menu & access the controller module_type=None # This item is not shown in the menu )), ( "admin", Storage( name_nice=T("Administration"), #description = "Site Administration", restricted=True, access= "|1|", # Only Administrators can see this module in the default menu & access the controller module_type=None # This item is handled separately for the menu )), ( "appadmin", Storage( name_nice=T("Administration"), #description = "Site Administration", restricted=True, module_type=None # No Menu )), ( "errors", Storage( name_nice=T("Ticket Viewer"), #description = "Needed for Breadcrumbs", restricted=False, module_type=None # No Menu )), ( "sync", Storage( name_nice=T("Synchronization"), #description = "Synchronization", restricted=True, access= "|1|", # Only Administrators can see this module in the default menu & access the controller module_type=None # This item is handled separately for the menu )), ( "translate", Storage( name_nice=T("Translation Functionality"), #description = "Selective translation of strings based on module.", module_type=None, )), ( "gis", Storage( name_nice=T("Map"), #description = "Situation Awareness & Geospatial Analysis", restricted=True, module_type=6, # 6th item in the menu )), ( "pr", Storage( name_nice=T("Person Registry"), #description = "Central point to record details on People", restricted=True, access= "|1|", # Only Administrators can see this module in the default menu (access to controller is possible to all still) module_type=10)), ( "org", Storage( name_nice=T("Organizations"), #description = 'Lists "who is doing what & where". Allows relief agencies to coordinate their activities', restricted=True, module_type=1)), # Requires RPy2 & PostgreSQL ( "climate", Storage( name_nice=T("Climate"), #description = "Climate data portal", restricted=True, module_type=10, )), ])
def _options(self, resource): T = current.T NOOPT = T("No options available") attr = self.attr opts = self.opts # Which levels should we display? # Lookup the appropriate labels from the GIS configuration hierarchy = current.gis.get_location_hierarchy() levels = OrderedDict() if "levels" in opts: for level in opts["levels"]: levels[level] = hierarchy.get(level, level) else: # @ToDo: Do this dynamically from the data? for level in hierarchy: levels[level] = hierarchy.get(level, level) # Pass to data_element self.levels = levels if "label" not in opts: opts["label"] = T("Filter by Location") ftype = "reference gis_location" default = (ftype, levels.keys(), opts.get("no_opts", NOOPT)) # Resolve the field selector field_name = self.field rfield = S3ResourceField(resource, field_name) field = rfield.field if not field or rfield.ftype[:len(ftype)] != ftype: # must be a real reference to gis_location return default fields = [field_name] + ["%s$%s" % (field_name, l) for l in levels] # Find the options rows = resource.select(fields=fields, start=None, limit=None, virtual=False) # No options? if not rows: return default # Intialise Options Storage & Hierarchy hierarchy = {} first = True for level in levels: if first: hierarchy[level] = {} _level = level first = False levels[level] = { "label": levels[level], "options": [], } # Store the options & hierarchy for row in rows: if "gis_location" in row: _row = row.gis_location parent = None grandparent = None greatgrandparent = None greatgreatgrandparent = None greatgreatgreatgrandparent = None i = 0 for level in levels: v = _row[level] if v: if v not in levels[level]["options"]: levels[level]["options"].append(v) if i == 0: if v not in hierarchy[_level]: hierarchy[_level][v] = {} parent = v elif i == 1: if v not in hierarchy[_level][parent]: hierarchy[_level][parent][v] = {} grandparent = parent parent = v elif i == 2: if v not in hierarchy[_level][grandparent][parent]: hierarchy[_level][grandparent][parent][v] = {} greatgrandparent = grandparent grandparent = parent parent = v elif i == 3: if v not in hierarchy[_level][greatgrandparent][ grandparent][parent]: hierarchy[_level][greatgrandparent][ grandparent][parent][v] = {} greatgreatgrandparent = greatgrandparent greatgrandparent = grandparent grandparent = parent parent = v i += 1 # Inject the Location Hierarchy hierarchy = "S3.location_filter_hierarchy=%s" % json.dumps(hierarchy) current.response.s3.js_global.append(hierarchy) return (ftype, levels, None)
def widget(self, resource, values): """ Render this widget as HTML helper object(s) @param resource: the resource @param values: the search values from the URL query """ attr = self._attr(resource) opts = self.opts name = attr["_name"] # Filter class (default+custom) _class = self._class if "_class" in attr and attr["_class"]: _class = "%s %s" % (_class, attr["_class"]) attr["_class"] = _class # Get the options ftype, options, noopt = self._options(resource) if noopt: return SPAN(noopt, _class="no-options-available") else: options = OrderedDict(options) # Any-All-Option : for many-to-many fields the user can # search for records containing all the options or any # of the options: if len(options) > 1 and ftype[:4] == "list": if self.operator == "anyof": filter_type = "any" else: filter_type = "all" if self.operator == "belongs": self.operator = "contains" any_all = DIV(T("Filter type "), INPUT(_name="%s_filter" % name, _id="%s_filter_any" % name, _type="radio", _value="any", value=filter_type), LABEL(T("Any"), _for="%s_filter_any" % name), INPUT(_name="%s_filter" % name, _id="%s_filter_all" % name, _type="radio", _value="all", value=filter_type), LABEL(T("All"), _for="%s_filter_all" % name), _class="s3-options-filter-anyall") else: any_all = "" # Render the filter widget dummy_field = Storage(name=name, type=ftype, requires=IS_IN_SET(options, multiple=True)) widget_type = opts["widget"] if widget_type == "multiselect-bootstrap": script = "/%s/static/scripts/bootstrap-multiselect.js" % \ current.request.application scripts = current.response.s3.scripts if script not in scripts: scripts.append(script) widget = MultipleOptionsWidget.widget(dummy_field, values, **attr) widget.add_class("multiselect-filter-bootstrap") elif widget_type == "multiselect": if "multiselect-filter-widget" not in _class: attr["_class"] = "%s multiselect-filter-widget" % _class w = S3MultiSelectWidget( filter=opts.get("filter", False), header=opts.get("header", False), selectedList=opts.get("selectedList", 3), ) widget = w(dummy_field, values, **attr) else: if "groupedopts-filter-widget" not in _class: attr["_class"] = "%s groupedopts-filter-widget" % _class w = S3GroupedOptionsWidget( options=options, multiple=True, cols=opts["cols"], size=opts["size"] or 12, help_field=opts["help_field"], ) widget = w(dummy_field, values, **attr) return TAG[""](any_all, widget)
settings = current.deployment_settings T = current.T """ Template settings for UK All settings which are to configure a specific template are located here Deployers should ideally not need to edit any other files outside of their template folder """ # Pre-Populate settings.base.prepopulate = ["Oxfam"] # L10n settings settings.L10n.languages = OrderedDict([ ("en-gb", "English"), ]) # Default Language settings.L10n.default_language = "en-gb" # Uncomment to Hide the language toolbar settings.L10n.display_toolbar = False # Number formats (defaults to ISO 31-0) # Decimal separator for numbers (defaults to ,) settings.L10n.decimal_separator = "." # Thousands separator for numbers (defaults to space) settings.L10n.thousands_separator = "," # Projects # Uncomment this to use settings suitable for a global/regional organisation (e.g. DRR) settings.project.mode_3w = True # Uncomment this to use Codes for projects
# Provide a tool to select locations via a map on all forms with location_id deployment_settings.gis.map_selector = True # Display Resources recorded to Admin-Level Locations on the map deployment_settings.gis.display_L0 = False # Currently unused #deployment_settings.gis.display_L1 = True # Allow non-MapAdmins to edit Admin locations? # (Defaults to True, if not set. Permission to edit location groups defaults # to false.) deployment_settings.gis.edit_L0 = False deployment_settings.gis.edit_L1 = True #deployment_settings.gis.edit_L2 = True deployment_settings.gis.locations_hierarchy = OrderedDict([ ("L0", T("Country")), ("L1", T("Province")), ("L2", T("District")), ("L3", T("Town")), ("L4", T("Village")), #("L5", T("Neighbourhood")), # Currently not supported by testSuite ]) # Should we require locations to follow strict hierarchy? deployment_settings.gis.strict_hierarchy = False # Maximum Marker Size # (takes effect only on display) deployment_settings.gis.marker_max_height = 35 deployment_settings.gis.marker_max_width = 30 # Duplicate Features so that they show wrapped across the Date Line? # Points only for now # lon<0 have a duplicate at lon+360 # lon>0 have a duplicate at lon-360 deployment_settings.gis.duplicate_features = False # Mouse Position: 'normal', 'mgrs' or 'off'