Restore the regions and country pages to upstream

The regions index, the region and country pages, their map and the /regions and /countries rules are the same as upstream again; the map slot no longer carries the country-map bundle they no longer use.
This commit is contained in:
Doxa Life 2026-10-01 22:11:17 +00:00
parent 7e8c458b9b
commit da3312ba17
8 changed files with 11 additions and 88 deletions

View file

@ -6,7 +6,7 @@ interface Props {
/** Which IIFE bundle to load. Defaults to 'simple-map' to preserve
* existing call-sites (home, pray, adopt). Pass 'research-map' on the
* research page to load the 5-tab research-mfe bundle instead. */
bundle?: 'simple-map' | 'research-map' | 'country-map'
bundle?: 'simple-map' | 'research-map'
}
const props = withDefaults(defineProps<Props>(), { bundle: 'simple-map' })
@ -19,7 +19,7 @@ useDoxaMap(props.bundle)
* overwritten by the next one. Using a distinct tag per bundle eliminates
* the "Profile not found" error that occurred when /research had loaded
* its IIFE first and then the user navigated to /, /pray, or /adopt. */
const TAGS = { 'simple-map': 'doxa-map', 'research-map': 'doxa-research-map', 'country-map': 'doxa-country-map' } as const
const TAGS = { 'simple-map': 'doxa-map', 'research-map': 'doxa-research-map' } as const
const tagName = TAGS[props.bundle]
const isSimple = props.bundle === 'simple-map'
@ -142,8 +142,7 @@ const effectiveConfig = computed(() => {
}
.doxa-map-slot :deep(doxa-map),
.doxa-map-slot :deep(doxa-research-map),
.doxa-map-slot :deep(doxa-country-map) {
.doxa-map-slot :deep(doxa-research-map) {
display: block;
position: absolute;
/* inset inside the rounded frame; the map keeps its stacking to itself so its legend and search

View file

@ -9,10 +9,6 @@ import { regionSlug, type CountrySummary } from '~~/config/countries-meta'
const props = defineProps<{ country: CountrySummary }>()
// The country map is dx-maps' <doxa-country-map> (MapLibre by default, Mapbox by NUXT_PUBLIC_MAP_PROVIDER).
// DX-life's own CountryMap (Mapbox-only, blank without a token) is kept, switched off: set true to bring it back.
const USE_LEGACY_COUNTRY_MAP = false
const { t, locale } = useI18n()
const localePath = useLocalePath()
@ -20,17 +16,6 @@ const translations = computed(() => buildUupgListTranslations(t))
const regionLink = computed(() => localePath(`/regions/${regionSlug(props.country.region.value)}`))
const regionLabel = computed(() => props.country.region.label || t('Other'))
// The element fetches its own people groups (pins) from DX-life's campaign server; its locale comes from
// DoxaMapSlot, like every map.
const mapPrayBaseUrl = (useRuntimeConfig().public.prayBaseUrl as string) || 'https://pray.doxa.life'
const countryMapConfig = computed(() => JSON.stringify({
profile: 'country-map',
prayBaseUrl: mapPrayBaseUrl,
countryCodes: [props.country.code],
center: props.country.center,
zoom: props.country.zoom,
researchUrl: localePath('/research') + '/'
}))
// Map note. Placeholders are substituted manually with %count%/%country%
// tokens rather than vue-i18n's {0}/{1} slots: vue-i18n empties brace slots
@ -62,15 +47,7 @@ const mapNote = computed(() =>
{{ mapNote }}
</p>
<ClientOnly>
<DoxaMapSlot
v-if="!USE_LEGACY_COUNTRY_MAP"
:map-id="`country-map-${country.code}`"
bundle="country-map"
:profile-config="countryMapConfig"
class="rounded-xlg"
/>
<CountryMap
v-else
:country-codes="[country.code]"
:center="country.center"
:zoom="country.zoom"

View file

@ -154,8 +154,8 @@ function popupHtml(p: any): string {
${rows.length ? `<dl class="cm-popup__stats">${rows.join('')}</dl>` : ''}
${p.description ? `<p class="cm-popup__desc">${escapeHtml(p.description)}</p>` : ''}
<div class="cm-popup__actions">
<a class="cm-popup__btn cm-popup__btn--primary" href="${escapeHtml(prayUrl)}">${escapeHtml(t('Pray'))}</a>
<a class="cm-popup__btn" href="${escapeHtml(profileUrl)}">${escapeHtml(t('Full Profile'))}</a>
<a class="cm-popup__btn cm-popup__btn--primary" href="${prayUrl}">${escapeHtml(t('Pray'))}</a>
<a class="cm-popup__btn" href="${profileUrl}">${escapeHtml(t('Full Profile'))}</a>
</div>
</div>
</div>`

View file

@ -18,23 +18,6 @@ const formatNumber = (n: number) => n.toLocaleString(`${locale.value}-u-nu-latn`
const label = computed(() => props.region.label || t('Other'))
const countryCodes = computed(() => props.region.countries.map(c => c.code))
// The region map is dx-maps' <doxa-country-map> (MapLibre by default, Mapbox by NUXT_PUBLIC_MAP_PROVIDER).
// DX-life's own CountryMap (Mapbox-only, blank without a token) is kept, switched off: set true to bring it back.
const USE_LEGACY_COUNTRY_MAP = false
// The element fetches its own people groups (pins) from DX-life's campaign server; its locale comes from
// DoxaMapSlot, like every map.
const mapPrayBaseUrl = (useRuntimeConfig().public.prayBaseUrl as string) || 'https://pray.doxa.life'
const regionMapConfig = computed(() => JSON.stringify({
profile: 'country-map',
prayBaseUrl: mapPrayBaseUrl,
countryCodes: countryCodes.value,
center: props.region.center,
zoom: props.region.zoom,
bounds: props.region.bounds,
colorByPrayer: true,
researchUrl: localePath('/research') + '/'
}))
// Prayer coverage split, mirroring the pray page: fully covered (100+
// committed), partially covered (1+), and no one committed yet.
const partialPrayerCount = computed(() => Math.max(0, props.region.withPrayer - props.region.withFullPrayer))
@ -89,15 +72,7 @@ const mapNote = computed(() =>
<div class="stack stack--sm">
<p class="text-center color-primary font-weight-bold">{{ mapNote }}</p>
<ClientOnly>
<DoxaMapSlot
v-if="!USE_LEGACY_COUNTRY_MAP"
:map-id="`region-map-${countryCodes.join('-')}`"
bundle="country-map"
:profile-config="regionMapConfig"
class="rounded-xlg"
/>
<CountryMap
v-else
:country-codes="countryCodes"
:center="region.center"
:zoom="region.zoom"

View file

@ -4,15 +4,12 @@
// So nothing from api.mapbox.com sits in front of the map: with MapLibre, Mapbox is never fetched, and
// a slow or blocked Mapbox CDN cannot stop the map from appearing.
// Map of bundle keys → bundles in the dx-maps build tree, the same tree the Research page's gallery
// is served from: NUXT_PUBLIC_DX_MAPS_BASE (the maps CDN, the default) or, when that is set empty,
// this site's own /dx-maps/. Each bundle registers its own custom element (<doxa-map>,
// Map of bundle keys → bundles in the dx-maps tree: this site's own /dx-maps/ (the default), or the tree
// NUXT_PUBLIC_DX_MAPS_BASE points at. Each bundle registers its own custom element (<doxa-map>,
// <doxa-research-map>).
const BUNDLES = {
'simple-map': 'doxa-simple-map/doxa-simple-map.js',
'research-map': 'doxa-research-map/doxa-research-map.js',
// The country/region detail pages' map (<doxa-country-map>): dx-maps' RegionCountryMap, both engines.
'country-map': 'country-map/country-map.js'
'research-map': 'doxa-research-map/doxa-research-map.js'
} as const
type BundleKey = keyof typeof BUNDLES

View file

@ -6,19 +6,6 @@
import type { RegionSummary } from '~~/config/countries-meta'
// Where the Research Gallery is the Research page, /regions (in every language) REDIRECTS there with
// ?tab=regions-dashboard. On this branch the gallery is the hidden Deep Research page, so this index is
// DX Life's own again: USE_LEGACY_REGIONS_PAGE is true. Set it false to bring the redirect back.
definePageMeta({
middleware: [(to) => {
const USE_LEGACY_REGIONS_PAGE = true
if (!USE_LEGACY_REGIONS_PAGE) {
// The locale is already in the path (/ar/regions -> /ar/research).
return navigateTo({ path: to.path.replace(/\/regions\/?$/, '/research'), query: { tab: 'regions-dashboard' } }, { redirectCode: 301 })
}
}]
})
const { t, locale } = useI18n()
const localePath = useLocalePath()

View file

@ -36,9 +36,7 @@ export default defineNuxtModule({
const prefixes = ['', ...ENABLED_LANGUAGE_CODES.filter(code => code !== 'en').map(code => `/${code}`)]
const routes: string[] = []
for (const prefix of prefixes) {
// The /regions index is not prerendered when a route rule redirects it (LEGACY_REGIONS_PAGE in nuxt.config.ts).
const indexRule = (nuxt.options.routeRules as Record<string, { redirect?: unknown }> | undefined)?.[`${prefix}/regions`]
if (!indexRule?.redirect) routes.push(`${prefix}/regions`)
routes.push(`${prefix}/regions`)
for (const slug of slugs) routes.push(`${prefix}/regions/${slug}`)
}

View file

@ -44,21 +44,11 @@ const marketingRouteRules = Object.fromEntries(
// be a static glob); these rules just apply the marketing HTML cache policy
// across all enabled locales. The former /countries URLs redirect permanently
// to their /regions equivalents (same slugs) so old links keep working.
// REGIONS IS A VIEW OF THE RESEARCH GALLERY: the /regions INDEX 301s to the gallery's Regions tab in every
// language (the region/country detail pages stay). LEGACY_REGIONS_PAGE = true brings the index back: it
// restores these rules and its prerender entry (modules/region-routes.ts). The page's own middleware covers
// in-app navigation. On this branch it is true: the gallery is the hidden Deep Research page, so /regions is
// DX Life's own index again and /countries goes to it.
const LEGACY_REGIONS_PAGE = true
const regionRouteRules = Object.fromEntries(
MARKETING_LOCALE_PREFIXES.flatMap(prefix => [
LEGACY_REGIONS_PAGE
? [`${prefix}/regions`, { headers: { 'cache-control': MARKETING_HTML_CACHE } }]
: [`${prefix}/regions`, { redirect: { to: `${prefix}/research?tab=regions-dashboard`, statusCode: 301 } }],
[`${prefix}/regions`, { headers: { 'cache-control': MARKETING_HTML_CACHE } }],
[`${prefix}/regions/**`, { headers: { 'cache-control': MARKETING_HTML_CACHE } }],
LEGACY_REGIONS_PAGE
? [`${prefix}/countries`, { redirect: { to: `${prefix}/regions`, statusCode: 301 } }]
: [`${prefix}/countries`, { redirect: { to: `${prefix}/research?tab=regions-dashboard`, statusCode: 301 } }],
[`${prefix}/countries`, { redirect: { to: `${prefix}/regions`, statusCode: 301 } }],
[`${prefix}/countries/**`, { redirect: { to: `${prefix}/regions/**`, statusCode: 301 } }]
])
)