From 095161872d93e9703a604efe929340c820b40cae Mon Sep 17 00:00:00 2001 From: kdeterme Date: Fri, 9 Oct 2026 14:31:17 +0200 Subject: [PATCH] feat: add dead tree symbology, icon, and map layer support for nature assets --- loko/assets/static/assets/asset_symbology.js | 38 +++++++++++++++---- .../static/assets/nature_tree_icon_dead.svg | 20 ++++++++++ .../assets/nature_tree_icon_regional.svg | 10 ++--- .../assets/nature_tree_icon_remarkable.svg | 4 +- loko/assets/static/assets/unified_index.js | 8 ++++ .../static/assets/unified_map_layers.js | 14 +++++-- .../templates/assets/unified_index.html | 13 ++++--- loko/assets/views/nature.py | 5 ++- 8 files changed, 88 insertions(+), 24 deletions(-) create mode 100644 loko/assets/static/assets/nature_tree_icon_dead.svg diff --git a/loko/assets/static/assets/asset_symbology.js b/loko/assets/static/assets/asset_symbology.js index d1eb61c..0ab91b9 100644 --- a/loko/assets/static/assets/asset_symbology.js +++ b/loko/assets/static/assets/asset_symbology.js @@ -264,21 +264,30 @@ naturetree_regional: { thematic: 'nature', color: '#1d4ed8', - iconUrl: '/static/assets/nature_tree_icon_regional.svg?v=20261009a', + iconUrl: '/static/assets/nature_tree_icon_regional.svg?v=20261009_round', iconSize: 56, - iconClass: 'bi-tree-fill', + iconClass: 'bi-tree', glyphCodepoint: 'f5e1', mapImage: 'icon-nature-regional', }, naturetree_remarkable: { thematic: 'nature', color: '#d97706', - iconUrl: '/static/assets/nature_tree_icon_remarkable.svg?v=20261009a', + iconUrl: '/static/assets/nature_tree_icon_remarkable.svg?v=20261009_round', iconSize: 56, - iconClass: 'bi-tree-fill', + iconClass: 'bi-tree', glyphCodepoint: 'f5e1', mapImage: 'icon-nature-remarkable', }, + naturetree_dead: { + thematic: 'nature', + color: '#6b7280', + iconUrl: '/static/assets/nature_tree_icon_dead.svg?v=20261009_round', + iconSize: 56, + iconClass: 'bi-tree', + glyphCodepoint: 'f5e1', + mapImage: 'icon-nature-dead', + }, naturetree: { thematic: 'nature', color: '#2e7d32', @@ -597,7 +606,12 @@ // 3. Specific asset_type override if (assetType === 'naturetree' || (thematic === 'nature' && (assetType === 'naturetree' || !assetType))) { - const isRemarkable = item.is_remarkable === true || item.is_remarkable === 'true'; + const isDead = item.is_dead === true || item.is_dead === 'true' || item.is_dead === 1 || + item.vitality === 'dead' || item.status === 'dead' || item.status === 'archived'; + if (isDead && ASSET_TYPE_OVERRIDES.naturetree_dead) { + return Object.assign({}, ASSET_TYPE_OVERRIDES.naturetree_dead); + } + const isRemarkable = item.is_remarkable === true || item.is_remarkable === 'true' || item.is_remarkable === 1; const isRegional = item.management_type === 'regional' || (typeof item.managing_authority === 'string' && (item.managing_authority.toLowerCase().includes('région') || item.managing_authority.toLowerCase().includes('mobilité'))); if (isRemarkable && ASSET_TYPE_OVERRIDES.naturetree_remarkable) { @@ -692,6 +706,7 @@ nature: injected.nature || THEMATIC_CONFIG.nature.iconUrl, natureregional: injected.natureregional || (ASSET_TYPE_OVERRIDES.naturetree_regional && ASSET_TYPE_OVERRIDES.naturetree_regional.iconUrl), natureremarkable: injected.natureremarkable || (ASSET_TYPE_OVERRIDES.naturetree_remarkable && ASSET_TYPE_OVERRIDES.naturetree_remarkable.iconUrl), + naturedead: injected.naturedead || (ASSET_TYPE_OVERRIDES.naturetree_dead && ASSET_TYPE_OVERRIDES.naturetree_dead.iconUrl), structures: injected.structures || THEMATIC_CONFIG.structures.iconUrl, roaddrain: injected.roaddrain || ASSET_TYPE_OVERRIDES.roaddrain.iconUrl, roadconcreteblockset: injected.roadconcreteblockset || ASSET_TYPE_OVERRIDES.roadconcreteblockset.iconUrl, @@ -717,8 +732,6 @@ { name: 'icon-trafficlightradarpole', codepoint: 'f4e0', color: '#e53935' }, { name: 'icon-sign', codepoint: 'f82b', color: '#0022ff' }, { name: 'icon-nature', codepoint: 'f5e1', color: '#2e7d32' }, - { name: 'icon-nature-regional', codepoint: 'f5e1', color: '#1d4ed8' }, - { name: 'icon-nature-remarkable', codepoint: 'f5e1', color: '#d97706' }, { name: 'icon-naturebench', codepoint: 'f5e1', color: '#2e7d32' }, { name: 'icon-natureplanter', codepoint: 'f3ce', color: '#d97706' }, { name: 'icon-naturerwiasset', codepoint: 'f30b', color: '#0277bd' }, @@ -814,6 +827,17 @@ ['==', ['slice', ['get', 'code'], 0, 7], 'CSE-BAC'], ], 'icon-natureplanter', ['==', ['get', 'asset_type'], 'naturebench'], 'icon-naturebench', + ['all', + ['any', ['==', ['get', 'asset_type'], 'naturetree'], ['==', ['get', 'thematic'], 'nature']], + ['any', + ['==', ['get', 'is_dead'], true], + ['==', ['get', 'is_dead'], 'true'], + ['==', ['get', 'is_dead'], 1], + ['==', ['get', 'status'], 'dead'], + ['==', ['get', 'status'], 'archived'], + ['==', ['get', 'vitality'], 'dead'] + ] + ], 'icon-nature-dead', ['all', ['any', ['==', ['get', 'asset_type'], 'naturetree'], ['==', ['get', 'thematic'], 'nature']], ['any', ['==', ['get', 'is_remarkable'], true], ['==', ['get', 'is_remarkable'], 'true'], ['==', ['get', 'is_remarkable'], 1]] diff --git a/loko/assets/static/assets/nature_tree_icon_dead.svg b/loko/assets/static/assets/nature_tree_icon_dead.svg new file mode 100644 index 0000000..cac81e3 --- /dev/null +++ b/loko/assets/static/assets/nature_tree_icon_dead.svg @@ -0,0 +1,20 @@ + diff --git a/loko/assets/static/assets/nature_tree_icon_regional.svg b/loko/assets/static/assets/nature_tree_icon_regional.svg index 547ddaf..a07855d 100644 --- a/loko/assets/static/assets/nature_tree_icon_regional.svg +++ b/loko/assets/static/assets/nature_tree_icon_regional.svg @@ -4,9 +4,9 @@ - - - + + + @@ -15,6 +15,6 @@ - - + + diff --git a/loko/assets/static/assets/nature_tree_icon_remarkable.svg b/loko/assets/static/assets/nature_tree_icon_remarkable.svg index 00258b2..2453db7 100644 --- a/loko/assets/static/assets/nature_tree_icon_remarkable.svg +++ b/loko/assets/static/assets/nature_tree_icon_remarkable.svg @@ -4,7 +4,7 @@ - + @@ -15,6 +15,6 @@ - + diff --git a/loko/assets/static/assets/unified_index.js b/loko/assets/static/assets/unified_index.js index 2218f18..465f66a 100644 --- a/loko/assets/static/assets/unified_index.js +++ b/loko/assets/static/assets/unified_index.js @@ -824,6 +824,12 @@ $(document).ready(function () { $('#unified-table').bootstrapTable({ columns: buildColumns(), + rowStyle: function (row) { + if (row && (row.is_dead || row.vitality === 'dead' || row.status === 'dead' || row.status === 'archived')) { + return { classes: 'text-muted opacity-75' }; + } + return {}; + }, height: calcHeight(), search: false, pagination: true, @@ -2754,6 +2760,8 @@ function loadTableData(features) { is_remarkable: p.is_remarkable || false, scientific_name: p.scientific_name || '', vernacular_name: p.vernacular_name || '', + is_dead: p.is_dead || false, + vitality: p.vitality || '', lon: p.lon, lat: p.lat, length: Number.isFinite(length) ? length : 0, diff --git a/loko/assets/static/assets/unified_map_layers.js b/loko/assets/static/assets/unified_map_layers.js index 9fd0f9b..1fab787 100644 --- a/loko/assets/static/assets/unified_map_layers.js +++ b/loko/assets/static/assets/unified_map_layers.js @@ -153,6 +153,11 @@ function loadUnifiedMapIcons(map) { .then(data => { if (!map.hasImage('icon-nature-remarkable')) map.addImage('icon-nature-remarkable', data); }) .catch(e => console.warn('unified_map_layers: could not load nature remarkable icon', e)); } + if (iconUrls.naturedead && !map.hasImage('icon-nature-dead')) { + loadNormalisedIcon(iconUrls.naturedead, 56) + .then(data => { if (!map.hasImage('icon-nature-dead')) map.addImage('icon-nature-dead', data); }) + .catch(e => console.warn('unified_map_layers: could not load nature dead icon', e)); + } // structures: dedicated bridge/tunnel SVG (52 px) if (iconUrls.structures && !map.hasImage('icon-structures')) { @@ -224,7 +229,12 @@ function loadUnifiedMapIcons(map) { // ── Bootstrap Icons glyph SDF icons (recoloured by icon-color) ────────── // codepoints and colors derived from AssetSymbology (single source of truth) - const FILE_ICON_NAMES = new Set(Object.keys(iconUrls).map(k => 'icon-' + k)); + const FILE_ICON_NAMES = new Set([ + ...Object.keys(iconUrls).map(k => 'icon-' + k), + 'icon-nature-regional', + 'icon-nature-remarkable', + 'icon-nature-dead', + ]); const GLYPH_ICONS = (typeof AssetSymbology !== 'undefined') ? AssetSymbology.getGlyphIcons() @@ -234,8 +244,6 @@ function loadUnifiedMapIcons(map) { { name: 'icon-trafficlightsequipment', codepoint: 'f1d5', color: '#331110' }, { name: 'icon-sign', codepoint: 'f82b', color: '#0022ff' }, { name: 'icon-nature', codepoint: 'f5e1', color: '#2e7d32' }, - { name: 'icon-nature-regional', codepoint: 'f5e1', color: '#1d4ed8' }, - { name: 'icon-nature-remarkable', codepoint: 'f5e1', color: '#d97706' }, { name: 'icon-structures', codepoint: 'f876', color: '#6d4c41' }, { name: 'icon-its', codepoint: 'f1d5', color: '#0288d1' }, { name: 'icon-clean', codepoint: 'f78a', color: '#5e5e5e' }, diff --git a/loko/assets/templates/assets/unified_index.html b/loko/assets/templates/assets/unified_index.html index ebe2085..897c2a4 100644 --- a/loko/assets/templates/assets/unified_index.html +++ b/loko/assets/templates/assets/unified_index.html @@ -1353,9 +1353,10 @@ trafficlightelectricalcabinet: "{% static 'assets/electrical-panel.png' %}", publiclighting: "{% static 'assets/public_lamp_post_icon.svg' %}?v=20260521c", publiclightingelectricalcabinet: "{% static 'assets/electrical-panel.png' %}", - nature: "{% static 'assets/nature_tree_icon.svg' %}?v=20260521a", - natureregional: "{% static 'assets/nature_tree_icon_regional.svg' %}?v=20261009a", - natureremarkable: "{% static 'assets/nature_tree_icon_remarkable.svg' %}?v=20261009a", + nature: "{% static 'assets/nature_tree_icon.svg' %}?v=20261009_round", + natureregional: "{% static 'assets/nature_tree_icon_regional.svg' %}?v=20261009_round", + natureremarkable: "{% static 'assets/nature_tree_icon_remarkable.svg' %}?v=20261009_round", + naturedead: "{% static 'assets/nature_tree_icon_dead.svg' %}?v=20261009_round", structures: "{% static 'assets/structures_bridge_tunnel_icon.svg' %}?v=20260522b", roaddrain: "{% static 'assets/roaddrain_grille_icon.svg' %}?v=20260521a", speedbump: "{% static 'assets/road_speedbump_icon.svg' %}?v=20260920", @@ -1372,7 +1373,7 @@ - - - + + + {% endblock script %} \ No newline at end of file diff --git a/loko/assets/views/nature.py b/loko/assets/views/nature.py index 8d2f941..e8d1c4a 100644 --- a/loko/assets/views/nature.py +++ b/loko/assets/views/nature.py @@ -721,6 +721,8 @@ def nature_assets_geojson(request): "is_remarkable": obj.get('is_remarkable', False), "scientific_name": obj.get('scientific_name') or '', "vernacular_name": obj.get('vernacular_name') or '', + "is_dead": bool(obj.get('is_dead') or obj.get('vitality') == 'dead' or obj.get('status') in ('dead', 'archived')), + "vitality": obj.get('vitality') or '', } } @@ -916,7 +918,8 @@ def nature_assets_geojson(request): 'category_name', 'model_name', 'color', 'geojson', 'category_id', 'model_id', 'location_lon', 'location_lat', 'managing_authority', 'management_type', 'is_remarkable', - 'scientific_name', 'vernacular_name' + 'scientific_name', 'vernacular_name', + 'is_dead', 'vitality' ) .order_by('code') )[:MAX_ASSET_FEATURES + 1]