From 3ffb6179700cfc37bee1ec8ee497fe29cb4f9067 Mon Sep 17 00:00:00 2001 From: AI Assistant Date: Tue, 24 Mar 2026 11:23:05 +0200 Subject: [PATCH] fix(geoportal): font 404s + slim tile views for performance - Labels: add text-font ["Noto Sans Regular"] (OpenFreeMap compatible) - Optimize views: gis_features/terenuri/cladiri/administrativ now exclude attributes, enrichment, timestamps (huge JSON columns that made tiles slow) - Views only include: id, layer_id, siruta, object_id, cadastral_ref, area_value, is_active, geom Run optimize-views again after deploy to apply slimmer views. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/app/api/geoportal/optimize-views/route.ts | 20 ++++++++++++++++++- .../geoportal/components/map-viewer.tsx | 5 +++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/app/api/geoportal/optimize-views/route.ts b/src/app/api/geoportal/optimize-views/route.ts index 939afa2..92dac0b 100644 --- a/src/app/api/geoportal/optimize-views/route.ts +++ b/src/app/api/geoportal/optimize-views/route.ts @@ -92,7 +92,25 @@ const STEPS = [ sql: `CREATE OR REPLACE VIEW gis_uats AS SELECT siruta, name, county, geom_z8 AS geom FROM "GisUat" WHERE geom_z8 IS NOT NULL`, }, - // 6. Update trigger to also compute simplified geoms on INSERT/UPDATE + // 6. Slim down gis_terenuri/cladiri views (drop huge attributes/enrichment JSON columns) + { + name: "Optimize gis_features view (slim columns)", + sql: `CREATE OR REPLACE VIEW gis_features AS SELECT id, "layerId" AS layer_id, siruta, "objectId" AS object_id, "cadastralRef" AS cadastral_ref, "areaValue" AS area_value, "isActive" AS is_active, geom FROM "GisFeature" WHERE geom IS NOT NULL`, + }, + { + name: "Optimize gis_terenuri view", + sql: `CREATE OR REPLACE VIEW gis_terenuri AS SELECT * FROM gis_features WHERE layer_id LIKE 'TERENURI%' OR layer_id LIKE 'CADGEN_LAND%'`, + }, + { + name: "Optimize gis_cladiri view", + sql: `CREATE OR REPLACE VIEW gis_cladiri AS SELECT * FROM gis_features WHERE layer_id LIKE 'CLADIRI%' OR layer_id LIKE 'CADGEN_BUILDING%'`, + }, + { + name: "Optimize gis_administrativ view", + sql: `CREATE OR REPLACE VIEW gis_administrativ AS SELECT * FROM gis_features WHERE layer_id LIKE 'LIMITE%' OR layer_id LIKE 'SPECIAL_AREAS%'`, + }, + + // 7. Update trigger to also compute simplified geoms on INSERT/UPDATE { name: "Update trigger to pre-compute simplified geoms", sql: `CREATE OR REPLACE FUNCTION gis_uat_sync_geom() RETURNS TRIGGER AS $$ BEGIN IF NEW.geometry IS NOT NULL THEN BEGIN NEW.geom := gis_uat_esri_to_geom(NEW.geometry::jsonb); IF NEW.geom IS NOT NULL THEN NEW.geom_z0 := ST_SimplifyPreserveTopology(NEW.geom, 2000); NEW.geom_z5 := ST_SimplifyPreserveTopology(NEW.geom, 500); NEW.geom_z8 := ST_SimplifyPreserveTopology(NEW.geom, 50); END IF; EXCEPTION WHEN OTHERS THEN NEW.geom := NULL; NEW.geom_z0 := NULL; NEW.geom_z5 := NULL; NEW.geom_z8 := NULL; END; ELSE NEW.geom := NULL; NEW.geom_z0 := NULL; NEW.geom_z5 := NULL; NEW.geom_z8 := NULL; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql`, diff --git a/src/modules/geoportal/components/map-viewer.tsx b/src/modules/geoportal/components/map-viewer.tsx index 3d8e93d..42a5bcc 100644 --- a/src/modules/geoportal/components/map-viewer.tsx +++ b/src/modules/geoportal/components/map-viewer.tsx @@ -381,7 +381,7 @@ export const MapViewer = forwardRef( map.addLayer({ id: LAYER_IDS.uatsZ8Line, type: "line", source: SOURCES.uatsZ8, "source-layer": SOURCES.uatsZ8, minzoom: 8, maxzoom: 12, paint: { "line-color": "#7c3aed", "line-width": 1 } }); map.addLayer({ id: LAYER_IDS.uatsZ8Label, type: "symbol", source: SOURCES.uatsZ8, "source-layer": SOURCES.uatsZ8, minzoom: 9, maxzoom: 12, - layout: { "text-field": ["coalesce", ["get", "name"], ""], "text-size": 10, "text-anchor": "center", "text-allow-overlap": false }, + layout: { "text-field": ["coalesce", ["get", "name"], ""], "text-font": ["Noto Sans Regular"], "text-size": 10, "text-anchor": "center", "text-allow-overlap": false }, paint: { "text-color": "#5b21b6", "text-halo-color": "#fff", "text-halo-width": 1.5 } }); // === UAT z12+: full detail (no simplification) === @@ -391,7 +391,7 @@ export const MapViewer = forwardRef( map.addLayer({ id: LAYER_IDS.uatsZ12Line, type: "line", source: SOURCES.uatsZ12, "source-layer": SOURCES.uatsZ12, minzoom: 12, paint: { "line-color": "#7c3aed", "line-width": 2 } }); map.addLayer({ id: LAYER_IDS.uatsZ12Label, type: "symbol", source: SOURCES.uatsZ12, "source-layer": SOURCES.uatsZ12, minzoom: 12, - layout: { "text-field": ["coalesce", ["get", "name"], ""], "text-size": 13, "text-anchor": "center", "text-allow-overlap": false }, + layout: { "text-field": ["coalesce", ["get", "name"], ""], "text-font": ["Noto Sans Regular"], "text-size": 13, "text-anchor": "center", "text-allow-overlap": false }, paint: { "text-color": "#5b21b6", "text-halo-color": "#fff", "text-halo-width": 1.5 } }); // === Intravilan — double line (black outer + orange inner), no fill, z13+ === @@ -411,6 +411,7 @@ export const MapViewer = forwardRef( map.addLayer({ id: LAYER_IDS.terenuriLabel, type: "symbol", source: SOURCES.terenuri, "source-layer": SOURCES.terenuri, minzoom: 16, layout: { "text-field": ["coalesce", ["get", "cadastral_ref"], ""], + "text-font": ["Noto Sans Regular"], "text-size": 10, "text-anchor": "center", "text-allow-overlap": false, "text-max-width": 8, },