Maintainers
+Maintainers
This module is part of the OpenSPP/OpenSPP2 project on GitHub.
You are welcome to contribute.
diff --git a/spp_gis_indicators/README.rst b/spp_gis_indicators/README.rst index e6a9006d..899431eb 100644 --- a/spp_gis_indicators/README.rst +++ b/spp_gis_indicators/README.rst @@ -31,27 +31,33 @@ legend generation. Key Capabilities ~~~~~~~~~~~~~~~~ -- Define indicator layer configurations that link CEL variables to color - scales and classification methods -- Classify continuous indicator values into discrete color classes using - quantile, equal interval, or manual breaks -- Apply preset ColorBrewer color scales (sequential, diverging, - categorical) or define custom scales -- Compute break values automatically based on actual data distribution +- Define indicator layer configurations linking a CEL variable to a + color scale and classification method +- Classify continuous values into discrete color classes using quantile, + equal interval, or manual breaks +- Compute break values automatically from actual data distribution - Generate HTML legends showing color-to-value mappings - Map area features to colors for choropleth rendering in GIS data layers -- Filter indicators by period and hazard incident context +- Filter indicators by period key and hazard incident context +- Ship 11 preset ColorBrewer color scales (5 sequential, 4 diverging, 2 + categorical) Key Models ~~~~~~~~~~ -- **spp.gis.indicator.layer** -- Configuration linking a CEL variable to - color scale and classification settings -- **spp.gis.color.scale** -- Color scheme definition with JSON array of - hex colors -- **spp.gis.data.layer** -- Extended with choropleth geo representation - option ++------------------------------+---------------------------------------+ +| Model | Description | ++==============================+=======================================+ +| ``spp.gis.indicator.layer`` | Configuration linking a CEL variable | +| | to color scale and class method | ++------------------------------+---------------------------------------+ +| ``spp.gis.color.scale`` | Color scheme definition with JSON | +| | array of hex colors | ++------------------------------+---------------------------------------+ +| ``spp.gis.data.layer`` (ext) | Extended with ``indicator_layer_id`` | +| | for choropleth rendering | ++------------------------------+---------------------------------------+ Configuration ~~~~~~~~~~~~~ @@ -59,37 +65,44 @@ Configuration After installing: 1. Navigate to **Settings > GIS Configuration > Color Scales** -2. Review preset ColorBrewer scales (Blues, Greens, Red-Yellow-Green, - etc.) or create custom scales +2. Review the 11 preset ColorBrewer scales or create custom ones 3. Navigate to **Settings > GIS Configuration > Indicator Layers** -4. Create an indicator layer specifying the CEL variable, period key, - color scale, and classification method -5. In an existing GIS data layer, set ``geo_repr`` to ``choropleth`` and - select the indicator layer to visualize +4. Create an indicator layer: select the CEL variable, period key, color + scale, and classification method +5. In a GIS data layer form, set ``geo_repr`` to ``choropleth`` and + select the indicator layer UI Location ~~~~~~~~~~~ - **Menu**: Settings > GIS Configuration > Indicator Layers - **Menu**: Settings > GIS Configuration > Color Scales +- **Access**: Menus restricted to ``base.group_system`` (Settings/System + admin) +- **Indicator form tabs**: Data Source, Visualization, Legend Preview Security ~~~~~~~~ -- **spp_security.group_spp_user** -- Read -- **spp_security.group_spp_manager** -- Read/write/create (no delete) -- **spp_security.group_spp_admin** -- Full CRUD +==================================== ============ ================ +Group Color Scales Indicator Layers +==================================== ============ ================ +``spp_registry.group_registry_read`` Read Read +``spp_security.group_spp_admin`` Full CRUD Full CRUD +==================================== ============ ================ Extension Points ~~~~~~~~~~~~~~~~ - Override ``_compute_quantile_breaks()`` or - ``_compute_equal_interval_breaks()`` in ``spp.gis.indicator.layer`` to - add custom classification algorithms + ``_compute_equal_interval_breaks()`` for custom classification + algorithms - Inherit ``spp.gis.color.scale`` and override ``get_color_for_value()`` - to implement custom color mapping logic + for custom color mapping - Extend ``spp.gis.indicator.layer._get_indicator_values()`` to support - additional data sources beyond ``spp.hxl.area.indicator`` + data sources beyond ``spp.hxl.area.indicator`` +- Override ``spp.gis.data.layer._get_choropleth_config()`` to customize + frontend choropleth config Dependencies ~~~~~~~~~~~~ @@ -101,6 +114,299 @@ Dependencies .. contents:: :local: +Usage +===== + +Prerequisites +~~~~~~~~~~~~~ + +- Log in as a user with **Settings / System admin** access + (``base.group_system``). The GIS Configuration menus are only visible + to this group. +- The following modules must be installed: ``spp_gis``, + ``spp_hxl_area``, ``spp_registry``, ``spp_security``. +- At least one ``spp.cel.variable`` record and some + ``spp.hxl.area.indicator`` records must exist for indicator layers to + display meaningful data. + +Color Scales — List View +~~~~~~~~~~~~~~~~~~~~~~~~ + +1. Go to **Settings > GIS Configuration > Color Scales**. +2. The list view shows columns: **Sequence** (drag handle), **Scale + Name**, **Scale Type**, **Description**, **Active**. +3. Eleven preset ColorBrewer scales are installed as demo data (loaded + with ``noupdate="1"``, so they survive module upgrades). + +Color Scales — Form View +~~~~~~~~~~~~~~~~~~~~~~~~ + +Open any preset scale (e.g., "Blues (Sequential)"). Verify the form +shows: + +- **Scale Name** — e.g., "Blues (Sequential)" +- **Scale Type** — dropdown with three options: "Sequential (low to + high)", "Diverging (negative to positive)", "Categorical (distinct + values)" +- **Sequence** — numeric ordering value +- **Description** — free-text field below a "Description" separator +- **Colors** section — a text area labeled "Colors (JSON)" containing a + JSON array of hex color codes +- **Preview** section — static help text showing the expected JSON + format + +To create a custom scale: click **New**, fill in **Scale Name** +(required), select a **Scale Type** (defaults to "Sequential"), and +enter a JSON array of at least 2 hex colors in the **Colors (JSON)** +field. Valid formats: ``#RGB`` (3-digit) or ``#RRGGBB`` (6-digit), e.g., +``["#f00", "#00ff00", "#0000ff"]``. + +To archive: open a scale, click **Action > Archive**. An "Archived" +ribbon appears. Archived scales no longer appear in dropdowns on +indicator layers. + +Color Scale — Validation Tests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++----------------------------------+----------------------------------+ +| Action | Expected Result | ++==================================+==================================+ +| Enter invalid JSON (e.g., | ValidationError: "Invalid JSON | +| ``not json``) | in colors_json" | ++----------------------------------+----------------------------------+ +| Enter a non-array (e.g., | ValidationError: "colors_json | +| ``{"a": 1}``) | must be a JSON array" | ++----------------------------------+----------------------------------+ +| Enter fewer than 2 colors (e.g., | ValidationError: "Color scale | +| ``["#fff"]``) | must have at least 2 colors" | ++----------------------------------+----------------------------------+ +| Enter a non-string element | ValidationError: "All colors | +| (e.g., ``[123, "#fff"]``) | must be strings" | ++----------------------------------+----------------------------------+ +| Enter invalid hex (e.g., | ValidationError: "Invalid hex | +| ``["red", "#fff"]``) | color format" | ++----------------------------------+----------------------------------+ +| Enter 5-digit hex (e.g., | ValidationError: "Invalid hex | +| ``["#12345"]``) | color format" | ++----------------------------------+----------------------------------+ + +Indicator Layers — List and Search +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +1. Go to **Settings > GIS Configuration > Indicator Layers**. +2. The list view shows: **Sequence** (drag handle), **Name**, **Variable + Name**, **Period Key**, **Classification Method**, **Number of + Classes**, **Active**. +3. The default search filter is "Active" (only active records shown). +4. Search bar supports filtering by **Name**, **Variable**, and **Period + Key**. +5. Predefined filters: **Active**, **Archived** (under the Filters + menu). +6. Group By options: **Variable**, **Period**, **Classification + Method**. + +Indicator Layer — Form: Data Source Tab +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Click **New** and fill in **Configuration Name** (required). The form +has three tabs: **Data Source**, **Visualization**, and **Legend +Preview**. + +The **Data Source** tab contains: + ++-----------------------------+-----------------------------+----------+ +| Field | Description | Required | ++=============================+=============================+==========+ +| **Indicator Variable** | Dropdown of | Yes | +| | ``spp.cel.variable`` | | +| | records (no inline | | +| | create/open) | | ++-----------------------------+-----------------------------+----------+ +| **Period Key** | Free-text, defaults to | No | +| | "current". Examples: | | +| | "2024-12", "current" | | ++-----------------------------+-----------------------------+----------+ +| **Incident/Disaster** | Dropdown of | No | +| | ``spp.hazard.incident`` | | +| | records. Filters indicator | | +| | data by incident. | | ++-----------------------------+-----------------------------+----------+ + +Indicator Layer — Form: Visualization Tab +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++----------------------+-------------------------+----------------------+ +| Field | Description | Visibility | ++======================+=========================+======================+ +| **Color Scale** | Dropdown of | Always visible | +| | ``spp.gis.color.scale`` | | +| | records (no inline | | +| | create) | | ++----------------------+-------------------------+----------------------+ +| **Classification | Dropdown: "Quantile | Always visible | +| Method** | (Equal count per | | +| | class)", "Equal | | +| | Interval (Equal range | | +| | per class)", "Manual | | +| | Breaks" | | ++----------------------+-------------------------+----------------------+ +| **Number of | Integer (2–10). | Hidden when method | +| Classes** | Controls how many color | is "Manual Breaks" | +| | buckets to create. | | ++----------------------+-------------------------+----------------------+ +| **Manual Break | Comma-separated | Only visible when | +| Points** | numbers, e.g., | method is "Manual | +| | "10,50,100,500" | Breaks" | ++----------------------+-------------------------+----------------------+ +| **Computed Breaks** | Shows the computed | Always visible (in | +| (read-only) | break values as a JSON | "Computed | +| | array | Classification" | +| | | section) | ++----------------------+-------------------------+----------------------+ + +Classification method behavior: + +- **Quantile**: Breaks computed so each class contains approximately the + same number of areas. Requires indicator data. If no data, Computed + Breaks is empty. +- **Equal Interval**: Breaks evenly spaced between minimum and maximum + indicator values. If all values are equal, Computed Breaks is empty. +- **Manual Breaks**: Uses user-supplied break points directly. Does not + depend on indicator data. + +Indicator Layer — Form: Legend Preview Tab +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Displays a read-only HTML preview of the legend. +- Each legend item shows a colored box and a label with the value range + (e.g., "< 10.00", "10.00 - 50.00", ">= 500.00"). +- The legend updates automatically when break values or color scale + changes. + +Indicator Layer — Validation Tests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Number of Classes:** + ++-----------------------------+----------------------------------------+ +| Action | Expected Result | ++=============================+========================================+ +| Set Number of Classes to 1 | ValidationError: "Number of classes | +| | must be at least 2" | ++-----------------------------+----------------------------------------+ +| Set Number of Classes to 11 | ValidationError: "Number of classes | +| | must not exceed 10" | ++-----------------------------+----------------------------------------+ +| Set Number of Classes to 5 | Saves successfully | ++-----------------------------+----------------------------------------+ + +**Manual Breaks:** + ++----------------------------------+----------------------------------+ +| Action | Expected Result | ++==================================+==================================+ +| Select "Manual Breaks" but leave | ValidationError: "Manual breaks | +| the field empty | are required when using manual | +| | classification" | ++----------------------------------+----------------------------------+ +| Enter non-numeric text (e.g., | ValidationError: "Invalid manual | +| "a,b,c") | breaks format" | ++----------------------------------+----------------------------------+ +| Enter descending values (e.g., | ValidationError: "Manual breaks | +| "100,50,10") | must be in ascending order" | ++----------------------------------+----------------------------------+ +| Enter valid ascending values | Saves successfully; Computed | +| (e.g., "10,50,100") | Breaks shows | +| | ``[10.0, 50.0, 100.0]`` | ++----------------------------------+----------------------------------+ + +GIS Data Layer — Choropleth Integration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This module extends the GIS data layer form to support indicator-based +choropleth visualization. Data layers are configured within GIS view +definitions, not through a standalone menu — they appear as inline +records on the GIS view form. + +To set up: open a GIS data layer form, set **Geo Repr** to "Choropleth +(Color by Value)". The "Colors" section hides and the "Choropleth +Configuration" and "Choropleth Settings" sections appear. In the +**Choropleth Settings** section (added by this module), select an +**Indicator Configuration** from the dropdown. + +When ``geo_repr`` is set to "Choropleth", two configuration paths are +available: + ++----------------------+-------------------------+----------------------------+ +| Path | Source | When to Use | ++======================+=========================+============================+ +| **Value Field** | ``choropleth_field_id`` | Simple field-based | +| (base ``spp_gis``) | — picks a numeric field | coloring | +| | directly from the | | +| | layer's model | | ++----------------------+-------------------------+----------------------------+ +| **Indicator | ``indicator_layer_id`` | Area-level indicator data | +| Configuration** | — uses a pre-configured | from | +| (this module) | indicator layer with | ``spp.hxl.area.indicator`` | +| | CEL variables | | ++----------------------+-------------------------+----------------------------+ + +Either one satisfies the choropleth validation. Setting both is allowed; +when an Indicator Configuration is set, it takes priority over the Value +Field. + +Data Layer — Choropleth Validation Tests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++----------------------------------+----------------------------------+ +| Action | Expected Result | ++==================================+==================================+ +| Set Geo Repr to "Choropleth" | ValidationError: "Choropleth | +| with neither Value Field nor | layers require a Value Field or | +| Indicator Configuration | Indicator Configuration." | ++----------------------------------+----------------------------------+ +| Set Geo Repr to "Choropleth" | Saves successfully | +| with only Indicator | | +| Configuration set | | ++----------------------------------+----------------------------------+ +| Set Geo Repr to "Choropleth" | Saves successfully | +| with only Value Field set | | ++----------------------------------+----------------------------------+ +| Set Geo Repr to "Basic" with no | Saves successfully (no | +| choropleth config | validation) | ++----------------------------------+----------------------------------+ + +Edge Cases to Verify +~~~~~~~~~~~~~~~~~~~~ + ++----------------------------------+----------------------------------+ +| Scenario | Expected Behavior | ++==================================+==================================+ +| Indicator layer with no matching | Computed Breaks is empty; Legend | +| indicator data | Preview is blank | ++----------------------------------+----------------------------------+ +| Indicator layer where all | Equal Interval returns empty | +| indicator values are identical | breaks; Quantile returns empty | +| | breaks; Legend shows single | +| | class | ++----------------------------------+----------------------------------+ +| Color scale with exactly 2 | Works correctly; values map to | +| colors | one of two colors | ++----------------------------------+----------------------------------+ +| Manual breaks with a single | Creates 2 classes: "< 50.00" and | +| value (e.g., "50") | ">= 50.00" | ++----------------------------------+----------------------------------+ +| Archiving an indicator layer | The data layer still references | +| used by a data layer | it but ``get_feature_colors()`` | +| | returns no colors for inactive | +| | config | ++----------------------------------+----------------------------------+ +| Deleting a color scale used by | Standard Odoo referential | +| an indicator layer | integrity behavior (blocked or | +| | cascaded depending on | +| | ``ondelete``) | ++----------------------------------+----------------------------------+ + Bug Tracker =========== diff --git a/spp_gis_indicators/readme/DESCRIPTION.md b/spp_gis_indicators/readme/DESCRIPTION.md index 87c6e3fc..beccd292 100644 --- a/spp_gis_indicators/readme/DESCRIPTION.md +++ b/spp_gis_indicators/readme/DESCRIPTION.md @@ -2,46 +2,52 @@ Choropleth visualization for area-level indicators on GIS maps. Maps indicator v ### Key Capabilities -- Define indicator layer configurations that link CEL variables to color scales and classification methods -- Classify continuous indicator values into discrete color classes using quantile, equal interval, or manual breaks -- Apply preset ColorBrewer color scales (sequential, diverging, categorical) or define custom scales -- Compute break values automatically based on actual data distribution +- Define indicator layer configurations linking a CEL variable to a color scale and classification method +- Classify continuous values into discrete color classes using quantile, equal interval, or manual breaks +- Compute break values automatically from actual data distribution - Generate HTML legends showing color-to-value mappings - Map area features to colors for choropleth rendering in GIS data layers -- Filter indicators by period and hazard incident context +- Filter indicators by period key and hazard incident context +- Ship 11 preset ColorBrewer color scales (5 sequential, 4 diverging, 2 categorical) ### Key Models -- **spp.gis.indicator.layer** -- Configuration linking a CEL variable to color scale and classification settings -- **spp.gis.color.scale** -- Color scheme definition with JSON array of hex colors -- **spp.gis.data.layer** -- Extended with choropleth geo representation option +| Model | Description | +| -------------------------- | -------------------------------------------------------------------- | +| `spp.gis.indicator.layer` | Configuration linking a CEL variable to color scale and class method | +| `spp.gis.color.scale` | Color scheme definition with JSON array of hex colors | +| `spp.gis.data.layer` (ext) | Extended with `indicator_layer_id` for choropleth rendering | ### Configuration After installing: 1. Navigate to **Settings > GIS Configuration > Color Scales** -2. Review preset ColorBrewer scales (Blues, Greens, Red-Yellow-Green, etc.) or create custom scales +2. Review the 11 preset ColorBrewer scales or create custom ones 3. Navigate to **Settings > GIS Configuration > Indicator Layers** -4. Create an indicator layer specifying the CEL variable, period key, color scale, and classification method -5. In an existing GIS data layer, set `geo_repr` to `choropleth` and select the indicator layer to visualize +4. Create an indicator layer: select the CEL variable, period key, color scale, and classification method +5. In a GIS data layer form, set `geo_repr` to `choropleth` and select the indicator layer ### UI Location - **Menu**: Settings > GIS Configuration > Indicator Layers - **Menu**: Settings > GIS Configuration > Color Scales +- **Access**: Menus restricted to `base.group_system` (Settings/System admin) +- **Indicator form tabs**: Data Source, Visualization, Legend Preview ### Security -- **spp_security.group_spp_user** -- Read -- **spp_security.group_spp_manager** -- Read/write/create (no delete) -- **spp_security.group_spp_admin** -- Full CRUD +| Group | Color Scales | Indicator Layers | +| -------------------------------- | ------------ | ---------------- | +| `spp_registry.group_registry_read` | Read | Read | +| `spp_security.group_spp_admin` | Full CRUD | Full CRUD | ### Extension Points -- Override `_compute_quantile_breaks()` or `_compute_equal_interval_breaks()` in `spp.gis.indicator.layer` to add custom classification algorithms -- Inherit `spp.gis.color.scale` and override `get_color_for_value()` to implement custom color mapping logic -- Extend `spp.gis.indicator.layer._get_indicator_values()` to support additional data sources beyond `spp.hxl.area.indicator` +- Override `_compute_quantile_breaks()` or `_compute_equal_interval_breaks()` for custom classification algorithms +- Inherit `spp.gis.color.scale` and override `get_color_for_value()` for custom color mapping +- Extend `spp.gis.indicator.layer._get_indicator_values()` to support data sources beyond `spp.hxl.area.indicator` +- Override `spp.gis.data.layer._get_choropleth_config()` to customize frontend choropleth config ### Dependencies diff --git a/spp_gis_indicators/readme/USAGE.md b/spp_gis_indicators/readme/USAGE.md new file mode 100644 index 00000000..6c7fabcc --- /dev/null +++ b/spp_gis_indicators/readme/USAGE.md @@ -0,0 +1,134 @@ +### Prerequisites + +- Log in as a user with **Settings / System admin** access (`base.group_system`). The GIS Configuration menus are only visible to this group. +- The following modules must be installed: `spp_gis`, `spp_hxl_area`, `spp_registry`, `spp_security`. +- At least one `spp.cel.variable` record and some `spp.hxl.area.indicator` records must exist for indicator layers to display meaningful data. + +### Color Scales — List View + +1. Go to **Settings > GIS Configuration > Color Scales**. +2. The list view shows columns: **Sequence** (drag handle), **Scale Name**, **Scale Type**, **Description**, **Active**. +3. Eleven preset ColorBrewer scales are installed as demo data (loaded with `noupdate="1"`, so they survive module upgrades). + +### Color Scales — Form View + +Open any preset scale (e.g., "Blues (Sequential)"). Verify the form shows: + +- **Scale Name** — e.g., "Blues (Sequential)" +- **Scale Type** — dropdown with three options: "Sequential (low to high)", "Diverging (negative to positive)", "Categorical (distinct values)" +- **Sequence** — numeric ordering value +- **Description** — free-text field below a "Description" separator +- **Colors** section — a text area labeled "Colors (JSON)" containing a JSON array of hex color codes +- **Preview** section — static help text showing the expected JSON format + +To create a custom scale: click **New**, fill in **Scale Name** (required), select a **Scale Type** (defaults to "Sequential"), and enter a JSON array of at least 2 hex colors in the **Colors (JSON)** field. Valid formats: `#RGB` (3-digit) or `#RRGGBB` (6-digit), e.g., `["#f00", "#00ff00", "#0000ff"]`. + +To archive: open a scale, click **Action > Archive**. An "Archived" ribbon appears. Archived scales no longer appear in dropdowns on indicator layers. + +### Color Scale — Validation Tests + +| Action | Expected Result | +|--------|----------------| +| Enter invalid JSON (e.g., `not json`) | ValidationError: "Invalid JSON in colors_json" | +| Enter a non-array (e.g., `{"a": 1}`) | ValidationError: "colors_json must be a JSON array" | +| Enter fewer than 2 colors (e.g., `["#fff"]`) | ValidationError: "Color scale must have at least 2 colors" | +| Enter a non-string element (e.g., `[123, "#fff"]`) | ValidationError: "All colors must be strings" | +| Enter invalid hex (e.g., `["red", "#fff"]`) | ValidationError: "Invalid hex color format" | +| Enter 5-digit hex (e.g., `["#12345"]`) | ValidationError: "Invalid hex color format" | + +### Indicator Layers — List and Search + +1. Go to **Settings > GIS Configuration > Indicator Layers**. +2. The list view shows: **Sequence** (drag handle), **Name**, **Variable Name**, **Period Key**, **Classification Method**, **Number of Classes**, **Active**. +3. The default search filter is "Active" (only active records shown). +4. Search bar supports filtering by **Name**, **Variable**, and **Period Key**. +5. Predefined filters: **Active**, **Archived** (under the Filters menu). +6. Group By options: **Variable**, **Period**, **Classification Method**. + +### Indicator Layer — Form: Data Source Tab + +Click **New** and fill in **Configuration Name** (required). The form has three tabs: **Data Source**, **Visualization**, and **Legend Preview**. + +The **Data Source** tab contains: + +| Field | Description | Required | +|-------|-------------|----------| +| **Indicator Variable** | Dropdown of `spp.cel.variable` records (no inline create/open) | Yes | +| **Period Key** | Free-text, defaults to "current". Examples: "2024-12", "current" | No | +| **Incident/Disaster** | Dropdown of `spp.hazard.incident` records. Filters indicator data by incident. | No | + +### Indicator Layer — Form: Visualization Tab + +| Field | Description | Visibility | +|-------|-------------|------------| +| **Color Scale** | Dropdown of `spp.gis.color.scale` records (no inline create) | Always visible | +| **Classification Method** | Dropdown: "Quantile (Equal count per class)", "Equal Interval (Equal range per class)", "Manual Breaks" | Always visible | +| **Number of Classes** | Integer (2–10). Controls how many color buckets to create. | Hidden when method is "Manual Breaks" | +| **Manual Break Points** | Comma-separated numbers, e.g., "10,50,100,500" | Only visible when method is "Manual Breaks" | +| **Computed Breaks** (read-only) | Shows the computed break values as a JSON array | Always visible (in "Computed Classification" section) | + +Classification method behavior: + +- **Quantile**: Breaks computed so each class contains approximately the same number of areas. Requires indicator data. If no data, Computed Breaks is empty. +- **Equal Interval**: Breaks evenly spaced between minimum and maximum indicator values. If all values are equal, Computed Breaks is empty. +- **Manual Breaks**: Uses user-supplied break points directly. Does not depend on indicator data. + +### Indicator Layer — Form: Legend Preview Tab + +- Displays a read-only HTML preview of the legend. +- Each legend item shows a colored box and a label with the value range (e.g., "< 10.00", "10.00 - 50.00", ">= 500.00"). +- The legend updates automatically when break values or color scale changes. + +### Indicator Layer — Validation Tests + +**Number of Classes:** + +| Action | Expected Result | +|--------|----------------| +| Set Number of Classes to 1 | ValidationError: "Number of classes must be at least 2" | +| Set Number of Classes to 11 | ValidationError: "Number of classes must not exceed 10" | +| Set Number of Classes to 5 | Saves successfully | + +**Manual Breaks:** + +| Action | Expected Result | +|--------|----------------| +| Select "Manual Breaks" but leave the field empty | ValidationError: "Manual breaks are required when using manual classification" | +| Enter non-numeric text (e.g., "a,b,c") | ValidationError: "Invalid manual breaks format" | +| Enter descending values (e.g., "100,50,10") | ValidationError: "Manual breaks must be in ascending order" | +| Enter valid ascending values (e.g., "10,50,100") | Saves successfully; Computed Breaks shows `[10.0, 50.0, 100.0]` | + +### GIS Data Layer — Choropleth Integration + +This module extends the GIS data layer form to support indicator-based choropleth visualization. Data layers are configured within GIS view definitions, not through a standalone menu — they appear as inline records on the GIS view form. + +To set up: open a GIS data layer form, set **Geo Repr** to "Choropleth (Color by Value)". The "Colors" section hides and the "Choropleth Configuration" and "Choropleth Settings" sections appear. In the **Choropleth Settings** section (added by this module), select an **Indicator Configuration** from the dropdown. + +When `geo_repr` is set to "Choropleth", two configuration paths are available: + +| Path | Source | When to Use | +|------|--------|-------------| +| **Value Field** (base `spp_gis`) | `choropleth_field_id` — picks a numeric field directly from the layer's model | Simple field-based coloring | +| **Indicator Configuration** (this module) | `indicator_layer_id` — uses a pre-configured indicator layer with CEL variables | Area-level indicator data from `spp.hxl.area.indicator` | + +Either one satisfies the choropleth validation. Setting both is allowed; when an Indicator Configuration is set, it takes priority over the Value Field. + +### Data Layer — Choropleth Validation Tests + +| Action | Expected Result | +|--------|----------------| +| Set Geo Repr to "Choropleth" with neither Value Field nor Indicator Configuration | ValidationError: "Choropleth layers require a Value Field or Indicator Configuration." | +| Set Geo Repr to "Choropleth" with only Indicator Configuration set | Saves successfully | +| Set Geo Repr to "Choropleth" with only Value Field set | Saves successfully | +| Set Geo Repr to "Basic" with no choropleth config | Saves successfully (no validation) | + +### Edge Cases to Verify + +| Scenario | Expected Behavior | +|----------|-------------------| +| Indicator layer with no matching indicator data | Computed Breaks is empty; Legend Preview is blank | +| Indicator layer where all indicator values are identical | Equal Interval returns empty breaks; Quantile returns empty breaks; Legend shows single class | +| Color scale with exactly 2 colors | Works correctly; values map to one of two colors | +| Manual breaks with a single value (e.g., "50") | Creates 2 classes: "< 50.00" and ">= 50.00" | +| Archiving an indicator layer used by a data layer | The data layer still references it but `get_feature_colors()` returns no colors for inactive config | +| Deleting a color scale used by an indicator layer | Standard Odoo referential integrity behavior (blocked or cascaded depending on `ondelete`) | diff --git a/spp_gis_indicators/static/description/index.html b/spp_gis_indicators/static/description/index.html index ff1a9f99..da6ae525 100644 --- a/spp_gis_indicators/static/description/index.html +++ b/spp_gis_indicators/static/description/index.html @@ -378,42 +378,58 @@
| Model | +Description | +
|---|---|
| spp.gis.indicator.layer | +Configuration linking a CEL variable +to color scale and class method | +
| spp.gis.color.scale | +Color scheme definition with JSON +array of hex colors | +
| spp.gis.data.layer (ext) | +Extended with indicator_layer_id +for choropleth rendering | +
After installing:
| Group | +Color Scales | +Indicator Layers | +
|---|---|---|
| spp_registry.group_registry_read | +Read | +Read | +
| spp_security.group_spp_admin | +Full CRUD | +Full CRUD | +
Table of contents
Open any preset scale (e.g., “Blues (Sequential)”). Verify the form +shows:
+To create a custom scale: click New, fill in Scale Name +(required), select a Scale Type (defaults to “Sequential”), and +enter a JSON array of at least 2 hex colors in the Colors (JSON) +field. Valid formats: #RGB (3-digit) or #RRGGBB (6-digit), e.g., +["#f00", "#00ff00", "#0000ff"].
+To archive: open a scale, click Action > Archive. An “Archived” +ribbon appears. Archived scales no longer appear in dropdowns on +indicator layers.
+| Action | +Expected Result | +
|---|---|
| Enter invalid JSON (e.g., +not json) | +ValidationError: “Invalid JSON +in colors_json” | +
| Enter a non-array (e.g., +{"a": 1}) | +ValidationError: “colors_json +must be a JSON array” | +
| Enter fewer than 2 colors (e.g., +["#fff"]) | +ValidationError: “Color scale +must have at least 2 colors” | +
| Enter a non-string element +(e.g., [123, "#fff"]) | +ValidationError: “All colors +must be strings” | +
| Enter invalid hex (e.g., +["red", "#fff"]) | +ValidationError: “Invalid hex +color format” | +
| Enter 5-digit hex (e.g., +["#12345"]) | +ValidationError: “Invalid hex +color format” | +
Click New and fill in Configuration Name (required). The form +has three tabs: Data Source, Visualization, and Legend +Preview.
+The Data Source tab contains:
+| Field | +Description | +Required | +
|---|---|---|
| Indicator Variable | +Dropdown of +spp.cel.variable +records (no inline +create/open) | +Yes | +
| Period Key | +Free-text, defaults to +“current”. Examples: +“2024-12”, “current” | +No | +
| Incident/Disaster | +Dropdown of +spp.hazard.incident +records. Filters indicator +data by incident. | +No | +
| Field | +Description | +Visibility | +
|---|---|---|
| Color Scale | +Dropdown of +spp.gis.color.scale +records (no inline +create) | +Always visible | +
| Classification +Method | +Dropdown: “Quantile +(Equal count per +class)”, “Equal +Interval (Equal range +per class)”, “Manual +Breaks” | +Always visible | +
| Number of +Classes | +Integer (2–10). +Controls how many color +buckets to create. | +Hidden when method +is “Manual Breaks” | +
| Manual Break +Points | +Comma-separated +numbers, e.g., +“10,50,100,500” | +Only visible when +method is “Manual +Breaks” | +
| Computed Breaks +(read-only) | +Shows the computed +break values as a JSON +array | +Always visible (in +“Computed +Classification” +section) | +
Classification method behavior:
+Number of Classes:
+| Action | +Expected Result | +
|---|---|
| Set Number of Classes to 1 | +ValidationError: “Number of classes +must be at least 2” | +
| Set Number of Classes to 11 | +ValidationError: “Number of classes +must not exceed 10” | +
| Set Number of Classes to 5 | +Saves successfully | +
Manual Breaks:
+| Action | +Expected Result | +
|---|---|
| Select “Manual Breaks” but leave +the field empty | +ValidationError: “Manual breaks +are required when using manual +classification” | +
| Enter non-numeric text (e.g., +“a,b,c”) | +ValidationError: “Invalid manual +breaks format” | +
| Enter descending values (e.g., +“100,50,10”) | +ValidationError: “Manual breaks +must be in ascending order” | +
| Enter valid ascending values +(e.g., “10,50,100”) | +Saves successfully; Computed +Breaks shows +[10.0, 50.0, 100.0] | +
This module extends the GIS data layer form to support indicator-based +choropleth visualization. Data layers are configured within GIS view +definitions, not through a standalone menu — they appear as inline +records on the GIS view form.
+To set up: open a GIS data layer form, set Geo Repr to “Choropleth +(Color by Value)”. The “Colors” section hides and the “Choropleth +Configuration” and “Choropleth Settings” sections appear. In the +Choropleth Settings section (added by this module), select an +Indicator Configuration from the dropdown.
+When geo_repr is set to “Choropleth”, two configuration paths are +available:
+| Path | +Source | +When to Use | +
|---|---|---|
| Value Field +(base spp_gis) | +choropleth_field_id +— picks a numeric field +directly from the +layer’s model | +Simple field-based +coloring | +
| Indicator +Configuration +(this module) | +indicator_layer_id +— uses a pre-configured +indicator layer with +CEL variables | +Area-level indicator data +from +spp.hxl.area.indicator | +
Either one satisfies the choropleth validation. Setting both is allowed; +when an Indicator Configuration is set, it takes priority over the Value +Field.
+| Action | +Expected Result | +
|---|---|
| Set Geo Repr to “Choropleth” +with neither Value Field nor +Indicator Configuration | +ValidationError: “Choropleth +layers require a Value Field or +Indicator Configuration.” | +
| Set Geo Repr to “Choropleth” +with only Indicator +Configuration set | +Saves successfully | +
| Set Geo Repr to “Choropleth” +with only Value Field set | +Saves successfully | +
| Set Geo Repr to “Basic” with no +choropleth config | +Saves successfully (no +validation) | +
| Scenario | +Expected Behavior | +
|---|---|
| Indicator layer with no matching +indicator data | +Computed Breaks is empty; Legend +Preview is blank | +
| Indicator layer where all +indicator values are identical | +Equal Interval returns empty +breaks; Quantile returns empty +breaks; Legend shows single +class | +
| Color scale with exactly 2 +colors | +Works correctly; values map to +one of two colors | +
| Manual breaks with a single +value (e.g., “50”) | +Creates 2 classes: “< 50.00” and +“>= 50.00” | +
| Archiving an indicator layer +used by a data layer | +The data layer still references +it but get_feature_colors() +returns no colors for inactive +config | +
| Deleting a color scale used by +an indicator layer | +Standard Odoo referential +integrity behavior (blocked or +cascaded depending on +ondelete) | +
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -466,15 +942,15 @@
Do not contact contributors directly about support or help with technical issues.
This module is part of the OpenSPP/OpenSPP2 project on GitHub.
You are welcome to contribute.