meshai/work/dashboard-frontend/node_modules/lodash/array.js
malice 2c46c9104d
feat(region-routing): unified per-family routing cards + region-scoped family→channel routing (#87)
* feat(region-routing): P1 tagging + region_routes primitive + read/write API + preview launcher

- config.py: add Coverage.region_tagging (bool=False); add RegionRouteMatrix
  dataclass (enabled, cells) above NotificationsConfig; add region_routes field
  to NotificationsConfig; add explicit hydration branch for region_routes in
  _dict_to_dataclass mirroring destinations pattern.

- coverage_area.py: add MonitoringArea.name (str|None=None, frozen); update
  areas_from_config to preserve name; refactor inline geom extraction from
  classify_event_areas into shared _event_geom_json helper; add
  matching_area_names(geom_json, areas)->list[str] (additive, all named
  matches, config-order, deduped; gate unchanged); add event_region_names
  convenience wrapper.

- coverage_filter.py: add region_tagging ctor kwarg; stamp event.region/
  regions before the gate when region_tagging=True and areas non-empty and
  not event.regions (never clobbers satpass preset).

- pipeline/__init__.py: wire region_tagging into CoverageFilter construction.

- notification_routes.py: add GET /notifications/regions (named coverage area
  names, config-order, deduped); GET /notifications/region-routing (matrix as
  JSON); POST /notifications/region-routing (explicit RMW — only region_routes
  changes, toggles/rules/destinations survive).

- scripts/preview_dashboard.py: mesh-free launcher — dashboard API only, no
  mesh connector, no broadcast loop; vite runs separately.

All 87 coverage tests pass; 300 total pass; 6 pre-existing failures unchanged
(adapter config count mismatch + MeshCore EventType.NEW_CONTACT).

* feat(region-routing): manual region x family matrix editor page

Adds RegionRoutingMatrix.tsx — a plain editor over the region_routes
config primitive. Rows = families (via useFamilies()), cols = regions
(from GET /api/notifications/regions). Each cell exposes MT channel
(ChannelPicker single + includeDisabled), MC channel name (text input),
min_severity select (routine/priority/critical/immediate), and an enabled
checkbox. Only cells where MT or MC is set are included in the sparse
POST payload. Master enable toggle maps to top-level enabled. MT budget
guard warns when more than 7 distinct MT indices are in use. Sticky
family column; horizontal scroll for wide region sets.

Registers route /region-routing in App.tsx and adds "Region Routing"
nav entry (Map icon) under the Meshtastic section in Layout.tsx,
immediately after Routing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(region-routing): regions endpoint reads saved (disk) coverage so routing columns are dynamic without a bot restart; preview reloads config after writes

* feat(routing): unify MT/MC routing into per-family cards; region routing as an in-card expand; remove rules/destinations UI + standalone page

* refactor(routing): move Meshtastic Routing from /notifications to /meshtastic/routing (mirror /meshcore/routing); redirect legacy path

* feat(region-routing): dispatcher honors region_routes matrix (authoritative-on-match, per-region cooldown, per-channel dedup); non-matrix path unchanged

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(region-routing): matrix dedup key must match boot-restore 2-tuple form (prevents restart re-broadcast flood); regression test

---------

Co-authored-by: Matt Johnson <mj@k7zvx.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-07 16:52:03 -06:00

67 lines
2.4 KiB
JavaScript

module.exports = {
'chunk': require('./chunk'),
'compact': require('./compact'),
'concat': require('./concat'),
'difference': require('./difference'),
'differenceBy': require('./differenceBy'),
'differenceWith': require('./differenceWith'),
'drop': require('./drop'),
'dropRight': require('./dropRight'),
'dropRightWhile': require('./dropRightWhile'),
'dropWhile': require('./dropWhile'),
'fill': require('./fill'),
'findIndex': require('./findIndex'),
'findLastIndex': require('./findLastIndex'),
'first': require('./first'),
'flatten': require('./flatten'),
'flattenDeep': require('./flattenDeep'),
'flattenDepth': require('./flattenDepth'),
'fromPairs': require('./fromPairs'),
'head': require('./head'),
'indexOf': require('./indexOf'),
'initial': require('./initial'),
'intersection': require('./intersection'),
'intersectionBy': require('./intersectionBy'),
'intersectionWith': require('./intersectionWith'),
'join': require('./join'),
'last': require('./last'),
'lastIndexOf': require('./lastIndexOf'),
'nth': require('./nth'),
'pull': require('./pull'),
'pullAll': require('./pullAll'),
'pullAllBy': require('./pullAllBy'),
'pullAllWith': require('./pullAllWith'),
'pullAt': require('./pullAt'),
'remove': require('./remove'),
'reverse': require('./reverse'),
'slice': require('./slice'),
'sortedIndex': require('./sortedIndex'),
'sortedIndexBy': require('./sortedIndexBy'),
'sortedIndexOf': require('./sortedIndexOf'),
'sortedLastIndex': require('./sortedLastIndex'),
'sortedLastIndexBy': require('./sortedLastIndexBy'),
'sortedLastIndexOf': require('./sortedLastIndexOf'),
'sortedUniq': require('./sortedUniq'),
'sortedUniqBy': require('./sortedUniqBy'),
'tail': require('./tail'),
'take': require('./take'),
'takeRight': require('./takeRight'),
'takeRightWhile': require('./takeRightWhile'),
'takeWhile': require('./takeWhile'),
'union': require('./union'),
'unionBy': require('./unionBy'),
'unionWith': require('./unionWith'),
'uniq': require('./uniq'),
'uniqBy': require('./uniqBy'),
'uniqWith': require('./uniqWith'),
'unzip': require('./unzip'),
'unzipWith': require('./unzipWith'),
'without': require('./without'),
'xor': require('./xor'),
'xorBy': require('./xorBy'),
'xorWith': require('./xorWith'),
'zip': require('./zip'),
'zipObject': require('./zipObject'),
'zipObjectDeep': require('./zipObjectDeep'),
'zipWith': require('./zipWith')
};