Skip to content

v1.1.2: Tutorial UX fixes + Selig database + Smart Group + Show Me tours#9

Merged
aeronauty-flexcompute merged 18 commits intomainfrom
dev
Mar 20, 2026
Merged

v1.1.2: Tutorial UX fixes + Selig database + Smart Group + Show Me tours#9
aeronauty-flexcompute merged 18 commits intomainfrom
dev

Conversation

@aeronauty-flexcompute
Copy link
Copy Markdown
Collaborator

Summary

  • Selig airfoil database: ~1,600 UIUC airfoils searchable and loadable from the Library panel, plus Random Foil button
  • Smart Group: one-click row grouping in Data Explorer by polar configuration (airfoil + Re + Mach + Ncrit + flap) with CL_max, L/D_max, alpha_stall aggregations
  • Show Me tours: interactive guided walkthroughs for new features, launched from the What's New dialog
  • Tutorial reliability: tour no longer dismisses when clicking the overlay; hidden-panel warning replaced with a "Show Panel" button that programmatically opens the required panel
  • Python API: PolarResult now exposes cl_max, alpha_stall, ld_max, cd_min, argmax/argmin/column_mean/column_median; explicit alpha arrays and matrix sweeps
  • Surface distributions: Cp, boundary-layer, and velocity distributions panel
  • File menu: Export .dat (Selig format) and SVG; import .dat fixed on Samsung browsers
  • Data Explorer: row grouping with aggregation, custom aggregation functions (argmax/argmin), aggregated data source in Plot Builder and correlogram, Converged Only quick-filter
  • Airfoil HUD: shows airfoil name with collapsible toggle

Changelog, Versions & Docs

  • flexfoil-ui/src/lib/version.ts CHANGELOG updated
  • All user-visible changes have a changelog entry
  • flexfoil-ui/package.json version matches top CHANGELOG entry (1.1.2)
  • packages/flexfoil-python/pyproject.toml version bumped (1.1.4)
  • New/changed docs pages added or updated in docs-site/docs/
  • No stale or aspirational content remains in affected docs

Test plan

  • Verify Selig database search and load works
  • Verify Smart Group button in Data Explorer
  • Trigger Show Me tours from What's New dialog
  • Close a panel, start a tour targeting it, click "Show Panel" button — panel should open
  • Click overlay during tour — should NOT dismiss
  • Run polar sweep via Python API, check PolarResult attributes
  • Export .dat and SVG from File menu
  • Import .dat on mobile browser

Made with Cursor

aeronauty and others added 18 commits March 19, 2026 11:10
- Add searchable Selig database panel with ~1,600 airfoils from UIUC
- Random Foil button picks and loads a random airfoil from the catalog
- Parse Lednicer-format .dat files (two-section upper/lower layout)
- Proxy endpoints for CORS-free .dat fetching (Vite dev + Python server)
- Attribution link to UIUC Airfoil Coordinates Database
- Bundled catalog JSON generated from UIUC database HTML
- Data Explorer enhancements, outlier flagging, Plot Builder improvements
- Python API polar result aggregation methods

Made-with: Cursor
Fetch from same-origin static path instead of proxy — fixes 403 on
the deployed beta (S3/CloudFront has no server to proxy through).

All 1,665 Selig-format .dat files from the UIUC archive are served
from public/airfoils/ alongside the app.

Made-with: Cursor
- Add Smart Group button in Data Explorer that groups by polar
  configuration (airfoil + Re + Mach + Ncrit + flap config) and
  auto-shows alpha_stall and alpha @ L/D_max summary columns
- Fix toFixed crash when grouping by non-numeric columns (all 11
  valueFormatters now guard with typeof check)
- Add flap_deflection and flap_hinge_x columns to Data Explorer
- Add Aggregated data source to Data Explorer correlogram
- Add aggregated scatter overlay (diamond markers) to Polar Plot
- Auto-switch correlogram to Aggregated when Smart Group activates
- Persist Smart Group state and data source in routeUiStore so they
  survive view switches and page reloads (ephemeral + URL)
- Update changelog with all new features

Made-with: Cursor
The const was declared 70 lines after the useCallback that referenced
it, causing a TDZ ReferenceError on component mount.

Made-with: Cursor
- Add .github/workflows/ci.yml (cargo test --workspace + flexfoil-python pytest)
- rustfoil-testkit: warn-only xfoil src check; paths helpers for instrumented bin/exe
- Skip instrumented-binary and Fortran object parity tests without Xfoil-instrumented
- Sync shifted_stmove_state fixture with qvfue/gamqv after gam override
- Workflow reference coords: fall back to testdata naca0012_xfoil_paneled.dat
- Committed spline testdata + gen_spline_fixtures example; assorted test robustness fixes

