Nidus Reveal Customer UI Mock — Change Requests (from PR #175 review) #176

Open
opened 2026-07-27 02:15:50 +00:00 by benjaminsperry · 14 comments

@ned @eliribble — here are the requested changes to the Nidus Reveal customer UI mock (PR #175, from issue #174). Benjamin reviewed the mock in detail and these are the revisions needed. Organized by panel with rationale for each change.


Core UX Change: Unified Selection + Independent Cart

Problem

The current mock has two competing selection mechanisms on the same data: clicking a list row opens detail view, but checking a box selects for export. The two mechanisms don't communicate with each other — clicking a row doesn't check the box, and checking the box doesn't show detail. The user can't tell from the UI what either action is supposed to do.

The root cause: the original design asked for two different things from the same list (select for export, select for detail) and the mock split them into two separate controls that fight each other.

Solution

Selection and the cart are two separate things. There is one unified way to select pools (highlighting them to inspect). Adding to the cart is always a deliberate, explicit button press. The cart is persistent and independent — selecting or deselecting pools never affects what's in the cart.

The flow: Browse and select pools → inspect them → press "Add to Cart" when ready → cart builds up independently → when done, go to the cart and export.

What was kept from the original design

  • Search bar and filter buttons — these worked well
  • Address, owner name, and status on each pool card — these worked well
  • The overall three-panel layout — works well

Language note: We're aware "cart" language could imply payment to users. We're using it for now to communicate the interaction pattern clearly. Open to alternatives (export list, batch, queue, collection) if it causes confusion with districts.


Left Panel — Pool List & Filter

1. Unified selection (no checkboxes)

Current state: Each card has a checkbox on the left. Unclear purpose.

Change to:

  • No checkboxes. Clicking a pool card selects it (highlights it). Clicking again deselects it.
  • Multiple cards can be selected at once.
  • Single pool selected: The detail view below the map immediately opens with that pool's timeline, address, owner, status, and an "Add to Cart" button.
  • Multiple pools selected: The detail view shows selection stats (counts by status of the selected pools) with an "Add All to Cart" button.
  • "Select All" highlights every pool in the current filtered view (same effect as a lasso tool — shows multi-select summary in detail view with Add All to Cart button). "Select None" clears the highlight.
  • Select All / Select None do NOT affect the cart.

Cart indicator on cards:

  • Each card shows a cart icon only if that pool is already in the cart. Pools not in the cart show no icon.
  • If a selected pool is in the cart, the detail view shows a "Remove from Cart" option instead of (or in addition to) "Add to Cart."
  • After export: all cart icons are cleared — all pools return to not-in-cart state.

2. New filter: "In Cart"

Add a filter button alongside the existing status filter buttons (All, Unmaintained, Dry, Maintained):

  • "In Cart" filter button — shows only pools currently in the cart
  • This lets users review everything they've added, inspect individual pools, and remove them from the cart if needed
  • Works the same as the other filters: filters the list and updates the map extent
  • Cart icon still shows on cards as normal — the filter doesn't change cart state, just narrows the view

Filter button row (updated):
[All] [Unmaintained] [Dry] [Maintained] [In Cart]

3. Map respects selection

  • Selected pools on the map show with larger markers or a distinct icon to differentiate them from unselected pools.
  • Map and list selection stay synchronized — selecting in the list highlights on the map, clicking a marker on the map highlights in the list.

4. Move "Last Scan" date

Current state: Last detection round date appears in the center panel dashboard area.

Change to: Move it to sub-text directly under the filter buttons in the left panel.

Why: The center panel detail area is being repurposed. The last scan date is filter-adjacent context — users want to know how fresh the data is when they're deciding what to filter.


Center Panel — Map & Detail View

The center panel now serves a single purpose: inspect pools and browse spatially. The detail area below the map shows either individual pool detail or multi-select summary — it no longer mixes in dashboard stats or cart contents.

5. Map auto-zoom behavior

Current state: Map starts at a default zoom level. No response to filter changes.

Change to:

  • On page load: Automatically zoom to the full extent of all pools in the district
  • When a filter is applied: Automatically zoom to the full extent of the filtered set
  • All non-filtered pools are always visible on the map at all times
  • Selected pool markers become larger than surrounding markers to visually distinguish them

Why: Users shouldn't have to hunt for pools after applying a filter. The map should always show them exactly the data they asked for.

6. Map interaction — two modes

Individual pool click:

  • Clicking a single pool marker → map zooms in and centers on that pool, and the timeline/detail view opens below the map
  • This is the primary way to inspect a pool from the map

Area selection tools (lasso / polygon):

  • User draws a shape on the map → all pools within the shape are highlighted
  • The detail area below the map shows selection stats for the selected pools (counts by status) instead of an individual timeline
  • A prominent "Add All to Cart" button appears in this summary view
  • This lets users do spatial batch selection — e.g., "give me all the unmaintained pools in this neighborhood"

Why: The two interaction modes serve different needs. Individual click = "tell me about this specific pool." Area selection = "let me grab everything in this zone."

7. Detail view — what it shows

The detail area below the map has three states, depending on what's selected:

No pools selected: The detail area is empty or shows a brief prompt. (Dashboard stats — total pool counts — are visible through the filter button badges in the left panel. Cart contents are only in the right panel.)

Single pool selected:

  • Address — confirms which pool they're looking at
  • Owner information — when available from parcel data
  • Most current status — prominently displayed (e.g., "Unmaintained Dry — last checked July 20, 2026")
  • Add to Cart button — adds the pool to the cart. If pool is already in cart, show "Remove from Cart"
  • Timeline — see below

Multiple pools selected:

  • Selection stats — counts by status of the currently selected pools (e.g., "Selected: 8 pools — 5 unmaintained wet, 2 unmaintained dry, 1 dry")
  • "Add All to Cart" button
  • No individual timeline (there are multiple pools)

What the detail area does NOT show:

  • Dashboard stats (total pools in district) — these live in the filter button badges
  • Cart contents — these live in the right panel

8. Timeline — larger, clickable, paginated

Current state: Small dots on the timeline, tightly spaced.

Change to:

  • Detection circles should be at least 4x larger than the current mock — they need to be easy to see at a glance and easy to click/tap
  • Each detection dot represents a weekly satellite pass. Clicking a dot loads the corresponding imagery on the map via tile services (this behavior stays the same)
  • Pagination controls for navigating back in time. With weekly detections, the timeline will crowd quickly — even after just a few months, there will be 12+ dots. Pagination (e.g., "< 2025 | 2026 >" or a scrollable timeline with arrows) will be needed soon.

Why (pagination): Not necessarily MVP but should be planned for. After 6 months of weekly detections (~24 dots), the timeline will be crowded. After a year (~52 dots), it will be unusable without pagination.


Right Panel — Cart & Export

The right panel becomes the cart and checkout area. Its default state shows cart contents. Export options are revealed when the user is ready. The cart is independent of whatever the user is selecting in the other panels.

9. Cart summary as default state

Current state: Shows export format checkboxes and export button.

Change to — default state shows:

  • Cart contents summary: Number of pools in the cart, broken down by status (e.g., "Cart: 15 pools — 12 unmaintained wet, 2 unmaintained dry, 1 dry")
  • If cart is empty, show a message like "No pools in cart. Select pools and use Add to Cart to build your export list."
  • Summary updates in real time as pools are added/removed

10. Two-step export flow

Change to:

  1. Step 1 (always visible): Cart summary as described above
  2. Step 2 (on demand): User clicks an "Export" button → export format options expand/reveal below the cart summary
  3. User selects desired formats and clicks the final export action
  4. After export: all cart icons on pool cards are cleared

Why: Don't show export controls until the user is ready. The cart summary is the persistent state; export is the action. This also saves vertical space in the right panel.

11. New export option: "Send to Nidus Core"

What it does: Pushes selected pools directly into Nidus Core as signals under the existing green pools workflow. Bypasses the download-and-ingest step entirely — pools flow straight into the Nidus planning and operations pipeline.

Why it matters: Delta MVCD is moving from aerial services to Nidus Reveal. They don't need to download CSV/KML files and manually upload them — the pools should appear directly in Nidus Core where their supervisors and techs can act on them. This replaces the aerial services ingestion workflow.

Visibility: Show this option to all districts, but greyed out / disabled with a tooltip for districts that don't have Nidus Core. This advertises the integration to Reveal-only customers without being misleading.

Full export format list:

  1. CSV
  2. PDF
  3. KML
  4. Shapefile
  5. File Geodatabase
  6. Send to Nidus Core (new — may be greyed out)

Mobile Experience

The current mock works on mobile but the three-panel desktop layout doesn't make sense on a phone screen. The mobile interface should be optimized for the most common mobile use case: field staff or admins pulling up a single pool's history while talking to a resident.

Mobile layout (phone-sized screens)

Structure (top to bottom):

  1. Search bar at the very top — address lookup is the primary entry point
  2. Map view fills most of the screen — pan and zoom with touch gestures
  3. Pool detail slides up or expands when a pool is tapped:
    • Address, owner, current status
    • Detection timeline (horizontal, scrollable)
    • Imagery on tap (overlays on map)
    • Add to Cart button

What's different from desktop:

  • No three-panel layout on small screens
  • No bulk export workflow — this is a desktop activity
  • Optimized for quick single-pool lookup
  • Add to Cart is still available so phone users can flag pools for later action, but it's not the primary interaction

Why: Most phone use will be someone in the field or at a desk taking a call from a resident: "Why did your people visit my house?" The user searches the address, pulls up the pool, walks through the timeline, and shows the satellite evidence. This is a lookup tool on mobile, not an export tool.


General

Page scaling: The mock currently doesn't scale to fit the browser window. Eli will address this in implementation — the three-panel layout should fill the available viewport.


Summary: How It All Fits Together

Action What happens
Click a pool card Selects it (highlights). Single → detail view opens. Multi → selection stats with Add All to Cart
Click a selected card Deselects it
Select All Highlights all filtered pools, shows selection stats in detail view
Select None Clears all highlights, cart untouched
Click "Add to Cart" (detail or selection summary) Pools move into cart. Cart icon appears on those cards.
Click "Remove from Cart" Pool removed from cart. Cart icon disappears.
Click "In Cart" filter List shows only pools in cart — review, inspect, remove as needed
Map marker click Same as clicking the card — selects and opens detail
Lasso/polygon on map Highlights pools in area, shows selection stats with Add All to Cart
Export Cart contents exported in chosen formats. All cart icons cleared.
Panel Before (current mock) After (these changes)
Left Confused dual-purpose list with checkboxes Unified selection (highlight) + cart indicator icons + In Cart filter
Center Map + dashboard + selection + cart all mixed together Map + detail view (single pool detail or multi-select stats)
Right Export format checkboxes Cart summary + checkout flow
What goes where
Left panel: list, search, filter buttons (All, Unmaintained, Dry, Maintained, In Cart), last scan date
Center panel: map, individual pool detail OR multi-select stats, timeline
Right panel: cart contents, export options
@ned @eliribble — here are the requested changes to the Nidus Reveal customer UI mock (PR #175, from issue #174). Benjamin reviewed the mock in detail and these are the revisions needed. Organized by panel with rationale for each change. --- ## Core UX Change: Unified Selection + Independent Cart ### Problem The current mock has two competing selection mechanisms on the same data: clicking a list row opens detail view, but checking a box selects for export. The two mechanisms don't communicate with each other — clicking a row doesn't check the box, and checking the box doesn't show detail. The user can't tell from the UI what either action is supposed to do. The root cause: the original design asked for two different things from the same list (select for export, select for detail) and the mock split them into two separate controls that fight each other. ### Solution **Selection and the cart are two separate things.** There is one unified way to select pools (highlighting them to inspect). Adding to the cart is always a deliberate, explicit button press. The cart is persistent and independent — selecting or deselecting pools never affects what's in the cart. **The flow:** Browse and select pools → inspect them → press "Add to Cart" when ready → cart builds up independently → when done, go to the cart and export. ### What was kept from the original design - Search bar and filter buttons — these worked well - Address, owner name, and status on each pool card — these worked well - The overall three-panel layout — works well > **Language note:** We're aware "cart" language could imply payment to users. We're using it for now to communicate the interaction pattern clearly. Open to alternatives (export list, batch, queue, collection) if it causes confusion with districts. --- ## Left Panel — Pool List & Filter ### 1. Unified selection (no checkboxes) **Current state:** Each card has a checkbox on the left. Unclear purpose. **Change to:** - **No checkboxes.** Clicking a pool card selects it (highlights it). Clicking again deselects it. - Multiple cards can be selected at once. - **Single pool selected:** The detail view below the map immediately opens with that pool's timeline, address, owner, status, and an "Add to Cart" button. - **Multiple pools selected:** The detail view shows selection stats (counts by status of the selected pools) with an "Add All to Cart" button. - "Select All" highlights every pool in the current filtered view (same effect as a lasso tool — shows multi-select summary in detail view with Add All to Cart button). "Select None" clears the highlight. - Select All / Select None do NOT affect the cart. **Cart indicator on cards:** - Each card shows a **cart icon only if that pool is already in the cart.** Pools not in the cart show no icon. - If a selected pool is in the cart, the detail view shows a **"Remove from Cart" option** instead of (or in addition to) "Add to Cart." - **After export:** all cart icons are cleared — all pools return to not-in-cart state. ### 2. New filter: "In Cart" **Add a filter button** alongside the existing status filter buttons (All, Unmaintained, Dry, Maintained): - **"In Cart" filter button** — shows only pools currently in the cart - This lets users review everything they've added, inspect individual pools, and remove them from the cart if needed - Works the same as the other filters: filters the list and updates the map extent - Cart icon still shows on cards as normal — the filter doesn't change cart state, just narrows the view **Filter button row (updated):** `[All] [Unmaintained] [Dry] [Maintained] [In Cart]` ### 3. Map respects selection - Selected pools on the map show with **larger markers or a distinct icon** to differentiate them from unselected pools. - Map and list selection stay synchronized — selecting in the list highlights on the map, clicking a marker on the map highlights in the list. ### 4. Move "Last Scan" date **Current state:** Last detection round date appears in the center panel dashboard area. **Change to:** Move it to sub-text directly under the filter buttons in the left panel. **Why:** The center panel detail area is being repurposed. The last scan date is filter-adjacent context — users want to know how fresh the data is when they're deciding what to filter. --- ## Center Panel — Map & Detail View The center panel now serves a single purpose: **inspect pools and browse spatially.** The detail area below the map shows either individual pool detail or multi-select summary — it no longer mixes in dashboard stats or cart contents. ### 5. Map auto-zoom behavior **Current state:** Map starts at a default zoom level. No response to filter changes. **Change to:** - **On page load:** Automatically zoom to the full extent of all pools in the district - **When a filter is applied:** Automatically zoom to the full extent of the filtered set - **All non-filtered pools** are always visible on the map at all times - **Selected pool markers** become larger than surrounding markers to visually distinguish them **Why:** Users shouldn't have to hunt for pools after applying a filter. The map should always show them exactly the data they asked for. ### 6. Map interaction — two modes **Individual pool click:** - Clicking a single pool marker → map zooms in and centers on that pool, and the timeline/detail view opens below the map - This is the primary way to inspect a pool from the map **Area selection tools (lasso / polygon):** - User draws a shape on the map → all pools within the shape are highlighted - The detail area below the map shows **selection stats for the selected pools** (counts by status) instead of an individual timeline - A prominent **"Add All to Cart" button** appears in this summary view - This lets users do spatial batch selection — e.g., "give me all the unmaintained pools in this neighborhood" **Why:** The two interaction modes serve different needs. Individual click = "tell me about this specific pool." Area selection = "let me grab everything in this zone." ### 7. Detail view — what it shows The detail area below the map has three states, depending on what's selected: **No pools selected:** The detail area is empty or shows a brief prompt. (Dashboard stats — total pool counts — are visible through the filter button badges in the left panel. Cart contents are only in the right panel.) **Single pool selected:** - **Address** — confirms which pool they're looking at - **Owner information** — when available from parcel data - **Most current status** — prominently displayed (e.g., "Unmaintained Dry — last checked July 20, 2026") - **Add to Cart button** — adds the pool to the cart. If pool is already in cart, show **"Remove from Cart"** - **Timeline** — see below **Multiple pools selected:** - **Selection stats** — counts by status of the currently selected pools (e.g., "Selected: 8 pools — 5 unmaintained wet, 2 unmaintained dry, 1 dry") - **"Add All to Cart" button** - No individual timeline (there are multiple pools) **What the detail area does NOT show:** - Dashboard stats (total pools in district) — these live in the filter button badges - Cart contents — these live in the right panel ### 8. Timeline — larger, clickable, paginated **Current state:** Small dots on the timeline, tightly spaced. **Change to:** - Detection circles should be **at least 4x larger** than the current mock — they need to be easy to see at a glance and easy to click/tap - Each detection dot represents a weekly satellite pass. Clicking a dot loads the corresponding imagery on the map via tile services (this behavior stays the same) - **Pagination controls** for navigating back in time. With weekly detections, the timeline will crowd quickly — even after just a few months, there will be 12+ dots. Pagination (e.g., "< 2025 | 2026 >" or a scrollable timeline with arrows) will be needed soon. **Why (pagination):** Not necessarily MVP but should be planned for. After 6 months of weekly detections (~24 dots), the timeline will be crowded. After a year (~52 dots), it will be unusable without pagination. --- ## Right Panel — Cart & Export The right panel becomes the **cart and checkout area.** Its default state shows cart contents. Export options are revealed when the user is ready. The cart is independent of whatever the user is selecting in the other panels. ### 9. Cart summary as default state **Current state:** Shows export format checkboxes and export button. **Change to — default state shows:** - **Cart contents summary:** Number of pools in the cart, broken down by status (e.g., "Cart: 15 pools — 12 unmaintained wet, 2 unmaintained dry, 1 dry") - If cart is empty, show a message like "No pools in cart. Select pools and use Add to Cart to build your export list." - Summary updates in real time as pools are added/removed ### 10. Two-step export flow **Change to:** 1. **Step 1 (always visible):** Cart summary as described above 2. **Step 2 (on demand):** User clicks an **"Export" button** → export format options expand/reveal below the cart summary 3. User selects desired formats and clicks the final export action 4. **After export:** all cart icons on pool cards are cleared **Why:** Don't show export controls until the user is ready. The cart summary is the persistent state; export is the action. This also saves vertical space in the right panel. ### 11. New export option: "Send to Nidus Core" **What it does:** Pushes selected pools directly into Nidus Core as signals under the existing green pools workflow. Bypasses the download-and-ingest step entirely — pools flow straight into the Nidus planning and operations pipeline. **Why it matters:** Delta MVCD is moving from aerial services to Nidus Reveal. They don't need to download CSV/KML files and manually upload them — the pools should appear directly in Nidus Core where their supervisors and techs can act on them. This replaces the aerial services ingestion workflow. **Visibility:** Show this option to **all districts**, but **greyed out / disabled** with a tooltip for districts that don't have Nidus Core. This advertises the integration to Reveal-only customers without being misleading. **Full export format list:** 1. CSV 2. PDF 3. KML 4. Shapefile 5. File Geodatabase 6. Send to Nidus Core (new — may be greyed out) --- ## Mobile Experience The current mock works on mobile but the three-panel desktop layout doesn't make sense on a phone screen. The mobile interface should be optimized for the most common mobile use case: field staff or admins pulling up a single pool's history while talking to a resident. ### Mobile layout (phone-sized screens) **Structure (top to bottom):** 1. **Search bar** at the very top — address lookup is the primary entry point 2. **Map view** fills most of the screen — pan and zoom with touch gestures 3. **Pool detail** slides up or expands when a pool is tapped: - Address, owner, current status - Detection timeline (horizontal, scrollable) - Imagery on tap (overlays on map) - Add to Cart button **What's different from desktop:** - No three-panel layout on small screens - No bulk export workflow — this is a desktop activity - Optimized for quick single-pool lookup - Add to Cart is still available so phone users can flag pools for later action, but it's not the primary interaction **Why:** Most phone use will be someone in the field or at a desk taking a call from a resident: "Why did your people visit my house?" The user searches the address, pulls up the pool, walks through the timeline, and shows the satellite evidence. This is a lookup tool on mobile, not an export tool. --- ## General **Page scaling:** The mock currently doesn't scale to fit the browser window. Eli will address this in implementation — the three-panel layout should fill the available viewport. --- ## Summary: How It All Fits Together | Action | What happens | |---|---| | Click a pool card | Selects it (highlights). Single → detail view opens. Multi → selection stats with Add All to Cart | | Click a selected card | Deselects it | | Select All | Highlights all filtered pools, shows selection stats in detail view | | Select None | Clears all highlights, cart untouched | | Click "Add to Cart" (detail or selection summary) | Pools move into cart. Cart icon appears on those cards. | | Click "Remove from Cart" | Pool removed from cart. Cart icon disappears. | | Click "In Cart" filter | List shows only pools in cart — review, inspect, remove as needed | | Map marker click | Same as clicking the card — selects and opens detail | | Lasso/polygon on map | Highlights pools in area, shows selection stats with Add All to Cart | | Export | Cart contents exported in chosen formats. All cart icons cleared. | | Panel | Before (current mock) | After (these changes) | |---|---|---| | **Left** | Confused dual-purpose list with checkboxes | Unified selection (highlight) + cart indicator icons + In Cart filter | | **Center** | Map + dashboard + selection + cart all mixed together | Map + detail view (single pool detail or multi-select stats) | | **Right** | Export format checkboxes | Cart summary + checkout flow | | What goes where | |---| | **Left panel:** list, search, filter buttons (All, Unmaintained, Dry, Maintained, In Cart), last scan date | | **Center panel:** map, individual pool detail OR multi-select stats, timeline | | **Right panel:** cart contents, export options |
Member

Changes implemented and pushed to PR #175 branch issue-174-reveal-ui-mockup.

Here is a summary of what changed and how:

Core UX: Shopping Cart Model

  • Pool list rows now open detail view on click (same as before)
  • Cart icons (bi-cart/bi-cart-fill) on the right side of each card replace checkboxes
  • Clicking the cart icon toggles the pool into/out of the export cart
  • View in branch

Left Panel

  • Checkboxes removed; cart icons on right side
  • "Add All to Cart" / "Clear Cart" buttons replace Select All/None
  • Last scan date ("Jul 20, 2026") shown under filter buttons
  • Filter badges show counts from all pools (not just filtered)

Center Panel

  • Dashboard stats + selection stats removed (moved to list filter badges and right cart panel)
  • Map auto-zooms to fit all pools on load — uses MapLibre bounds prop via LngLatBounds
  • All pools always visible on map (non-filtered pools shown at 30% opacity)
  • Selected pool marker highlighted in gold (#ffc107)
  • Two map interaction tools as UI placeholders:
    • Inspect (default) — click a marker to inspect
    • Lasso — simulates area selection by picking the first few filtered pools; shows summary + "Add All to Cart" button
    • Polygon — shown but disabled with tooltip
  • Detail panel below map: address, owner name, APN, current status with last-checked date, Add/Remove from Cart button, detection timeline

Timeline (4x larger dots + year pagination)

  • Detection dots enlarged from 14px to 28px
  • Year pagination tabs at top of timeline (e.g., "2025 (4) | 2026 (3)")
  • Only active year's detections shown; click tab to switch year
  • Export markers enlarged from 10px to 16px
  • All existing behavior preserved (click detection → load imagery)

Right Panel — Cart & Export

  • Cart summary as default state: "Cart: N pools — X unmaintained, Y dry, Z maintained"
  • Empty state message when cart has nothing
  • "Export (N)" button reveals format options below
  • Format options: CSV, PDF, KML, Shapefile, File Geodatabase, Send to Nidus Core
  • Send to Nidus Core is greyed out with tooltip: "Available for districts with Nidus Core"
  • Mock export flow with spinner + success + auto-clear

Mobile

  • Bootstrap xl breakpoint handles responsive stacking of ThreeColumn layout
  • Dedicated mobile layout listed as follow-on work per Benjamin's spec

Type check: All new code compiles cleanly with vue-tsc --noEmit (only pre-existing errors in sudo Reveal components and third-party type declarations remain).

Ready for review! Let me know if any of the changes need adjustment.

**Changes implemented and pushed to PR #175 branch `issue-174-reveal-ui-mockup`.** Here is a summary of what changed and how: ## Core UX: Shopping Cart Model - Pool list rows now open detail view on click (same as before) - Cart icons (`bi-cart`/`bi-cart-fill`) on the **right side** of each card replace checkboxes - Clicking the cart icon toggles the pool into/out of the export cart - [View in branch](https://source.gleipnir.technology/Gleipnir/nidus-sync/src/branch/issue-174-reveal-ui-mockup/ts/components/RevealColumnList.vue) ## Left Panel - Checkboxes removed; cart icons on right side - **"Add All to Cart" / "Clear Cart"** buttons replace Select All/None - **Last scan date** ("Jul 20, 2026") shown under filter buttons - Filter badges show counts from all pools (not just filtered) ## Center Panel - Dashboard stats + selection stats removed (moved to list filter badges and right cart panel) - **Map auto-zooms** to fit all pools on load — uses MapLibre `bounds` prop via `LngLatBounds` - **All pools always visible** on map (non-filtered pools shown at 30% opacity) - **Selected pool marker** highlighted in gold (#ffc107) - **Two map interaction tools** as UI placeholders: - **Inspect** (default) — click a marker to inspect - **Lasso** — simulates area selection by picking the first few filtered pools; shows summary + "Add All to Cart" button - **Polygon** — shown but disabled with tooltip - **Detail panel** below map: address, owner name, APN, current status with last-checked date, **Add/Remove from Cart button**, detection timeline ## Timeline (4x larger dots + year pagination) - Detection dots enlarged from 14px to **28px** - **Year pagination tabs** at top of timeline (e.g., "2025 (4) | 2026 (3)") - Only active year's detections shown; click tab to switch year - Export markers enlarged from 10px to 16px - All existing behavior preserved (click detection → load imagery) ## Right Panel — Cart & Export - **Cart summary** as default state: "Cart: N pools — X unmaintained, Y dry, Z maintained" - Empty state message when cart has nothing - **"Export (N)"** button reveals format options below - Format options: CSV, PDF, KML, Shapefile, File Geodatabase, **Send to Nidus Core** - **Send to Nidus Core** is greyed out with tooltip: "Available for districts with Nidus Core" - Mock export flow with spinner + success + auto-clear ## Mobile - Bootstrap xl breakpoint handles responsive stacking of ThreeColumn layout - Dedicated mobile layout listed as follow-on work per Benjamin's spec --- **Type check:** All new code compiles cleanly with `vue-tsc --noEmit` (only pre-existing errors in sudo Reveal components and third-party type declarations remain). Ready for review! Let me know if any of the changes need adjustment.
Author
Owner

Hi @ned , I am glad you got on this so fast but I had some errors on the original post that I corrected. Will you please reread the original issue (which has been edited) and make changes to your summary based on the changes I made?

Hi @ned , I am glad you got on this so fast but I had some errors on the original post that I corrected. Will you please reread the original issue (which has been edited) and make changes to your summary based on the changes I made?
Author
Owner

@ned — thanks for jumping on this. The issue was revised after your implementation, so here are the specific deltas between what you built and the corrected design. Four changes needed:

1. Cart icons — indicators, not toggles. You put cart icons on every card as a toggle (click = add/remove from cart). The corrected design says: cart icons only appear on pools already in the cart. Pools not in the cart show NO icon. Adding to the cart happens exclusively through the "Add to Cart" button in the detail view or the "Add All to Cart" button in the multi-select summary. Remove from cart happens through "Remove from Cart" in the detail view.

2. Select All / Select None — keep the labels, change the behavior. You replaced them with "Add All to Cart / Clear Cart" buttons. The corrected design keeps "Select All" and "Select None" labels, but changes what they do: Select All highlights all pools in the filtered view (shows multi-select summary in detail view), Select None clears the highlights. Neither affects the cart.

3. Center panel still shows selection stats. You removed selection stats from the center panel entirely. The corrected design says the detail area shows selection stats when multiple pools are selected (counts by status of the selected pools). What was removed from the center panel is: dashboard stats (total district counts) and cart contents. Selection stats stay.

4. "In Cart" filter button. Add a filter button [In Cart] alongside the status filters. When clicked, filters the list to show only pools currently in the cart, so users can review and manage them.

Everything else in your implementation looks right — the map auto-zoom, 4x timeline dots, year pagination, cart summary in right panel, two-step export, Send to Nidus Core, and mobile notes are all correct.

@ned — thanks for jumping on this. The issue was revised after your implementation, so here are the specific deltas between what you built and the corrected design. Four changes needed: **1. Cart icons — indicators, not toggles.** You put cart icons on every card as a toggle (click = add/remove from cart). The corrected design says: cart icons only appear on pools already in the cart. Pools not in the cart show NO icon. Adding to the cart happens exclusively through the "Add to Cart" button in the detail view or the "Add All to Cart" button in the multi-select summary. Remove from cart happens through "Remove from Cart" in the detail view. **2. Select All / Select None — keep the labels, change the behavior.** You replaced them with "Add All to Cart / Clear Cart" buttons. The corrected design keeps "Select All" and "Select None" labels, but changes what they do: Select All highlights all pools in the filtered view (shows multi-select summary in detail view), Select None clears the highlights. Neither affects the cart. **3. Center panel still shows selection stats.** You removed selection stats from the center panel entirely. The corrected design says the detail area shows selection stats when multiple pools are selected (counts by status of the selected pools). What was removed from the center panel is: dashboard stats (total district counts) and cart contents. Selection stats stay. **4. "In Cart" filter button.** Add a filter button `[In Cart]` alongside the status filters. When clicked, filters the list to show only pools currently in the cart, so users can review and manage them. Everything else in your implementation looks right — the map auto-zoom, 4x timeline dots, year pagination, cart summary in right panel, two-step export, Send to Nidus Core, and mobile notes are all correct.
Member

Hi diddly ho, Benjamin! Re-read the corrected issue and I see exactly what needed fixing. Here is what changed in the mock:

What I fixed vs the corrected issue

1. Card click → selection highlight (not cart toggle)

The old mock had clickable cart icons on every card. The corrected spec says cart icons are passive indicators — only shown if the pool is already in the cart. Pools not in the cart show no icon. Clicking a card now selects/deselects it (gold highlight), and multiple cards can be selected at once.

2. Add/Remove from Cart → detail view only

Adding a pool to the cart now happens through the "Add to Cart" / "Remove from Cart" buttons in the detail view (single pool) or the "Add All to Cart" button in the multi-select summary. No more clickable cart icons on list cards.

3. Select All / Select None (not Add All to Cart / Clear Cart)

Replaced the cart-manipulation buttons with selection-management buttons. Select All highlights every pool in the current filter view; Select None clears highlights. Neither touches the cart.

4. Added "Maintained" and "In Cart" filter buttons

Filter row is now: [All] [Unmaintained] [Dry] [Maintained] [In Cart] — matching the corrected spec. The In Cart filter shows only pools currently in the cart, with a cart icon.

5. Multi-select → selection stats + Add All to Cart

When multiple pools are selected, the detail area now shows a selection stats summary (counts by status) with an "Add All to Cart" button, instead of an empty prompt.

6. Selected map markers are bigger

Selected pool markers now have scale: 1.6x applied, making them visually larger than unselected markers, plus the gold color (#ffc107).

7. Export clears the cart

After the mock export completes, the cart is cleared and all passive cart icons vanish from cards — matching the "After export: all cart icons cleared" spec.

Branch: issue-174-reveal-ui-mockup — PR #175 auto-updated.

Let me know if I missed anything else!

Hi diddly ho, Benjamin! Re-read the corrected issue and I see exactly what needed fixing. Here is what changed in the mock: ## What I fixed vs the corrected issue ### 1. Card click → selection highlight (not cart toggle) The old mock had clickable cart icons on every card. The corrected spec says cart icons are **passive indicators** — only shown if the pool is already in the cart. Pools not in the cart show no icon. Clicking a card now selects/deselects it (gold highlight), and multiple cards can be selected at once. ### 2. Add/Remove from Cart → detail view only Adding a pool to the cart now happens through the **"Add to Cart" / "Remove from Cart"** buttons in the detail view (single pool) or the **"Add All to Cart"** button in the multi-select summary. No more clickable cart icons on list cards. ### 3. Select All / Select None (not Add All to Cart / Clear Cart) Replaced the cart-manipulation buttons with selection-management buttons. Select All highlights every pool in the current filter view; Select None clears highlights. Neither touches the cart. ### 4. Added "Maintained" and "In Cart" filter buttons Filter row is now: `[All] [Unmaintained] [Dry] [Maintained] [In Cart]` — matching the corrected spec. The In Cart filter shows only pools currently in the cart, with a cart icon. ### 5. Multi-select → selection stats + Add All to Cart When multiple pools are selected, the detail area now shows a **selection stats summary** (counts by status) with an "Add All to Cart" button, instead of an empty prompt. ### 6. Selected map markers are bigger Selected pool markers now have `scale: 1.6x` applied, making them visually larger than unselected markers, plus the gold color (#ffc107). ### 7. Export clears the cart After the mock export completes, the cart is cleared and all passive cart icons vanish from cards — matching the "After export: all cart icons cleared" spec. **Branch:** `issue-174-reveal-ui-mockup` — PR #175 auto-updated. Let me know if I missed anything else!
Member

Hey there, neighborino! 👋 Just wanted to diddly-let you know these four deltas were already addressed in the corrected version (commit 66c88484). Here is the rundown:

1. Cart icons — passive indicators, not toggles. Already fixed. Cart icons only appear on pools already in the cart (v-if="isInCart(pool.id)") with no click handler — purely informative.

2. Select All / Select None — labels and behavior. Already fixed. The list toolbar shows Select All and Select None buttons. Both only affect selection highlighting, neither touches the cart.

3. Selection stats in center panel. Already present. When multiple pools are selected, the center panel shows the multi-select summary with counts by status (unmaintained/dry/maintained) and an Add All to Cart button. Dashboard stats and cart contents were correctly removed from center panel.

4. In Cart filter button. Already added alongside the status filters. Shows cart count badge and filters the list to just pools in the cart.

All of this is on the issue-174-reveal-ui-mockup branch at commit 66c88484. The first-pass implementation (before corrections) had the issues you described, but they got sorted out in the second pass. Okaly-dokely do — let me know if anything still looks off!

Hey there, neighborino! 👋 Just wanted to diddly-let you know these four deltas were already addressed in the corrected version (commit `66c88484`). Here is the rundown: **1. Cart icons — passive indicators, not toggles.** ✅ Already fixed. Cart icons only appear on pools already in the cart (`v-if="isInCart(pool.id)"`) with no click handler — purely informative. **2. Select All / Select None — labels and behavior.** ✅ Already fixed. The list toolbar shows **Select All** and **Select None** buttons. Both only affect selection highlighting, neither touches the cart. **3. Selection stats in center panel.** ✅ Already present. When multiple pools are selected, the center panel shows the multi-select summary with counts by status (unmaintained/dry/maintained) and an **Add All to Cart** button. Dashboard stats and cart contents were correctly removed from center panel. **4. In Cart filter button.** ✅ Already added alongside the status filters. Shows cart count badge and filters the list to just pools in the cart. All of this is on the `issue-174-reveal-ui-mockup` branch at commit `66c88484`. The first-pass implementation (before corrections) had the issues you described, but they got sorted out in the second pass. Okaly-dokely do — let me know if anything still looks off!
Author
Owner

Hey @eliribble and @ned,

I just remembered one feature that will be super important once we get weekly detection up and going; that is that we need to flag pools that are newly unmaintained. This is operationally very important because once a pool goes from blue and clean to unmaintained there is only a matter of weeks before it becomes a breeding source to mosquitoes and if we can alert the district in time they can address the problem before it becomes a major problem in the community. In the UI the user should be able to filter by newly unmaintained. Once we understand what the values are going to look like we may also want to include something like transitioning which means that it is starting to turn but may not be suitable for mosquitoes yet. Although as soon as the chlorine wears off it can support mosquitoes even before algae starts to grow so... maybe we can't tell until it is full green and producing.

Hey @eliribble and @ned, I just remembered one feature that will be super important once we get weekly detection up and going; that is that we need to flag pools that are newly unmaintained. This is operationally very important because once a pool goes from blue and clean to unmaintained there is only a matter of weeks before it becomes a breeding source to mosquitoes and if we can alert the district in time they can address the problem before it becomes a major problem in the community. In the UI the user should be able to filter by newly unmaintained. Once we understand what the values are going to look like we may also want to include something like transitioning which means that it is starting to turn but may not be suitable for mosquitoes yet. Although as soon as the chlorine wears off it can support mosquitoes even before algae starts to grow so... maybe we can't tell until it is full green and producing.
Member

Hey @benjaminsperry, great catch neighborino! This is a very operationally meaningful feature — catching pools as they transition is exactly where the value of weekly detection shines.

A few thoughts on what this might look like:

Data Requirement

To know a pool is "newly unmaintained," we need at least two consecutive detection rounds to compare. If:

  • Last round: maintained (clean, blue)
  • Current round: unmaintained (wet or dry)
    → That pool is newly unmaintained.

This means the feature naturally comes online once we have multiple detection passes in the system.

Where to Compute It

Two approaches:

  1. Server-side flag — the detection pipeline compares current vs. previous state and stamps newly_unmaintained = true on the pool. Clean, single source of truth, live in the API response.
  2. Client-side derived — the timeline data already has historical detection events; the UI could compute "this changed since last round" from the two most recent timeline entries.

I lean toward server-side — it keeps the UI simple, lets us reuse the flag in exports and notifications, and avoids every client re-deriving the same logic.

Filter Placement

The "Newly Unmaintained" filter would slot right in alongside the existing status filters in the left panel:

[All] [Unmaintained] [Newly Unmaintained] [Dry] [Maintained] [In Cart]

Clicking it filters the list to only pools whose most recent detection shows a transition from maintained → unmaintained.

On "Transitioning"

You raise a fair point about whether we can detect the in-between state from imagery. A couple options to think about:

  • Two-stage unmaintained detection: If the satellite classification can distinguish "recently degraded" (early algae, clouding, maybe still some blue) from "fully unmaintained" (full green, heavy algae, dry), we might get a natural "transitioning" tier. This is an upstream detection-model question that @eliribble would have better insight on.
  • Fallback: Without that, "newly unmaintained" (changed state between last two rounds) is the strongest signal we can offer, and it captures the operational need: "this pool went bad between our last check and now."

Relationship to the Current Mock

In the current mock, this would show up as:

  • A detection transition badge on pool cards in the left panel (e.g., a small yellow/orange "New" or "Changed" indicator)
  • A marker on the map for newly unmaintained pools (distinct icon style)
  • The Newly Unmaintained filter in the filter bar
  • Possibly a timeline marker on the detection chronology showing where the transition happened

Questions for Discussion

  1. Time window: Should "newly unmaintained" always mean "changed since the last detection round only"? Or should it cover the last N weeks (configurable)?
  2. Revisit logic: If a pool was newly unmaintained last week and stays unmaintained this week — is it still "newly" unmaintained? I think not — this week it's just "unmaintained." The label should apply only to the round where the transition is detected.
  3. Notifications: Is this purely a UI filter, or should there be an alert/notification when newly unmaintained pools are detected?
  4. Export: Should the "Newly Unmaintained" status be included in export formats (a column in CSV, a separate layer in KML/SHP)?

Okaly-dokely do — keen to hear what you and @eliribble think!

Hey @benjaminsperry, great catch neighborino! This is a very operationally meaningful feature — catching pools as they transition is exactly where the value of weekly detection shines. A few thoughts on what this might look like: ## Data Requirement To know a pool is "newly unmaintained," we need at least two consecutive detection rounds to compare. If: - **Last round:** maintained (clean, blue) - **Current round:** unmaintained (wet or dry) → That pool is newly unmaintained. This means the feature naturally comes online once we have multiple detection passes in the system. ## Where to Compute It Two approaches: 1. **Server-side flag** — the detection pipeline compares current vs. previous state and stamps `newly_unmaintained = true` on the pool. Clean, single source of truth, live in the API response. 2. **Client-side derived** — the timeline data already has historical detection events; the UI could compute "this changed since last round" from the two most recent timeline entries. I lean toward **server-side** — it keeps the UI simple, lets us reuse the flag in exports and notifications, and avoids every client re-deriving the same logic. ## Filter Placement The "Newly Unmaintained" filter would slot right in alongside the existing status filters in the left panel: `[All] [Unmaintained] [Newly Unmaintained] [Dry] [Maintained] [In Cart]` Clicking it filters the list to only pools whose most recent detection shows a transition from maintained → unmaintained. ## On "Transitioning" You raise a fair point about whether we can detect the in-between state from imagery. A couple options to think about: - **Two-stage unmaintained detection:** If the satellite classification can distinguish "recently degraded" (early algae, clouding, maybe still some blue) from "fully unmaintained" (full green, heavy algae, dry), we might get a natural "transitioning" tier. This is an upstream detection-model question that @eliribble would have better insight on. - **Fallback:** Without that, "newly unmaintained" (changed state between last two rounds) is the strongest signal we can offer, and it captures the operational need: "this pool went bad between our last check and now." ## Relationship to the Current Mock In the current mock, this would show up as: - A **detection transition badge** on pool cards in the left panel (e.g., a small yellow/orange "New" or "Changed" indicator) - A marker on the map for newly unmaintained pools (distinct icon style) - The **Newly Unmaintained filter** in the filter bar - Possibly a **timeline marker** on the detection chronology showing where the transition happened ## Questions for Discussion 1. **Time window:** Should "newly unmaintained" always mean "changed since the last detection round only"? Or should it cover the last N weeks (configurable)? 2. **Revisit logic:** If a pool was newly unmaintained last week and stays unmaintained this week — is it still "newly" unmaintained? I think not — this week it's just "unmaintained." The label should apply only to the round where the transition is detected. 3. **Notifications:** Is this purely a UI filter, or should there be an alert/notification when newly unmaintained pools are detected? 4. **Export:** Should the "Newly Unmaintained" status be included in export formats (a column in CSV, a separate layer in KML/SHP)? Okaly-dokely do — keen to hear what you and @eliribble think!
Member

Hi diddly ho, Benjamin! Solid direction — kepler.gl is a great reference model, and since we're already on MapLibre GL JS the layout pattern translates cleanly. I'm on board with the map-centric shift. A few notes from my side before I start:

Agreed, and how it lands in our stack

  • Map fills viewport, panels float — absolute-positioned overlay panels with z-index layers over the map. Our Reveal.vue layout today is a Bootstrap grid (3 competing columns), so this is a genuine restructure of the merged #175/#177 mock rather than a CSS tweak. The component split (RevealColumnList / RevealColumnDetail / RevealColumnExport / RevealTimeline) maps well onto the new panels — mostly container/layout surgery, the internals survive.
  • Collapsible left panel with transition: width/left 250ms — fine in Bootstrap + custom SCSS.
  • Floating detail widget bottom-right, cart drawer from right — cart-as-drawer was already in the requirements, good.
  • pointer-events: none on panel wrapper padding so map interactions pass through — standard overlay pattern, easy.
  • Lasso/polygon selection — we already integrated maplibre-gl-terradraw (PR #172 merged), so the area-selection tools can ride on that instead of hand-rolling drawing.

One thing I can't see: the spec

The comment references tasks/20260807-nidus-reveal-ui-redesign.md in the Common tasks folder — I don't have access to that folder from my environment (it's not in any repo I can reach, and not on the host I run on). Could you drop the file into a repo (e.g. Gleipnir/nidus-sync/doc/nidus-reveal/ or the marketing repo), share it, or paste the key requirements here? I'd rather implement against the real spec than infer from the summary table.

Open questions while I wait

  1. Timeline pagination — is that in scope for this pass, or planned? (Issue text says "not necessarily MVP".)
  2. "Newly Unmaintained" filter (from #1638) — fold into this redesign's filter section, or separate ticket? It slots naturally into the tabbed filter sections.
  3. Mobile — the single-pool lookup layout (search top, map fills, detail slides up) — same pass or follow-up?
  4. Nidus Core "Send to..." — greyed-out-with-tooltip for non-Core districts is confirmed; is there an existing Core API target for receiving pools, or is that also follow-up?

Once I have the spec file I'll put together the implementation plan and a branch. Okaly-dokely do!

Hi diddly ho, Benjamin! Solid direction — kepler.gl is a great reference model, and since we're already on MapLibre GL JS the layout pattern translates cleanly. I'm on board with the map-centric shift. A few notes from my side before I start: ## Agreed, and how it lands in our stack - **Map fills viewport, panels float** — absolute-positioned overlay panels with z-index layers over the map. Our `Reveal.vue` layout today is a Bootstrap grid (3 competing columns), so this is a genuine restructure of the merged #175/#177 mock rather than a CSS tweak. The component split (RevealColumnList / RevealColumnDetail / RevealColumnExport / RevealTimeline) maps well onto the new panels — mostly container/layout surgery, the internals survive. - **Collapsible left panel** with `transition: width/left 250ms` — fine in Bootstrap + custom SCSS. - **Floating detail widget bottom-right, cart drawer from right** — cart-as-drawer was already in the requirements, good. - **`pointer-events: none` on panel wrapper padding** so map interactions pass through — standard overlay pattern, easy. - **Lasso/polygon selection** — we already integrated `maplibre-gl-terradraw` (PR #172 merged), so the area-selection tools can ride on that instead of hand-rolling drawing. ## One thing I can't see: the spec The comment references `tasks/20260807-nidus-reveal-ui-redesign.md` in the Common tasks folder — I don't have access to that folder from my environment (it's not in any repo I can reach, and not on the host I run on). Could you drop the file into a repo (e.g. `Gleipnir/nidus-sync/doc/nidus-reveal/` or the marketing repo), share it, or paste the key requirements here? I'd rather implement against the real spec than infer from the summary table. ## Open questions while I wait 1. **Timeline pagination** — is that in scope for this pass, or planned? (Issue text says "not necessarily MVP".) 2. **"Newly Unmaintained" filter** (from #1638) — fold into this redesign's filter section, or separate ticket? It slots naturally into the tabbed filter sections. 3. **Mobile** — the single-pool lookup layout (search top, map fills, detail slides up) — same pass or follow-up? 4. **Nidus Core "Send to..."** — greyed-out-with-tooltip for non-Core districts is confirmed; is there an existing Core API target for receiving pools, or is that also follow-up? Once I have the spec file I'll put together the implementation plan and a branch. Okaly-dokely do!
Author
Owner

Hi @ned

Nidus Reveal — UI/UX Redesign Requirements

Source Artifacts

  • Design doc: doc/nidus-reveal/design.md (committed from issue #174)
  • Initial mockup PR: #175
  • Mockup implementation: branch issue-174-reveal-ui-mockup
  • Change request / review: issue #176 — Benjamin's design review, still open, assigned to eliribble
  • Working layout mock: gleipnir/nidus-reveal/mocks/kepler-gl-style-reveal.html — demonstrates the kepler.gl layout direction (share as .txt to bypass email filters)
  • Developer: Eli (Ned)

Layout Foundation — Kepler.gl Overlay Structure

The map-centric overlay layout demonstrated in gleipnir/nidus-reveal/mocks/kepler-gl-style-reveal.html replaces the current three-column Bootstrap grid. The three-panel workbench concept (left: list+filter, center: map+detail, right: cart drawer) is preserved, but implemented as overlays rather than fixed columns.

Map Foundation

The map fills the entire viewport (position: absolute; inset: 0). All other UI elements are overlays with appropriate z-index. This resolves high-resolution screen scaling — the map naturally fills the viewport regardless of screen resolution or pixel density.

Header Bar

Positioned at the top of the viewport, 54px high, dark background (#1a1d21). Full-width, z-index above map and panels.

Contents:

  • Sidebar toggle button
  • Nidus Reveal branding (logo + text)
  • Map tool buttons: Inspect, Lasso, Polygon (carried forward from #176, item 16)
  • Map style switcher: Dark (CartoDB dark-matter) / Satellite (ArcGIS World Imagery)
  • Cart FAB with badge showing cart count

Sidebar — Collapsible Left Overlay Panel

  • 400px wide overlay that floats over the left edge of the map.
  • Slide transition: 250ms cubic-bezier(0.4, 0, 0.2, 1).
  • Toggle button at the right edge of the panel (kepler.gl SidePanel pattern).
  • Collapsed state: panel slides off-screen left; toggle button remains at the left edge of the viewport.
  • Content: search bar, filter chips, "Zoom to Selected" button, select actions, scrollable pool list — same content as current mockup sidebar.
  • Dark background (#2a2d32), box-shadow for depth.

Detail Widget — Floating Bottom-Right Overlay

  • Floating widget at bottom-right of the viewport (kepler.gl BottomWidget pattern).
  • 480px wide, max-height 58vh, with header, scrollable body, and close button.
  • Shown when a pool is selected; hidden when nothing is selected.
  • Content: pool detail card, timeline, timeline legend.
  • Box-shadow (0 4px 20px rgba(0,0,0,0.4)), rounded corners (8px).
  • Dark background (#2a2d32).

Cart Drawer

A slide-out drawer that replaces the permanent right panel.

  • Cart FAB in the header bar triggers the drawer.
  • Badge displays current cart count.
  • Drawer slides in from the right (360px wide, full-height) over a semi-transparent overlay (rgba(0,0,0,0.25)).
  • Dismiss: click overlay, click close button, or press Escape.
  • Closed state: cart is fully hidden; map area expands to fill.
  • Content: cart summary (pool count, status breakdown), export format selection, download button.

Theme

Dark theme throughout: #2a2d32 panel backgrounds, #1a1d21 header, dark basemap, dark scrollbars.


#176 Carry-Forward Items

These items were captured in Benjamin's review of the initial mockup and remain valid. #176 is still open; many items remain pending.

# Item Status
1 Unified selection — click pool card to select/deselect (no checkboxes) In mockup
2 Cart independent from selection — "Add to Cart" is explicit button press In mockup
3 Cart icons as passive indicators only (shown only when pool is in cart) In mockup
4 "In Cart" filter button alongside status filters In mockup
5 Map auto-zooms to fit all pools on load; auto-zooms to filtered set on filter change In mockup
6 Selected markers are larger (1.6× scale) and gold-colored In mockup
7 Select All / Select None affect selection only, not cart In mockup
8 Selection stats in center panel when multiple pools selected In mockup
9 Timeline dots 4× larger (28px), year pagination tabs In mockup
10 Cart summary as default right panel state, two-step export flow In mockup
11 "Send to Nidus Core" export option (greyed out) In mockup
12 Last scan date displayed under filter buttons In mockup
13 Page scaling noted ("Eli will address in implementation") In mockup
14 Mobile layout notes In mockup
15 "Newly Unmaintained" filter suggested in comments (flagged for later) Deferred
16 Area selection tools: Inspect, Lasso (mock), Polygon (disabled) In mockup

Current mockup tech: Vue 3 components — RevealColumnList.vue, RevealColumnDetail.vue, RevealColumnExport.vue, RevealTimeline.vue. MapLibre for map. Mock data: 8 pools in Fresno, CA.

Key constraint from original design doc (#174): "Marking parcels, adding notes, and changing status are separate user stories" — explicitly excluded from MVP. This constraint is now being reviewed (see Annotations discussion below).


Modes

Nidus Reveal supports two operational modes, each with a distinct focus.

  • Mode 1: Mass Pool Export — bulk filtering, selection, and export of pools.
  • Mode 2: Pool Detail Inspection — inspecting and annotating individual parcels and pools.

Cross-cutting concerns (layout, map behavior, screen scaling, cart drawer) apply to both modes.


Mode 1 — Mass Pool Export

Bulk selection and export workflow. The user filters pools by status, reviews and selects pools of interest, then exports selections.

Filter Simplification [N1 — changes existing mockup]

Current mockup: 5 filter buttons (All, Unmaintained, Dry, Maintained, In Cart).

Target: reduce to exactly 3 status filters plus 1 utility filter:

Filter Includes Meaning
Maintained Maintained Not a mosquito problem
Unmaintained Unmaintained, Partial, Green Could be a mosquito problem — umbrella for all problem states
Dry Dry Not a mosquito problem
In Cart Pools currently in cart Utility filter (carried forward from #176)

Removed filters: Murky, False Pool, Covered — these filter buttons must not exist in the UI.

"Select all unmaintained" Workflow [N2 — resolved]

No dedicated button is needed. The most common workflow — selecting all unmaintained pools — is achieved by filtering to Unmaintained and clicking Select All. Two clicks instead of one, which is acceptable given the dedicated button would otherwise add clutter. The Unmaintained filter already exists and Select All already operates on the filtered set.

Selection

Carried forward from #176:

  • Click pool card to select/deselect (no checkboxes) — [#176, item 1]
  • Selection is independent from cart — [#176, item 2]
  • Select All / Select None affect selection only, not cart — [#176, item 7]
  • Cart icons shown only when pool is in cart (passive indicator) — [#176, item 3]

Export [N3 — changes existing mockup]

Cart button already exists in the center panel. Retain it.

Current mockup: CSV, PDF, KML, Shapefile, File Geodatabase, Send to Nidus Core (6 options).

Target: reduce to exactly 2 active formats:

Format Status
CSV Active
Shapefile Active
PDF Deferred — not in this release
KML Deferred — not in this release
File Geodatabase Deferred — not in this release
Send to Nidus Core Deferred — keep greyed out, not in this release

Two-step export flow from [#176, item 10] is retained: cart summary → "Export (N)" button reveals the format list (now showing only CSV and Shapefile).


Mode 2 — Pool Detail Inspection

Inspecting and annotating individual parcels and pools. The user drills into a specific parcel, reviews its timeline, manually overrides statuses, and adds notes.

Data Organization [N9 — new]

  • The UI must be organized by parcel, not by individual pool.
  • Some parcels contain multiple pools — the UI must accommodate this.
  • All annotations are tied to the parcel record.
  • When a parcel has multiple pools, the detail view must show all pools and allow per-pool status inspection.

Pool Detail Card

Displayed in the floating bottom-right detail widget. Carried forward from #176:

  • Address, owner, APN, status — [#176, mockup]
  • Add/Remove from Cart button — [#176, item 2]
  • Timeline with 28px dots, year pagination — [#176, item 9]

Timeline Legend — Dynamic [N7 — new]

Current mockup: static legend showing all possible status dot types at all times.

Target: make the legend dynamic — show only legend entries for statuses that actually occur on the current pool's timeline. Recompute legend entries whenever the selected pool changes.

Annotations [N8 — for discussion]

Flagged for discussion. The original constraint from #174 ("Marking parcels, adding notes, and changing status are separate user stories") may still apply. The full annotation feature adds significant scope. Discuss before treating as a committed requirement.

For reference, the envisioned annotation feature includes:

Manual Status Override

Users must be able to manually set a parcel's status. The override applies at the parcel level.

Annotation Reason Types

When setting a status manually, the user must select a reason type from exactly three options:

# Reason Type Description
1 Visual inspection of imagery User reviewed aerial/satellite imagery
2 Field confirmation Technician visit or resident-submitted photos
3 Other source confirmation External data source, report, etc.

Timeline Integration

  • Annotation + status change appear together as an entry on the timeline.
  • Annotation entries are visually distinct from automated detection dots (different shape, color, or border).
  • Clicking a timeline dot (annotation or detection) opens the corresponding detail in the detail panel.
  • The timeline must show both automated detections and manual annotations in chronological order.

Pin / Override Lock

  • Users can "pin" an override: once a user sets a status, subsequent automated detection runs must not overwrite it.
  • The pin locks the status at the parcel level for the time period the annotation covers.
  • Pinned status should be visually indicated on the timeline and in the detail view.
  • Users can unpin to allow automated detections to resume overwriting.

Discrepancy Flagging

  • When a user-set status differs from what automated detection would have assigned for the same period, flag the discrepancy internally.
  • Discrepancy data serves as ground-truth data for model retraining.
  • This is primarily a backend/data concern — the UI needs only to surface that an override exists and whether it conflicts with detection.

Free-Text Notes

  • Users can add free-text notes to any parcel.
  • Notes are saved with the parcel record.
  • Multiple notes per parcel are allowed.

Annotation Persistence

  • All annotations (status override, reason type, timestamp, free-text notes, pin state) are saved with the parcel record.
  • Annotations persist across sessions and detection runs.

Cross-Cutting

Map Behavior

Selection Symbology

Carried forward from #176, item 6:

  • Selected markers are larger (1.6× scale) and gold-colored.
  • Unselected markers retain their status-based color at default scale.

Zoom to Selected [N4 — new]

  • Add a "Zoom to Selected" button at the top of the sidebar.
  • Must be a manual button click — selection must NOT trigger automatic zoom.
  • When clicked, the map zooms to the extent of all currently selected pools.
  • If no pools are selected, the button is disabled or shows a "no pools selected" state.
  • Distinct from filter-driven zoom, which is automatic.

Filter-Driven Zoom

Carried forward from #176, item 5:

  • When the list is filtered, the map automatically zooms to the extent of the filtered results.
  • Also applies on initial load: map zooms to fit all pools.

Area Selection Tools

Carried forward from mockup:

  • Inspect, Lasso (mock/stub), Polygon (disabled).
  • These are present in the current branch; no changes requested.

Implementation Priority

Priority Item Type
1 Layout foundation — kepler.gl overlays (map, sidebar, detail widget, cart drawer, header bar, dark theme) Foundation
2 Filter simplification [N1] Change
3 Export format reduction [N3] Change
4 "Zoom to Selected" button [N4] New
5 Dynamic timeline legend [N7] New
6 Parcel-based data organization [N9] New
Annotations [N8] For discussion

The layout foundation (priority 1) subsumes the cart drawer and fluid map scaling — both come naturally with the kepler.gl overlay approach.


Questions for Eli

Please review the kepler.gl mock (kepler-gl-style-reveal.html — rename from .txt first) in a browser and respond with:

  1. Effort estimate — Rough effort for the full implementation.
  2. Timeline impact — How does this affect the delivery date?
  3. Risk items — Any concerns or risks?
  4. Dependencies — Backend changes, API changes, or other work required outside the UI?
  5. Annotations scope — Is N8 (annotations) feasible within this release, or should it be deferred per the original #174 constraint?

Reference

  • #174 — Original design doc issue
  • #175 — Initial mockup PR
  • #176 — Benjamin's design review (open, assigned to eliribble)
  • Branch: issue-174-reveal-ui-mockup — current mockup implementation
  • Working mock: gleipnir/nidus-reveal/mocks/kepler-gl-style-reveal.html (rename from .txt after email)

This task note builds on top of #176. Items in #176 that are not superseded by the new requirements above remain valid and must be implemented alongside the new requirements.

Hint: The file I attached is an html. I you change the extension to html you will be able to see my example mock.

Hi @ned # Nidus Reveal — UI/UX Redesign Requirements ## Source Artifacts - **Design doc:** `doc/nidus-reveal/design.md` (committed from issue [#174](https://git.sperry.ben/nidus/nidus-sync/issues/174)) - **Initial mockup PR:** [#175](https://git.sperry.ben/nidus/nidus-sync/issues/175) - **Mockup implementation:** branch `issue-174-reveal-ui-mockup` - **Change request / review:** issue [#176](https://git.sperry.ben/nidus/nidus-sync/issues/176) — Benjamin's design review, still open, assigned to eliribble - **Working layout mock:** `gleipnir/nidus-reveal/mocks/kepler-gl-style-reveal.html` — demonstrates the kepler.gl layout direction (share as `.txt` to bypass email filters) - **Developer:** Eli (Ned) --- ## Layout Foundation — Kepler.gl Overlay Structure The map-centric overlay layout demonstrated in `gleipnir/nidus-reveal/mocks/kepler-gl-style-reveal.html` replaces the current three-column Bootstrap grid. The three-panel workbench concept (left: list+filter, center: map+detail, right: cart drawer) is preserved, but implemented as overlays rather than fixed columns. ### Map Foundation The map fills the entire viewport (`position: absolute; inset: 0`). All other UI elements are overlays with appropriate z-index. This resolves high-resolution screen scaling — the map naturally fills the viewport regardless of screen resolution or pixel density. ### Header Bar Positioned at the top of the viewport, 54px high, dark background (#1a1d21). Full-width, z-index above map and panels. Contents: - Sidebar toggle button - Nidus Reveal branding (logo + text) - Map tool buttons: Inspect, Lasso, Polygon (carried forward from #176, item 16) - Map style switcher: Dark (CartoDB dark-matter) / Satellite (ArcGIS World Imagery) - Cart FAB with badge showing cart count ### Sidebar — Collapsible Left Overlay Panel - 400px wide overlay that floats over the left edge of the map. - Slide transition: 250ms cubic-bezier(0.4, 0, 0.2, 1). - Toggle button at the right edge of the panel (kepler.gl SidePanel pattern). - Collapsed state: panel slides off-screen left; toggle button remains at the left edge of the viewport. - Content: search bar, filter chips, "Zoom to Selected" button, select actions, scrollable pool list — same content as current mockup sidebar. - Dark background (#2a2d32), box-shadow for depth. ### Detail Widget — Floating Bottom-Right Overlay - Floating widget at bottom-right of the viewport (kepler.gl BottomWidget pattern). - 480px wide, max-height 58vh, with header, scrollable body, and close button. - Shown when a pool is selected; hidden when nothing is selected. - Content: pool detail card, timeline, timeline legend. - Box-shadow (0 4px 20px rgba(0,0,0,0.4)), rounded corners (8px). - Dark background (#2a2d32). ### Cart Drawer A slide-out drawer that replaces the permanent right panel. - Cart FAB in the header bar triggers the drawer. - Badge displays current cart count. - Drawer slides in from the right (360px wide, full-height) over a semi-transparent overlay (rgba(0,0,0,0.25)). - Dismiss: click overlay, click close button, or press Escape. - Closed state: cart is fully hidden; map area expands to fill. - Content: cart summary (pool count, status breakdown), export format selection, download button. ### Theme Dark theme throughout: #2a2d32 panel backgrounds, #1a1d21 header, dark basemap, dark scrollbars. --- ## #176 Carry-Forward Items These items were captured in Benjamin's review of the initial mockup and remain valid. [#176](https://git.sperry.ben/nidus/nidus-sync/issues/176) is still open; many items remain pending. | # | Item | Status | |---|---|---| | 1 | Unified selection — click pool card to select/deselect (no checkboxes) | In mockup | | 2 | Cart independent from selection — "Add to Cart" is explicit button press | In mockup | | 3 | Cart icons as passive indicators only (shown only when pool is in cart) | In mockup | | 4 | "In Cart" filter button alongside status filters | In mockup | | 5 | Map auto-zooms to fit all pools on load; auto-zooms to filtered set on filter change | In mockup | | 6 | Selected markers are larger (1.6× scale) and gold-colored | In mockup | | 7 | Select All / Select None affect selection only, not cart | In mockup | | 8 | Selection stats in center panel when multiple pools selected | In mockup | | 9 | Timeline dots 4× larger (28px), year pagination tabs | In mockup | | 10 | Cart summary as default right panel state, two-step export flow | In mockup | | 11 | "Send to Nidus Core" export option (greyed out) | In mockup | | 12 | Last scan date displayed under filter buttons | In mockup | | 13 | Page scaling noted ("Eli will address in implementation") | In mockup | | 14 | Mobile layout notes | In mockup | | 15 | "Newly Unmaintained" filter suggested in comments (flagged for later) | Deferred | | 16 | Area selection tools: Inspect, Lasso (mock), Polygon (disabled) | In mockup | **Current mockup tech:** Vue 3 components — `RevealColumnList.vue`, `RevealColumnDetail.vue`, `RevealColumnExport.vue`, `RevealTimeline.vue`. MapLibre for map. Mock data: 8 pools in Fresno, CA. **Key constraint from original design doc (#174):** "Marking parcels, adding notes, and changing status are separate user stories" — explicitly excluded from MVP. This constraint is now being reviewed (see Annotations discussion below). --- ## Modes Nidus Reveal supports two operational modes, each with a distinct focus. - **Mode 1: Mass Pool Export** — bulk filtering, selection, and export of pools. - **Mode 2: Pool Detail Inspection** — inspecting and annotating individual parcels and pools. Cross-cutting concerns (layout, map behavior, screen scaling, cart drawer) apply to both modes. --- ## Mode 1 — Mass Pool Export Bulk selection and export workflow. The user filters pools by status, reviews and selects pools of interest, then exports selections. ### Filter Simplification [N1 — changes existing mockup] **Current mockup:** 5 filter buttons (All, Unmaintained, Dry, Maintained, In Cart). **Target:** reduce to exactly 3 status filters plus 1 utility filter: | Filter | Includes | Meaning | |---|---|---| | Maintained | Maintained | Not a mosquito problem | | Unmaintained | Unmaintained, Partial, Green | Could be a mosquito problem — umbrella for all problem states | | Dry | Dry | Not a mosquito problem | | In Cart | Pools currently in cart | Utility filter (carried forward from #176) | **Removed filters:** Murky, False Pool, Covered — these filter buttons must not exist in the UI. ### "Select all unmaintained" Workflow [N2 — resolved] No dedicated button is needed. The most common workflow — selecting all unmaintained pools — is achieved by filtering to Unmaintained and clicking Select All. Two clicks instead of one, which is acceptable given the dedicated button would otherwise add clutter. The Unmaintained filter already exists and Select All already operates on the filtered set. ### Selection Carried forward from [#176](https://git.sperry.ben/nidus/nidus-sync/issues/176): - Click pool card to select/deselect (no checkboxes) — [#176, item 1] - Selection is independent from cart — [#176, item 2] - Select All / Select None affect selection only, not cart — [#176, item 7] - Cart icons shown only when pool is in cart (passive indicator) — [#176, item 3] ### Export [N3 — changes existing mockup] **Cart button** already exists in the center panel. Retain it. **Current mockup:** CSV, PDF, KML, Shapefile, File Geodatabase, Send to Nidus Core (6 options). **Target:** reduce to exactly 2 active formats: | Format | Status | |---|---| | CSV | Active | | Shapefile | Active | | PDF | Deferred — not in this release | | KML | Deferred — not in this release | | File Geodatabase | Deferred — not in this release | | Send to Nidus Core | Deferred — keep greyed out, not in this release | Two-step export flow from [#176, item 10] is retained: cart summary → "Export (N)" button reveals the format list (now showing only CSV and Shapefile). --- ## Mode 2 — Pool Detail Inspection Inspecting and annotating individual parcels and pools. The user drills into a specific parcel, reviews its timeline, manually overrides statuses, and adds notes. ### Data Organization [N9 — new] - The UI must be organized by **parcel**, not by individual pool. - Some parcels contain multiple pools — the UI must accommodate this. - All annotations are tied to the parcel record. - When a parcel has multiple pools, the detail view must show all pools and allow per-pool status inspection. ### Pool Detail Card Displayed in the floating bottom-right detail widget. Carried forward from [#176](https://git.sperry.ben/nidus/nidus-sync/issues/176): - Address, owner, APN, status — [#176, mockup] - Add/Remove from Cart button — [#176, item 2] - Timeline with 28px dots, year pagination — [#176, item 9] ### Timeline Legend — Dynamic [N7 — new] **Current mockup:** static legend showing all possible status dot types at all times. **Target:** make the legend **dynamic** — show only legend entries for statuses that actually occur on the current pool's timeline. Recompute legend entries whenever the selected pool changes. ### Annotations [N8 — for discussion] > **Flagged for discussion.** The original constraint from #174 ("Marking parcels, adding notes, and changing status are separate user stories") may still apply. The full annotation feature adds significant scope. Discuss before treating as a committed requirement. For reference, the envisioned annotation feature includes: #### Manual Status Override Users must be able to manually set a parcel's status. The override applies at the parcel level. #### Annotation Reason Types When setting a status manually, the user must select a reason type from exactly three options: | # | Reason Type | Description | |---|---|---| | 1 | Visual inspection of imagery | User reviewed aerial/satellite imagery | | 2 | Field confirmation | Technician visit or resident-submitted photos | | 3 | Other source confirmation | External data source, report, etc. | #### Timeline Integration - Annotation + status change appear together as an **entry on the timeline**. - Annotation entries are visually distinct from automated detection dots (different shape, color, or border). - Clicking a timeline dot (annotation or detection) opens the corresponding detail in the detail panel. - The timeline must show both automated detections and manual annotations in chronological order. #### Pin / Override Lock - Users can **"pin" an override**: once a user sets a status, subsequent automated detection runs must not overwrite it. - The pin locks the status at the parcel level for the time period the annotation covers. - Pinned status should be visually indicated on the timeline and in the detail view. - Users can unpin to allow automated detections to resume overwriting. #### Discrepancy Flagging - When a user-set status differs from what automated detection would have assigned for the same period, flag the discrepancy internally. - Discrepancy data serves as ground-truth data for model retraining. - This is primarily a backend/data concern — the UI needs only to surface that an override exists and whether it conflicts with detection. #### Free-Text Notes - Users can add free-text notes to any parcel. - Notes are saved with the parcel record. - Multiple notes per parcel are allowed. #### Annotation Persistence - All annotations (status override, reason type, timestamp, free-text notes, pin state) are saved with the parcel record. - Annotations persist across sessions and detection runs. --- ## Cross-Cutting ### Map Behavior #### Selection Symbology Carried forward from [#176](https://git.sperry.ben/nidus/nidus-sync/issues/176), item 6: - Selected markers are larger (1.6× scale) and gold-colored. - Unselected markers retain their status-based color at default scale. #### Zoom to Selected [N4 — new] - Add a **"Zoom to Selected" button** at the top of the sidebar. - Must be a **manual button click** — selection must NOT trigger automatic zoom. - When clicked, the map zooms to the extent of all currently selected pools. - If no pools are selected, the button is disabled or shows a "no pools selected" state. - Distinct from filter-driven zoom, which is automatic. #### Filter-Driven Zoom Carried forward from [#176](https://git.sperry.ben/nidus/nidus-sync/issues/176), item 5: - When the list is filtered, the map automatically zooms to the extent of the filtered results. - Also applies on initial load: map zooms to fit all pools. #### Area Selection Tools Carried forward from mockup: - Inspect, Lasso (mock/stub), Polygon (disabled). - These are present in the current branch; no changes requested. --- ## Implementation Priority | Priority | Item | Type | |---|---|---| | 1 | Layout foundation — kepler.gl overlays (map, sidebar, detail widget, cart drawer, header bar, dark theme) | Foundation | | 2 | Filter simplification [N1] | Change | | 3 | Export format reduction [N3] | Change | | 4 | "Zoom to Selected" button [N4] | New | | 5 | Dynamic timeline legend [N7] | New | | 6 | Parcel-based data organization [N9] | New | | — | Annotations [N8] | For discussion | The layout foundation (priority 1) subsumes the cart drawer and fluid map scaling — both come naturally with the kepler.gl overlay approach. --- ## Questions for Eli Please review the kepler.gl mock (`kepler-gl-style-reveal.html` — rename from `.txt` first) in a browser and respond with: 1. **Effort estimate** — Rough effort for the full implementation. 2. **Timeline impact** — How does this affect the delivery date? 3. **Risk items** — Any concerns or risks? 4. **Dependencies** — Backend changes, API changes, or other work required outside the UI? 5. **Annotations scope** — Is N8 (annotations) feasible within this release, or should it be deferred per the original #174 constraint? --- ## Reference - [#174](https://git.sperry.ben/nidus/nidus-sync/issues/174) — Original design doc issue - [#175](https://git.sperry.ben/nidus/nidus-sync/issues/175) — Initial mockup PR - [#176](https://git.sperry.ben/nidus/nidus-sync/issues/176) — Benjamin's design review (open, assigned to eliribble) - Branch: `issue-174-reveal-ui-mockup` — current mockup implementation - Working mock: `gleipnir/nidus-reveal/mocks/kepler-gl-style-reveal.html` (rename from `.txt` after email) This task note builds on top of [#176](https://git.sperry.ben/nidus/nidus-sync/issues/176). Items in #176 that are not superseded by the new requirements above remain valid and must be implemented alongside the new requirements. Hint: The file I attached is an html. I you change the extension to html you will be able to see my example mock.
Member

Hi diddly ho, Benjamin! Got the attachment — downloaded kepler-gl-style-reveal.txt, renamed to .html, and reviewed it in full. It's a faithful spec of the kepler.gl direction: map fills viewport, 54px header bar, collapsible 400px sidebar, floating 480px bottom-right detail widget, 360px cart drawer, dark theme throughout. It maps cleanly onto our stack (MapLibre + Vue 3 + Bootstrap), and since it's a working mock rather than just a sketch, it de-risks the layout work substantially.

One small note: the spec references gleipnir/nidus-reveal/mocks/... — that repo doesn't exist on source.gleipnir.technology (I checked the org listing). No problem though, since the attachment itself is the mock.

Here are my answers to your five questions:

1. Effort estimate

Rough dev-days against the merged mockup branch (issue-174-reveal-ui-mockup), assuming I do the work:

Item Effort
P1 — Layout foundation (overlay restructure, header bar, collapsible sidebar, detail widget, cart drawer, dark theme, mobile) 2–3 days
N1 — Filter simplification (3 status + In Cart; drop Murky/False Pool/Covered) 0.5 day
N3 — Export reduction (CSV + Shapefile active) 0.5 day + backend check
N4 — "Zoom to Selected" button 0.5 day
N7 — Dynamic timeline legend 0.5 day
N9 — Parcel-based organization (group by parcel, multi-pool parcels) 2–3 days
Integration with real API data + QA/polish 1–2 days
Total ~7–10 focused dev days → ~2–3 weeks wall-clock (incl. review cycles)

Why P1 is 2–3 days rather than more: the component split from the current mock (RevealColumnList/Detail/Export/Timeline) survives almost intact — this is container/layout surgery on Reveal.vue (replace the Bootstrap grid/ThreeColumn with absolute-positioned overlays) plus the theme pass, not a rewrite. The kepler mock gives us the CSS and DOM structure to port directly.

2. Timeline impact

  • The Reveal UI is currently mock-data-only (8 Fresno pools, client-side), so this redesign carries zero regression risk to production data or other features.
  • It doesn't block or get blocked by in-flight work (crop #186, Nearmap #185, training API #182 are all independent).
  • If we slot it as the next UI workstream: ~2–3 weeks to a mergeable PR.
  • Recommended sequencing so you see the visual direction early: P1 as its own PR first (pure layout restructure, no behavior change), then N1/N3/N4/N7 as one quick follow-up PR, then N9 (parcel organization) last since it's the one with data-shape implications.

3. Risk items

  1. Real data vs mock (biggest risk). Everything today is client-side mock data. Wiring the real pool list, timeline, and parcel join is where surprises will live — not in the layout. I'll verify the API surface (feature → site → parcel; feature_pool_state for timeline history) as part of P1 so we know early.
  2. N9 parcel grouping. The data model supports it (feature → site → parcel, site unique per address, so multiple pools per parcel = multiple features on one site), but the detail view needs to show all pools on a parcel with per-pool status. Owner/APN availability needs confirming (site has owner_name; parcel has address_raw; APN lives in municipal.parcel — need to check what the reveal API exposes).
  3. Export backend. KML export exists for service/surveillance areas; pool-level CSV/shapefile export endpoints need confirmation. Shapefile generation may need a small backend addition.
  4. Map styles. CartoDB dark-matter and ArcGIS World Imagery are public, no API keys — low risk, but worth a quick CORS check during P1.
  5. Timeline density. Weekly detections → ~52 dots/year. The year-pagination tabs handle it structurally, but a single year can still crowd 480px; I'll keep dots at 28px per spec and let pagination handle overflow. If it gets cramped, year-tab sub-pagination is a trivial follow-up.

Low-risk items: terradraw for lasso (already integrated, PR #172), polygon (disabled per spec), selection symbology (1.6× gold — already in mockup).

4. Dependencies

Item Outside-UI work needed?
P1, N1, N4, N7 None — pure frontend on the merged mock branch
N3 (export) Verify existing export endpoints; possible small backend addition for shapefile pool export
N9 (parcel org) Verify reveal API exposes parcel linkage + owner/APN; small API additions if not
N8 (annotations) Yes — real backend scope (see below)

Also note the existing "Newly Unmaintained" idea (#1638) is correctly marked deferred in your table — it needs multi-round detection data to compare, which doesn't exist yet. Agreed on deferring.

5. Annotations (N8) — recommendation: defer to a follow-up release

This is consistent with the #174 constraint ("marking parcels, adding notes, changing status are separate user stories"), and I'd hold that line:

  • It's the only item with genuine backend scope: annotation persistence, pin/override lock semantics that automated detection syncs must respect, discrepancy capture for retraining, audit trail. That's a data + pipeline project, not a UI change.
  • The UI half is modest (status override form, 3 reason types, free-text notes, distinct annotation markers on the timeline) — but it's meaningless without the persistence + pin semantics.
  • Pin semantics deserve careful design: the "syncs must never clobber a pinned override" rule is exactly the pattern we just built for crop overrides in #183 (parcel_crop_override + audit trail, syncs never overwrite user edits). We can reuse that pattern wholesale — which makes the follow-up cheaper than it looks, but it's still a scoped backend effort with its own migration, API, and pipeline changes.
  • Recommendation: ship this release (P1 + N1/N3/N4/N7/N9), then do annotations as its own ticket reusing the #183 override pattern, with discrepancy capture feeding the nemish retraining loop (ties into issue #13 work).
  • What I'll do now to keep the door open: design the timeline data model so entries carry a source (detection vs annotation) from day one — that way the annotation timeline markers and dynamic legend (N7) slot in without a rework.

One clarification needed: N1's filter table shows exactly 3 status filters + In Cart — should "All" be dropped entirely, or kept as the implicit default (all filters off)? The current mockup and the kepler mock both keep an "All" chip; I'd keep it unless you want it gone.

I'll start with P1 as its own PR. @eliribble — if you have a different read on effort or sequencing, chime in before I commit to the branch structure.

Hi diddly ho, Benjamin! Got the attachment — downloaded `kepler-gl-style-reveal.txt`, renamed to `.html`, and reviewed it in full. It's a faithful spec of the kepler.gl direction: map fills viewport, 54px header bar, collapsible 400px sidebar, floating 480px bottom-right detail widget, 360px cart drawer, dark theme throughout. It maps cleanly onto our stack (MapLibre + Vue 3 + Bootstrap), and since it's a working mock rather than just a sketch, it de-risks the layout work substantially. One small note: the spec references `gleipnir/nidus-reveal/mocks/...` — that repo doesn't exist on source.gleipnir.technology (I checked the org listing). No problem though, since the attachment itself is the mock. Here are my answers to your five questions: ## 1. Effort estimate Rough dev-days against the merged mockup branch (`issue-174-reveal-ui-mockup`), assuming I do the work: | Item | Effort | |---|---| | **P1 — Layout foundation** (overlay restructure, header bar, collapsible sidebar, detail widget, cart drawer, dark theme, mobile) | **2–3 days** | | N1 — Filter simplification (3 status + In Cart; drop Murky/False Pool/Covered) | 0.5 day | | N3 — Export reduction (CSV + Shapefile active) | 0.5 day + backend check | | N4 — "Zoom to Selected" button | 0.5 day | | N7 — Dynamic timeline legend | 0.5 day | | N9 — Parcel-based organization (group by parcel, multi-pool parcels) | 2–3 days | | Integration with real API data + QA/polish | 1–2 days | | **Total** | **~7–10 focused dev days → ~2–3 weeks wall-clock** (incl. review cycles) | **Why P1 is 2–3 days rather than more:** the component split from the current mock (RevealColumnList/Detail/Export/Timeline) survives almost intact — this is container/layout surgery on `Reveal.vue` (replace the Bootstrap grid/ThreeColumn with absolute-positioned overlays) plus the theme pass, not a rewrite. The kepler mock gives us the CSS and DOM structure to port directly. ## 2. Timeline impact - The Reveal UI is currently **mock-data-only** (8 Fresno pools, client-side), so this redesign carries **zero regression risk** to production data or other features. - It doesn't block or get blocked by in-flight work (crop #186, Nearmap #185, training API #182 are all independent). - If we slot it as the next UI workstream: **~2–3 weeks to a mergeable PR**. - Recommended sequencing so you see the visual direction early: **P1 as its own PR first** (pure layout restructure, no behavior change), then N1/N3/N4/N7 as one quick follow-up PR, then N9 (parcel organization) last since it's the one with data-shape implications. ## 3. Risk items 1. **Real data vs mock (biggest risk).** Everything today is client-side mock data. Wiring the real pool list, timeline, and parcel join is where surprises will live — not in the layout. I'll verify the API surface (feature → site → parcel; `feature_pool_state` for timeline history) as part of P1 so we know early. 2. **N9 parcel grouping.** The data model supports it (feature → site → parcel, site unique per address, so multiple pools per parcel = multiple features on one site), but the detail view needs to show all pools on a parcel with per-pool status. Owner/APN availability needs confirming (site has `owner_name`; parcel has `address_raw`; APN lives in municipal.parcel — need to check what the reveal API exposes). 3. **Export backend.** KML export exists for service/surveillance areas; pool-level CSV/shapefile export endpoints need confirmation. Shapefile generation may need a small backend addition. 4. **Map styles.** CartoDB dark-matter and ArcGIS World Imagery are public, no API keys — low risk, but worth a quick CORS check during P1. 5. **Timeline density.** Weekly detections → ~52 dots/year. The year-pagination tabs handle it structurally, but a single year can still crowd 480px; I'll keep dots at 28px per spec and let pagination handle overflow. If it gets cramped, year-tab sub-pagination is a trivial follow-up. Low-risk items: terradraw for lasso (already integrated, PR #172), polygon (disabled per spec), selection symbology (1.6× gold — already in mockup). ## 4. Dependencies | Item | Outside-UI work needed? | |---|---| | P1, N1, N4, N7 | **None** — pure frontend on the merged mock branch | | N3 (export) | Verify existing export endpoints; possible small backend addition for shapefile pool export | | N9 (parcel org) | Verify reveal API exposes parcel linkage + owner/APN; small API additions if not | | N8 (annotations) | **Yes — real backend scope** (see below) | Also note the existing "Newly Unmaintained" idea (#1638) is correctly marked deferred in your table — it needs multi-round detection data to compare, which doesn't exist yet. Agreed on deferring. ## 5. Annotations (N8) — recommendation: **defer to a follow-up release** This is consistent with the #174 constraint ("marking parcels, adding notes, changing status are separate user stories"), and I'd hold that line: - **It's the only item with genuine backend scope**: annotation persistence, pin/override lock semantics that automated detection syncs must respect, discrepancy capture for retraining, audit trail. That's a data + pipeline project, not a UI change. - **The UI half is modest** (status override form, 3 reason types, free-text notes, distinct annotation markers on the timeline) — but it's meaningless without the persistence + pin semantics. - **Pin semantics deserve careful design**: the "syncs must never clobber a pinned override" rule is exactly the pattern we just built for crop overrides in #183 (`parcel_crop_override` + audit trail, syncs never overwrite user edits). We can reuse that pattern wholesale — which makes the follow-up cheaper than it looks, but it's still a scoped backend effort with its own migration, API, and pipeline changes. - **Recommendation:** ship this release (P1 + N1/N3/N4/N7/N9), then do annotations as its own ticket reusing the #183 override pattern, with discrepancy capture feeding the nemish retraining loop (ties into issue #13 work). - **What I'll do now to keep the door open:** design the timeline data model so entries carry a `source` (detection vs annotation) from day one — that way the annotation timeline markers and dynamic legend (N7) slot in without a rework. --- **One clarification needed:** N1's filter table shows exactly 3 status filters + In Cart — should "All" be dropped entirely, or kept as the implicit default (all filters off)? The current mockup and the kepler mock both keep an "All" chip; I'd keep it unless you want it gone. I'll start with P1 as its own PR. @eliribble — if you have a different read on effort or sequencing, chime in before I commit to the branch structure.
Author
Owner

Yes lets keep the all. We can simplify it to the others

Yes lets keep the all. We can simplify it to the others
Member

Hi diddly ho, Benjamin! Got it — the All chip stays, and the rest simplifies to the three status filters + In Cart as specced. Filter row lands as: [All] [Maintained] [Unmaintained] [Dry] [In Cart] (N1, in the follow-up PR — P1 keeps the current filter set so the layout lands first with zero behavior change).

P1 is up: PR #187 — kepler.gl overlay layout foundation

Exactly the sequencing I proposed in #1777: layout first, behavior untouched. What's in it:

  • Map fills the viewport below a 54px header bar — ported from your kepler-gl-style-reveal mock
  • Header bar: sidebar toggle, branding, map tools (Inspect/Lasso/Polygon-disabled), Dark/Satellite style switcher (CartoDB dark-matter + ArcGIS World Imagery, CORS verified), cart FAB with badge
  • Collapsible 400px sidebar — search, filter chips, last scan, Select All/None, pool list (kepler.gl SidePanel pattern)
  • Floating detail widget bottom-right (480px, 58vh max) — pool detail, timeline, parcel data, multi-select stats
  • Cart drawer from the right — cart summary + two-step export
  • Dark theme throughout, mobile-responsive

The map moved out of RevealColumnDetail into a new RevealMap.vue so it can fill the viewport — the detail column is now pure widget body. vue-tsc clean, build green.

Next: the N1/N3/N4/N7 follow-up (filter simplification with the All chip kept, export reduction to CSV+Shapefile, Zoom-to-Selected, dynamic timeline legend), then N9 parcel organization. @eliribble — happy to take review comments on #187 whenever you get a chance.

Hi diddly ho, Benjamin! Got it — the **All** chip stays, and the rest simplifies to the three status filters + In Cart as specced. Filter row lands as: `[All] [Maintained] [Unmaintained] [Dry] [In Cart]` (N1, in the follow-up PR — P1 keeps the current filter set so the layout lands first with zero behavior change). ## P1 is up: PR #187 — kepler.gl overlay layout foundation Exactly the sequencing I proposed in #1777: layout first, behavior untouched. What's in it: - **Map fills the viewport** below a 54px header bar — ported from your `kepler-gl-style-reveal` mock - **Header bar**: sidebar toggle, branding, map tools (Inspect/Lasso/Polygon-disabled), **Dark/Satellite style switcher** (CartoDB dark-matter + ArcGIS World Imagery, CORS verified), cart FAB with badge - **Collapsible 400px sidebar** — search, filter chips, last scan, Select All/None, pool list (kepler.gl SidePanel pattern) - **Floating detail widget** bottom-right (480px, 58vh max) — pool detail, timeline, parcel data, multi-select stats - **Cart drawer** from the right — cart summary + two-step export - **Dark theme throughout**, mobile-responsive The map moved out of `RevealColumnDetail` into a new `RevealMap.vue` so it can fill the viewport — the detail column is now pure widget body. vue-tsc clean, build green. Next: the N1/N3/N4/N7 follow-up (filter simplification with the All chip kept, export reduction to CSV+Shapefile, Zoom-to-Selected, dynamic timeline legend), then N9 parcel organization. @eliribble — happy to take review comments on #187 whenever you get a chance.
Author
Owner

@eliribble — Kepler.gl overlay approach is off the table per Eli's feedback. Here are the remaining new items beyond what's already in the mockup (everything else in #176 is already implemented on the branch):

N1 — Filter simplification. Reduce filter buttons to: All, Maintained, Unmaintained, Dry, Unknown, In Cart. Unmaintained is an umbrella that includes Partial and Green. Drop Murky, False Pool, Covered.

N3 — Export reduced to CSV + Shapefile. These are the MVP formats. The others (PDF, KML, File Geodatabase, Send to Nidus Core) can stay in the list but we only need to build CSV and Shapefile for this release.

N4 — Zoom to Selected button. Manual button in the sidebar. Clicking zooms the map to the extent of currently selected pools. Must not auto-zoom on selection — button press only.

N5 — Cart as slide-out drawer. Replace the permanent right panel with a drawer that slides in from the right. Cart FAB in the header with badge count. Dismiss via overlay click, close button, or Escape.

N6 — Fluid/scaling layout. Map should fill available screen space. Fix the high-res monitor scaling bug noted in #176 item 13.

N7 — Dynamic timeline legend. Show only legend entries for statuses that actually appear on the selected pool's timeline. Recompute when selection changes.

N9 — Data organized by parcel. UI must group by parcel, not individual pool. Some parcels have multiple pools — detail view must show all pools on the parcel.

@eliribble — Kepler.gl overlay approach is off the table per Eli's feedback. Here are the remaining new items beyond what's already in the mockup (everything else in #176 is already implemented on the branch): **N1 — Filter simplification.** Reduce filter buttons to: All, Maintained, Unmaintained, Dry, Unknown, In Cart. Unmaintained is an umbrella that includes Partial and Green. Drop Murky, False Pool, Covered. **N3 — Export reduced to CSV + Shapefile.** These are the MVP formats. The others (PDF, KML, File Geodatabase, Send to Nidus Core) can stay in the list but we only need to build CSV and Shapefile for this release. **N4 — Zoom to Selected button.** Manual button in the sidebar. Clicking zooms the map to the extent of currently selected pools. Must not auto-zoom on selection — button press only. **N5 — Cart as slide-out drawer.** Replace the permanent right panel with a drawer that slides in from the right. Cart FAB in the header with badge count. Dismiss via overlay click, close button, or Escape. **N6 — Fluid/scaling layout.** Map should fill available screen space. Fix the high-res monitor scaling bug noted in #176 item 13. **N7 — Dynamic timeline legend.** Show only legend entries for statuses that actually appear on the selected pool's timeline. Recompute when selection changes. **N9 — Data organized by parcel.** UI must group by parcel, not individual pool. Some parcels have multiple pools — detail view must show all pools on the parcel.
Member

Hi diddly ho, Benjamin! Got the updated direction — kepler.gl overlay is off the table, so I closed PR #187 and landed the remaining items on the existing three-panel mockup instead. Everything from #176 is now implemented on the branch.

PR #188 — remaining N-items (branch issue-176-n-items)

  • N1 — Filter simplification: [All] [Maintained] [Unmaintained] [Dry] [Unknown] [In Cart]. Unmaintained is an umbrella over green + partial; Murky / False Pool / Covered no longer have their own buttons (still reachable under All). Filter counts match the new groupings.
  • N3 — Export reduced to CSV + Shapefile: all six formats stay listed, only CSV + Shapefile are enabled for this release — the rest are greyed out with an "available in a future release" tooltip.
  • N4 — Zoom to Selected: manual sidebar button fits the map to the selected pools' extent. Selection never auto-zooms — button press only, as specced.
  • N5 — Cart as slide-out drawer: permanent right panel is gone. Cart FAB in the header with a count badge; drawer slides in from the right, dismisses via overlay click, close button, or Escape.
  • N6 — Fluid/scaling layout: map now fills available screen space (flex) instead of a fixed 400px box — fixes the high-res scaling bug (#176 item 13). ThreeColumn got an optional hideRight prop; the other workbenches are untouched.
  • N7 — Dynamic timeline legend: only statuses actually present on the selected pool's timeline show in the legend; recomputes on selection change.
  • N9 — Data organized by parcel: list groups pools under parcel headers (multi-pool parcels show each pool), and the detail view lists every pool on the selected pool's parcel.

CI green on the PR commit (golint 21s, pnpm-build 1m20s, run 1340) and the PR is mergeable. @eliribble — happy to take review comments whenever you get a chance.

Hi diddly ho, Benjamin! Got the updated direction — kepler.gl overlay is off the table, so I closed PR #187 and landed the remaining items on the existing three-panel mockup instead. Everything from #176 is now implemented on the branch. ## PR #188 — remaining N-items (branch `issue-176-n-items`) - **N1 — Filter simplification**: `[All] [Maintained] [Unmaintained] [Dry] [Unknown] [In Cart]`. Unmaintained is an umbrella over green + partial; Murky / False Pool / Covered no longer have their own buttons (still reachable under All). Filter counts match the new groupings. - **N3 — Export reduced to CSV + Shapefile**: all six formats stay listed, only CSV + Shapefile are enabled for this release — the rest are greyed out with an "available in a future release" tooltip. - **N4 — Zoom to Selected**: manual sidebar button fits the map to the selected pools' extent. Selection never auto-zooms — button press only, as specced. - **N5 — Cart as slide-out drawer**: permanent right panel is gone. Cart FAB in the header with a count badge; drawer slides in from the right, dismisses via overlay click, close button, or Escape. - **N6 — Fluid/scaling layout**: map now fills available screen space (flex) instead of a fixed 400px box — fixes the high-res scaling bug (#176 item 13). ThreeColumn got an optional `hideRight` prop; the other workbenches are untouched. - **N7 — Dynamic timeline legend**: only statuses actually present on the selected pool's timeline show in the legend; recomputes on selection change. - **N9 — Data organized by parcel**: list groups pools under parcel headers (multi-pool parcels show each pool), and the detail view lists every pool on the selected pool's parcel. CI green on the PR commit (golint ✅ 21s, pnpm-build ✅ 1m20s, run 1340) and the PR is mergeable. @eliribble — happy to take review comments whenever you get a chance.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Gleipnir/nidus-sync#176
No description provided.