Three fixes for the power-app SPA running as a go-base plugin (sandboxed iframe, origin 'null' — where localStorage throws and root-absolute asset paths misresolve under the /plugin-assets/<name>/ subpath): - localStorage: wrap every theme/preference read+write in try/catch across the library (ProfileLoader, useMapTheme, uiStore). `typeof localStorage` is not enough — in a sandbox the object exists but ACCESS throws SecurityError. Sandboxed maps now boot themeless instead of crashing. - assets: the SPA shell now injects an absolute assetsBase (derived from its own document.baseURI) into every mounted element's profile-config, so bundles fetch tables/vendor (Tabulator) from the correct subpath instead of a root-absolute /assets that 404s under /plugin-assets/doxa-maps-spa/. - nav: revert the Prayer Mobilization section icon to 'heart' (the prayer glyph read as a header it is not). Rebuilds every bundle (library-wide localStorage change). |
||
|---|---|---|
| .. | ||
| dataStore.js | ||
| mapStore.js | ||
| README.md | ||
| uiStore.js | ||
library/stores/ — per-instance Pinia stores
Three stores, one responsibility each. Created fresh per <doxa-map> element and provided to
descendants from ProfileLoader.vue — reach them via inject(), never a direct useXxxStore()
import (LL-010, LL-023).
| File | Owns | Example fields |
|---|---|---|
mapStore.js |
Map state: selections, zoom, bbox, Mapbox instances | selectedRegion, selectedFamily, maps[mapId], activeMapId |
uiStore.js |
UI state: sidebar, tabs, theme, toasts, modals | activeTab, sidebarCollapsed, theme, legendState |
dataStore.js |
Data caching: GeoJSON (markRaw), fetch status, errors | sources[sourceId], loadingStates[sourceId] |
- Use
markRaw()on large GeoJSON — Vue should not deeply proxy it. - Keep state changes in named actions; stores don't import each other (cross-store coordination happens at the component level).