Made-with: Cursor
Replace the Start/End/Step sweep fields with a single text input
accepting start:step:end, [v1,v2,v3], bare CSV, and mixed notation
for non-uniform parameter sweeps (e.g. 5e5, 1e6, 3e6).

Add a Distributions panel that plots Cp, Cf, δ*, θ, H, and ue
against x/c, y, or arc-length s, with multi-run overlay support
driven by checkbox selection in the Data Explorer table.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Made-with: Cursor
…ions

- polar() now accepts alpha as a list (e.g. [5e5, 1e6, 3e6]) alongside
  the existing (start, end, step) tuple notation
- polar() Re, mach, ncrit accept lists for automatic outer-product
  matrix sweeps, returning list[PolarResult]
- SolveResult exposes cp and cp_x arrays (from inviscid panel solve)
- New Airfoil.bl_distribution() method returns BLResult with per-surface
  Cf, delta_star, theta, H, and ue arrays (viscous only)
- New get_bl_distribution Rust binding in rustfoil-python crate
- 10 new tests covering all new functionality (44 total, all pass)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Made-with: Cursor
Group runs by "everything the same except the X-axis parameter"
instead of a hardcoded invariant-field list. This correctly handles:
- Non-uniform alpha sweeps (e.g. 5:1:11, 11.11, 15:1:28)
- Re/Mach/Ncrit sweeps on the X-axis
- Matrix sweeps (alpha x Re)

Also raises the gap-split multiplier from 3 to 5 and skips gap
splitting for groups smaller than 6 points, preventing spurious
fragmentation of intentional non-uniform sweeps.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Made-with: Cursor
Add text/* MIME types to the file input accept attribute so Samsung
Internet uses the document picker instead of the media-only browser.
No effect on Chrome/Firefox/Safari.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Made-with: Cursor
- Add tourSlides to 1.1.1 changelog (Selig Database, Smart Group,
  Outlier Flagging, File Menu & Export)
- Add inline "Show Me" buttons to the flat changelog list view via
  optional showMeTourId on ChangelogItem
- Create showMe tours for seligDatabase and smartGroup with data-tour
  attributes on Library and Data Explorer panels
- Bump flexfoil-ui to 1.1.1 to match changelog
- Trigger pypi-publish workflow on push to main (auto-publish on merge)
- Add version-bumping gate to pr-to-main rule

Made-with: Cursor
…ing replaced with Show Panel button

- Set overlayClickBehavior to no-op so clicking the overlay doesn't
  destroy the tour (users can still close via the X button)
- Replace "Element not visible" warning with "Panel hidden" label,
  an animated SVG cursor, and a "Show {Panel}" button that
  programmatically opens the required panel
- Add delegated click handler for [data-open-panel] buttons
- Bump to 1.1.2

Made-with: Cursor
driver.js registers a capture-phase click handler on document that calls
stopImmediatePropagation() for all clicks inside the popover. Our handler
was being re-registered (losing priority) every time openPanel changed
identity. Use a ref so the listener stays first in the chain, and call
stopImmediatePropagation ourselves to block driver.js from swallowing it.

Made-with: Cursor
driver.js registers capture-phase click handlers on document that call
stopImmediatePropagation() for all clicks inside the popover wrapper.
By registering our handler on window instead of document, it fires
before any document-level handlers in the capture phase (window →
document → ... → target), guaranteeing we intercept the click first.

Made-with: Cursor
driver.js registers capture-phase handlers on document for pointerdown,
mousedown, pointerup, mouseup AND click. All call stopImmediatePropagation.
We now intercept all five event types on window capture phase to fully
own the event chain for [data-open-panel] button interactions.

Made-with: Cursor
LayoutContext's openPanel can hold a stale model reference when the
layout is restored from localStorage. Use applyRouteActivePanel from
the route store instead — this bumps a revision counter that triggers
DockingLayout's own useEffect, which has direct access to the current
model state and calls handleOpenPanel/handleRestorePanel reliably.

Made-with: Cursor
Made-with: Cursor

# Conflicts:
#	flexfoil-ui/src/App.tsx
@aeronauty-flexcompute aeronauty-flexcompute self-assigned this Mar 20, 2026
@aeronauty-flexcompute aeronauty-flexcompute merged commit 0643e0c into main Mar 20, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants