Public snapshot
63
README.md
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# ABC Audit — app-shell MFE Plugin drop
|
||||
|
||||
This folder makes the **ABC Audit** service appear in the app-shell **Plugin
|
||||
Library** (`/library`) and open **in-shell**, authed by the user's app-shell
|
||||
session — the Class-2 MFE-plugin path (the app-shell has no Class-3 "Services"
|
||||
registry; it embeds MFE bundles).
|
||||
|
||||
## What the app-shell expects (contract)
|
||||
|
||||
The app-shell `/library` page reads a multi-MFE **`index.json`** manifest
|
||||
(schema `doxa-1040-maps-mfe-index@1`) via `GET /api/_library`, which scans the
|
||||
source configured by the server env var:
|
||||
|
||||
```
|
||||
NUXT_MFE_INDEX_SOURCE=<path-or-url> # a local path to this folder / its index.json, OR an http(s) URL
|
||||
NUXT_PUBLIC_MFE_LIBRARY_ENABLED=true # already set on the DT app-shell (turns /library on)
|
||||
```
|
||||
|
||||
Each **bundle** in the manifest is an **IIFE** that registers a **custom
|
||||
element**; the shell embeds it as `<abc-audit-tree profile-config='{…}'>`. The
|
||||
`/library` "View" action opens the profile's `embed` staging page.
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
mfe-index/
|
||||
index.json manifest (static, checked in)
|
||||
build.sh assembles the drop (builds the IIFE, copies it in)
|
||||
abc-audit/
|
||||
abc-audit.iife.js BUILT — self-mounting <abc-audit-tree> (see build.sh)
|
||||
audit-tree/index.html staging "View" page — loader-injects-token
|
||||
```
|
||||
|
||||
`abc-audit.iife.js` is **built, not committed** (the builder sandbox has no npm).
|
||||
Run `./build.sh` on any host with npm (the deploy host / BUILD-GATE) to produce it.
|
||||
|
||||
## The auth wire (C1 — no second login)
|
||||
|
||||
The token is **never baked** into the bundle. The staging page injects it at
|
||||
runtime (priority: `?tk=` → `window.__MFE_TOKEN__` → baked `profile-config.tk`)
|
||||
and the API base the same way (`?api=` → `window.__ABC_API_URL__` → `apiUrl`).
|
||||
The custom element writes the token to `localStorage['abc_dev_token']` and sets
|
||||
the API host before the Vue app's first `getTree()` — so the tree loads live
|
||||
under the user's tenant with no re-login. The token is the **app-shell-signed
|
||||
HS256 JWT**; the running ABC API verifies it with the same
|
||||
`APP_SHELL_JWT_SECRET` (C1 wire, already live).
|
||||
|
||||
The app-shell's library "View" href must therefore be given `?tk=<session JWT>`
|
||||
and `?api=<abc api base>` for a specific deployment — or a host wrapper sets
|
||||
`window.__MFE_TOKEN__` / `window.__ABC_API_URL__` before loading the bundle.
|
||||
|
||||
## Deploy steps (coordinator / deploy-side)
|
||||
|
||||
1. `cd abc-audit-service/mfe-index && ./build.sh` → produces `abc-audit/abc-audit.iife.js`
|
||||
2. Serve this `mfe-index/` folder (static) OR push it to the forge raw.
|
||||
3. Set on the app-shell container:
|
||||
`NUXT_MFE_INDEX_SOURCE=<served-url-or-path>/index.json` and recreate the app-shell.
|
||||
4. Log into `:3000` → `/library` shows **ABC Audit** → View → the audit tree opens
|
||||
in-shell (44 audits render), no second login.
|
||||
|
||||
No app-shell **code** change is needed — `NUXT_MFE_INDEX_SOURCE` is deploy
|
||||
config. (If in-shell mounting ever needs shell code, STOP and coordinate the
|
||||
authoritative app-shell tree with qa-coord/pm-1040-maps.)
|
||||
110
app/doxa-maps/all-people-groups/all-people-groups.js
Normal file
171
app/doxa-maps/all-people-groups/all-people-groups/index.html
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>all-people-groups · all-people-groups</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<!-- Mapbox peer loaded ONCE here; the map custom element mounts in this page and
|
||||
uses window.mapboxgl directly (same realm → no cross-realm container errors). -->
|
||||
<link rel="preconnect" href="https://api.mapbox.com" crossorigin />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css" rel="stylesheet" />
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
|
||||
<style>
|
||||
/* BARE full-page map — no chrome. The custom element IS the page, so the
|
||||
browser URL shares the map itself. */
|
||||
html, body { height: 100%; margin: 0; background: #0a0e15; }
|
||||
#slot, all-people-groups { position: fixed; inset: 0; width: 100%; height: 100%; display: block; }
|
||||
#status { position: fixed; inset: 0; z-index: 2; display: grid; place-items: center;
|
||||
padding: 24px; text-align: center; color: #9aa7b8;
|
||||
font: 13px/1.6 ui-monospace, SFMono-Regular, Menlo, monospace; }
|
||||
#status.err { color: #f87171; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="slot"></div>
|
||||
<div id="status">loading token…</div>
|
||||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <all-people-groups> custom element. -->
|
||||
<script src="../all-people-groups.js" integrity="sha384-naI/FjUN6z0mTDZsarX/PHn6uR/XAs1dXnRBGtfLE4xJcfVhDJ7KzoB9+VvLIuCz" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
// 1. prop — a token hardcoded into this page's profile-config (config.tk)
|
||||
// 2. ?tk= URL param — token carried in the shared link
|
||||
// 3. baked token — opt-in literal token inlined at build time (build-config.token)
|
||||
// A token from rungs 1-3 is used DIRECTLY (no network). Otherwise a token
|
||||
// *endpoint* is resolved and fetched:
|
||||
// 4. window.MAP_TOKEN_URL override 5. configured TOKEN_SRC URL 6. same-origin /api/maps/token
|
||||
// TOKEN_SRC is treated as DATA, never eval'd: the literal "window.MAP_TOKEN_URL"
|
||||
// means "read that global"; anything else is used as a URL — so both a global
|
||||
// name and a plain URL are safe (no SyntaxError footgun).
|
||||
(function () {
|
||||
var slot = document.getElementById('slot');
|
||||
var status = document.getElementById('status');
|
||||
var BASE_CONFIG = {"profile":"all-people-groups","dataSource":"pray-tools","instanceId":"all-people-groups-all-people-groups","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = false;
|
||||
var TOKEN_SRC = "window.MAP_TOKEN_URL";
|
||||
var BAKED_TOKEN = "pk.eyJ1IjoiZ29zeXN0ZW1zIiwiYSI6ImNtZm9vM291czA3amQya3BzYW42YW9ibTcifQ.52WM0IpxY9FcB0zc9f1zbQ";
|
||||
// Expose the baked token as window.MAP_TOKEN so a BAKED composite (a compiled element that mounts
|
||||
// a map component directly, with no ProfileLoader/profile-config wrapper) still finds a token —
|
||||
// useMapInstance falls back to window.MAP_TOKEN. No effect when BAKED_TOKEN is empty.
|
||||
if (BAKED_TOKEN && typeof window !== 'undefined' && !window.MAP_TOKEN) { window.MAP_TOKEN = BAKED_TOKEN; }
|
||||
var DEFAULT_TOKEN_URL = '/api/maps/token';
|
||||
|
||||
function fail(msg) { if (status) { status.className = 'err'; status.textContent = '⚠ ' + msg; } }
|
||||
// No token anywhere on the ladder → ask ONCE, store locally, remount. No dead ends.
|
||||
function askToken() {
|
||||
if (!status) return;
|
||||
status.className = 'err';
|
||||
status.innerHTML = 'map needs a Mapbox token — ' +
|
||||
'<input id="tkIn" type="password" placeholder="paste pk.… (stays in this browser)" ' +
|
||||
'style="font:12px ui-monospace,monospace;padding:6px 8px;border-radius:6px;border:1px solid #223047;background:#0e1623;color:#eef2f7;width:min(320px,70vw)"> ' +
|
||||
'<button id="tkGo" style="font:700 11px ui-monospace,monospace;padding:7px 12px;border-radius:999px;border:0;cursor:pointer;background:linear-gradient(90deg,#46d4ff,#b9a6f5);color:#0a0e15">use it</button>';
|
||||
var go = document.getElementById('tkGo');
|
||||
if (go) go.addEventListener('click', function () {
|
||||
var v = (document.getElementById('tkIn').value || '').trim();
|
||||
if (!v) return;
|
||||
try { localStorage.setItem('MAPS_STAGING_TK', v); } catch (e) {}
|
||||
mount(v);
|
||||
});
|
||||
}
|
||||
/* ★ RELEASE THE LOAD BACKDROP WHEN THE ELEMENT MOUNTS (BUG-GOSPEL-MAP-BLACK-RECTANGLE).
|
||||
html/body carry background:#0a0e15 so the light #status text (#9aa7b8) is readable while the
|
||||
bundle loads. That backdrop is LOAD-STATE CHROME, but it outlived its moment: any gap the
|
||||
mounted element does not cover shows it through, because every layer above body is
|
||||
transparent. On gospel-resources/resources-map that produced a 352x126 DARK RECTANGLE between
|
||||
the legend card and the detail panel — MEASURED rgb(8,12,18), i.e. the page background, NOT an
|
||||
unpainted canvas as first supposed. Clearing it here (the one place we already know the
|
||||
element is up) is a one-shot style write — no resize, no repaint loop. The product owner is
|
||||
PHOTOSENSITIVE and a 60fps resize-strobe was already fixed this session; do NOT turn this into
|
||||
a per-frame or per-event handler. */
|
||||
function done() {
|
||||
if (status && status.parentNode) { status.parentNode.removeChild(status); }
|
||||
document.documentElement.style.background = '#f3f3f1';
|
||||
document.body.style.background = '#f3f3f1';
|
||||
}
|
||||
|
||||
function mount(token) {
|
||||
if (!token && !TOKEN_FREE) { return askToken(); }
|
||||
try {
|
||||
var cfg = token ? Object.assign({}, BASE_CONFIG, { tk: token }) : BASE_CONFIG;
|
||||
var el = document.createElement("all-people-groups");
|
||||
el.setAttribute('profile-config', JSON.stringify(cfg));
|
||||
slot.innerHTML = '';
|
||||
slot.appendChild(el);
|
||||
done();
|
||||
} catch (e) { fail(e && e.message ? e.message : String(e)); }
|
||||
}
|
||||
|
||||
function qp(name) {
|
||||
try { return new URLSearchParams(location.search).get(name) || ''; }
|
||||
catch (e) { return ''; }
|
||||
}
|
||||
|
||||
function extractToken(data) {
|
||||
if (typeof data === 'string') return data.trim();
|
||||
if (data && typeof data === 'object') return data.token || data.tk || data.accessToken || '';
|
||||
return '';
|
||||
}
|
||||
|
||||
// Rungs 1-3b: an actual token → mount directly, no fetch.
|
||||
// 2b = localStorage: the paste-once store shared with the staging pages
|
||||
// (MAPS_STAGING_TK) — paste a token ONCE anywhere in the tree, every page uses it.
|
||||
var stored = '';
|
||||
try { stored = localStorage.getItem('MAPS_STAGING_TK') || ''; } catch (e) {}
|
||||
var urlTk = qp('tk');
|
||||
if (urlTk) { try { localStorage.setItem('MAPS_STAGING_TK', urlTk); } catch (e) {} }
|
||||
var directToken = (BASE_CONFIG && BASE_CONFIG.tk) || urlTk || stored || BAKED_TOKEN;
|
||||
if (TOKEN_FREE) { return mount(''); }
|
||||
if (directToken) { return mount(directToken); }
|
||||
|
||||
// Rungs 4-6: resolve the token ENDPOINT candidates and try them IN ORDER — the first
|
||||
// one that answers with a token wins. Order: window.MAP_TOKEN_URL override → the
|
||||
// configured TOKEN_SRC (an ABSOLUTE url, so a tree hosted on a CDN away from the API
|
||||
// still finds it) → same-origin /api/maps/token (dev, or the site hosting both).
|
||||
// A single hard-coded pick used to kill the page when its one url 404'd or was
|
||||
// blocked by CORS; a shared link must work wherever the tree is hosted.
|
||||
var candidates = [];
|
||||
function addCandidate(u) { if (u && candidates.indexOf(u) === -1) candidates.push(u); }
|
||||
addCandidate(window.MAP_TOKEN_URL);
|
||||
addCandidate(TOKEN_SRC && TOKEN_SRC !== 'window.MAP_TOKEN_URL' ? TOKEN_SRC : '');
|
||||
addCandidate(DEFAULT_TOKEN_URL);
|
||||
|
||||
function fetchToken(i, errors) {
|
||||
if (i >= candidates.length) {
|
||||
// Every endpoint failed: say which, and still offer the paste-once box (no dead ends).
|
||||
askToken();
|
||||
if (status) {
|
||||
var d = document.createElement('div');
|
||||
d.textContent = '⚠ Token fetch failed from ' + candidates.join(', ') + ' — set window.MAP_TOKEN_URL or pass ?tk=. (' + errors.join(' | ') + ')';
|
||||
status.insertBefore(d, status.firstChild);
|
||||
}
|
||||
return;
|
||||
}
|
||||
var url = candidates[i];
|
||||
return fetch(url)
|
||||
.then(function (r) {
|
||||
if (!r.ok) throw new Error(url + ' → HTTP ' + r.status);
|
||||
var ct = r.headers.get('content-type') || '';
|
||||
return ct.indexOf('json') !== -1 ? r.json() : r.text();
|
||||
})
|
||||
.then(function (data) {
|
||||
var tk = extractToken(data);
|
||||
if (!tk) throw new Error(url + ' → no token in response');
|
||||
mount(tk);
|
||||
})
|
||||
.catch(function (e) {
|
||||
errors.push(e && e.message ? e.message : String(e));
|
||||
return fetchToken(i + 1, errors);
|
||||
});
|
||||
}
|
||||
fetchToken(0, []);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
1
app/doxa-maps/assets/boundaries/gb-CHN-ADM1.geojson
Normal file
1
app/doxa-maps/assets/boundaries/gb-IND-ADM1.geojson
Normal file
1
app/doxa-maps/assets/boundaries/world-adm0.geojson
Normal file
BIN
app/doxa-maps/assets/previews/andean-caribbean.webp
Normal file
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 46 KiB |
BIN
app/doxa-maps/assets/previews/asia-china-yunnan-province.webp
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
app/doxa-maps/assets/previews/asia-india-andhra-pradesh.webp
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
app/doxa-maps/assets/previews/asia-india-gujarat.webp
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
app/doxa-maps/assets/previews/asia-india-karnataka.webp
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
app/doxa-maps/assets/previews/asia-india-kerala.webp
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
app/doxa-maps/assets/previews/asia-india-madhya-pradesh.webp
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
app/doxa-maps/assets/previews/asia-india-odisha.webp
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
app/doxa-maps/assets/previews/asia-india-rajasthan.webp
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
app/doxa-maps/assets/previews/asia-india-tamil-nadu.webp
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
app/doxa-maps/assets/previews/asia-india-uttarakhand.webp
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
app/doxa-maps/assets/previews/asia-india-west-bengal.webp
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
app/doxa-maps/assets/previews/brazil.webp
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
app/doxa-maps/assets/previews/central-africa.webp
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
app/doxa-maps/assets/previews/city-ago--8.8484-13.2535.webp
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
app/doxa-maps/assets/previews/city-bfa-9.7792--4.2879.webp
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
app/doxa-maps/assets/previews/city-brn-4.9234-114.9209.webp
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
app/doxa-maps/assets/previews/city-btn-27.75-91.2637.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
app/doxa-maps/assets/previews/city-cod-3.5049-24.4533.webp
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
app/doxa-maps/assets/previews/city-idn--3.7191-127.9542.webp
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-10.1396-77.7883.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-10.3796-78.8202.webp
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-10.5285-76.2146.webp
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-10.7853-78.7051.webp
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-10.7855-76.6516.webp
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-10.787-79.1378.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-10.8469-76.2633.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-11.0049-76.9626.webp
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-11.0546-78.6369.webp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-11.06-76.0816.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-11.0991-77.2807.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-11.1271-78.6565.webp
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-11.253-76.2299.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-11.3548-77.711.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-11.4517-76.7145.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-11.6234-92.7265.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-11.6765-76.1741.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-11.8745-75.3695.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-11.9182-79.8085.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-11.967-75.3663.webp
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-12.2973-75.7684.webp
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-12.3022-76.6423.webp
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-12.427-75.742.webp
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-12.4538-75.1701.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-12.5102-74.9852.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-12.5446-80.0193.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-12.6867-79.9614.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-12.8403-75.2483.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-12.9125-79.3429.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-12.964-74.837.webp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-12.9789-77.5857.webp
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-13.0505-75.1773.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-13.2174-79.101.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-13.2466-80.2533.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-13.3138-75.7731.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-13.3389-74.7451.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-13.4672-79.0137.webp
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-13.6192-79.4197.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-14.4428-79.9882.webp
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-14.494-78.7992.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-14.7445-74.7282.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-14.7811-74.6161.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-14.8066-74.1305.webp
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-15.1518-75.4446.webp
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-15.2213-74.0714.webp
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-15.4573-75.0086.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-15.4895-79.6006.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-15.5127-77.9554.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-15.8971-79.7392.webp
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-16.1786-81.1347.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-16.3172-80.0518.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-16.4355-80.0228.webp
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-16.5066-80.6501.webp
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-16.6981-74.2441.webp
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-16.7107-81.0956.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-16.8296-75.7135.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-17.0598-74.68.webp
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-17.2551-78.4478.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-17.3189-82.4772.webp
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-17.4284-78.4492.webp
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-17.6602-75.908.webp
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-17.6921-83.2225.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-17.9875-82.6791.webp
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-18.1063-83.3951.webp
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-18.1085-78.9859.webp
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-18.2978-83.9127.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-18.4856-79.1748.webp
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-18.488-83.8616.webp
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-18.5347-84.0184.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-18.5355-83.5092.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-18.8207-82.6805.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
app/doxa-maps/assets/previews/city-ind-19.1051-81.9755.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |