From 2f82dd981d337b4298e56d8239db232f3392ea6a Mon Sep 17 00:00:00 2001 From: Gwendolyn Date: Tue, 17 Sep 2024 19:31:38 +0200 Subject: [PATCH] leaflet marker theming --- src/c3nav/editor/forms.py | 1 + ...e_icon_path_theme_leaflet_marker_config.py | 23 +++++++ src/c3nav/mapdata/models/theme.py | 3 + src/c3nav/site/static/site/js/c3nav.js | 57 +++++++++++------- src/c3nav/site/themes.py | 4 ++ .../static/img/marker-icon-default-2x.png | Bin 0 -> 2586 bytes src/c3nav/static/img/marker-icon-default.png | Bin 0 -> 1466 bytes src/c3nav/static/img/marker-shadow.png | Bin 0 -> 618 bytes 8 files changed, 67 insertions(+), 21 deletions(-) create mode 100644 src/c3nav/mapdata/migrations/0110_theme_icon_path_theme_leaflet_marker_config.py create mode 100644 src/c3nav/static/img/marker-icon-default-2x.png create mode 100644 src/c3nav/static/img/marker-icon-default.png create mode 100644 src/c3nav/static/img/marker-shadow.png diff --git a/src/c3nav/editor/forms.py b/src/c3nav/editor/forms.py index c5632a70..6935ec37 100644 --- a/src/c3nav/editor/forms.py +++ b/src/c3nav/editor/forms.py @@ -436,6 +436,7 @@ def create_editor_form(editor_model): 'color_css_header_text', 'color_css_header_text_hover', 'color_css_shadow', 'color_css_overlay_background', 'color_css_grid', 'color_css_modal_backdrop', 'color_css_route_dots_shadow', 'extra_css', + 'icon_path', 'leaflet_marker_config', 'color_background', 'color_wall_fill', 'color_wall_border', 'color_door_fill', 'color_ground_fill', 'color_obstacles_default_fill', 'color_obstacles_default_border', ] diff --git a/src/c3nav/mapdata/migrations/0110_theme_icon_path_theme_leaflet_marker_config.py b/src/c3nav/mapdata/migrations/0110_theme_icon_path_theme_leaflet_marker_config.py new file mode 100644 index 00000000..a7b0cfc6 --- /dev/null +++ b/src/c3nav/mapdata/migrations/0110_theme_icon_path_theme_leaflet_marker_config.py @@ -0,0 +1,23 @@ +# Generated by Django 5.0.8 on 2024-09-17 17:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mapdata', '0109_accesspermissionssogrant_accesspermission_sso_grant'), + ] + + operations = [ + migrations.AddField( + model_name='theme', + name='icon_path', + field=models.CharField(blank=True, default='', max_length=255, verbose_name='Root path for icon images'), + ), + migrations.AddField( + model_name='theme', + name='leaflet_marker_config', + field=models.TextField(blank=True, default='', verbose_name='Leaflet marker config override'), + ), + ] diff --git a/src/c3nav/mapdata/models/theme.py b/src/c3nav/mapdata/models/theme.py index 88cc2c9e..8cdf1182 100644 --- a/src/c3nav/mapdata/models/theme.py +++ b/src/c3nav/mapdata/models/theme.py @@ -45,6 +45,9 @@ class Theme(TitledMixin, models.Model): verbose_name=_('CSS route dots shadow color')) extra_css = models.TextField(default='', blank=True, verbose_name=_('Extra CSS')) + icon_path = models.CharField(default='', blank=True, max_length=255, verbose_name=_('Root path for icon images')) + leaflet_marker_config = models.TextField(default='', blank=True, verbose_name=_('Leaflet marker config override')) + color_background = models.CharField(max_length=32, blank=True, verbose_name=_('background color')) color_wall_fill = models.CharField(max_length=32, blank=True, verbose_name=_('wall fill color')) color_wall_border = models.CharField(max_length=32, blank=True, verbose_name=_('wall border color')) diff --git a/src/c3nav/site/static/site/js/c3nav.js b/src/c3nav/site/static/site/js/c3nav.js index fa7f8b8e..8030ff9a 100644 --- a/src/c3nav/site/static/site/js/c3nav.js +++ b/src/c3nav/site/static/site/js/c3nav.js @@ -1346,7 +1346,7 @@ c3nav = { _modal_link_click: function (e) { var location = $(this).attr('href'); if ($(this).is('[target]') || c3nav._href_modal_open_tab(location)) { - if(!$(this).is('[target]')) $(this).attr('target', '_blank'); + if (!$(this).is('[target]')) $(this).attr('target', '_blank'); return; } e.preventDefault(); @@ -1436,9 +1436,7 @@ c3nav = { // set up icons L.Icon.Default.imagePath = '/static/leaflet/images/'; - c3nav._add_icon('origin'); - c3nav._add_icon('destination'); - c3nav._add_icon('nearby'); + c3nav.create_icons(); // setup scale control L.control.scale({imperial: false}).addTo(c3nav.map); @@ -1502,6 +1500,8 @@ c3nav = { document.querySelector('#theme-color-meta-dark').content = theme.theme_color_dark; document.querySelector('#theme-color-meta-light').content = theme.theme_color_light; + c3nav.create_icons(); + c3nav._levelControl.setTheme(id); c3nav.create_key(id); }, @@ -1601,17 +1601,32 @@ c3nav = { c3nav.update_map_state(); c3nav.update_location_labels(); }, - _add_icon: function (name) { - c3nav[name + 'Icon'] = new L.Icon({ - iconUrl: '/static/img/marker-icon-' + name + '.png', - iconRetinaUrl: '/static/img/marker-icon-' + name + '-2x.png', - shadowUrl: '/static/leaflet/images/marker-shadow.png', - iconSize: [25, 41], - iconAnchor: [12, 41], - popupAnchor: [1, -34], - tooltipAnchor: [16, -28], - shadowSize: [41, 41] - }); + icons: {}, + create_icons: function () { + const theme = c3nav.themes[c3nav.theme]; + let rootPath = theme.icon_path; + let config = theme.marker_config ? JSON.parse(theme.marker_config) : null; + if (!rootPath) { + rootPath = '/static/img/'; + } + if (!config) { + config = {}; + } + c3nav.icons = {}; + for (const name of ['default', 'origin', 'destination', 'nearby']) { + c3nav.icons[name] = new L.Icon({ + iconUrl: rootPath + 'marker-icon-' + name + '.png', + iconRetinaUrl: rootPath + 'marker-icon-' + name + '-2x.png', + shadowUrl: rootPath + 'marker-shadow.png', + iconSize: [25, 41], + iconAnchor: [12, 41], + popupAnchor: [1, -34], + tooltipAnchor: [16, -28], + shadowSize: [41, 41], + ...config, + }); + } + }, visible_map_locations: [], update_map_locations: function () { @@ -1624,24 +1639,24 @@ c3nav = { c3nav._locationLayers[level_id].clearLayers() } c3nav._visible_map_locations = []; - if (origin) c3nav._merge_bounds(bounds, c3nav._add_location_to_map(origin, single ? new L.Icon.Default() : c3nav.originIcon)); - if (destination) c3nav._merge_bounds(bounds, c3nav._add_location_to_map(destination, single ? new L.Icon.Default() : c3nav.destinationIcon)); + if (origin) c3nav._merge_bounds(bounds, c3nav._add_location_to_map(origin, single ? c3nav.icons.default : c3nav.icons.origin)); + if (destination) c3nav._merge_bounds(bounds, c3nav._add_location_to_map(destination, single ? c3nav.icons.default : c3nav.icons.destination)); var done = []; if (c3nav.state.nearby && destination && 'areas' in destination) { if (destination.space) { - c3nav._merge_bounds(bounds, c3nav._add_location_to_map(c3nav.locations_by_id[destination.space], c3nav.nearbyIcon, true)); + c3nav._merge_bounds(bounds, c3nav._add_location_to_map(c3nav.locations_by_id[destination.space], c3nav.icons.nearby, true)); } if (destination.near_area) { done.push(destination.near_area); - c3nav._merge_bounds(bounds, c3nav._add_location_to_map(c3nav.locations_by_id[destination.near_area], c3nav.nearbyIcon, true)); + c3nav._merge_bounds(bounds, c3nav._add_location_to_map(c3nav.locations_by_id[destination.near_area], c3nav.icons.nearby, true)); } for (var area of destination.areas) { done.push(area); - c3nav._merge_bounds(bounds, c3nav._add_location_to_map(c3nav.locations_by_id[area], c3nav.nearbyIcon, true)); + c3nav._merge_bounds(bounds, c3nav._add_location_to_map(c3nav.locations_by_id[area], c3nav.icons.nearby, true)); } for (var location of destination.nearby) { if (location in done) continue; - c3nav._merge_bounds(bounds, c3nav._add_location_to_map(c3nav.locations_by_id[location], c3nav.nearbyIcon, true)); + c3nav._merge_bounds(bounds, c3nav._add_location_to_map(c3nav.locations_by_id[location], c3nav.icons.nearby, true)); } } c3nav._locationLayerBounds = bounds; diff --git a/src/c3nav/site/themes.py b/src/c3nav/site/themes.py index 149a1227..cd207125 100644 --- a/src/c3nav/site/themes.py +++ b/src/c3nav/site/themes.py @@ -82,6 +82,10 @@ def make_themes(theme_models): 'randomize_primary_color': theme.randomize_primary_color, 'primary_color': primary_color, } + if theme.icon_path: + themes[theme.pk]['icon_path'] = theme.icon_path + if theme.leaflet_marker_config: + themes[theme.pk]['marker_config'] = theme.leaflet_marker_config if theme.default: default_theme = { 'css_vars': css_code, diff --git a/src/c3nav/static/img/marker-icon-default-2x.png b/src/c3nav/static/img/marker-icon-default-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e4abba3b511d14752426e8cbadae03c1e5fe15fb GIT binary patch literal 2586 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 UQO-*oc+)|Q_08}VdXD6O0C*xx%>V!Z literal 0 HcmV?d00001 diff --git a/src/c3nav/static/img/marker-icon-default.png b/src/c3nav/static/img/marker-icon-default.png new file mode 100644 index 0000000000000000000000000000000000000000..950edf24677ded147df13b26f91baa2b0fa70513 GIT binary patch literal 1466 zcmV;r1x5OaP)P001cn1^@s6z>|W`000GnNklGNuHDcIX17Zdjl&3`L?0sTjIws<{((Dh&g-s0<@jYQyl?D*X^?%13;ml^gy> ziMrY_^1WI=(g@LMizu=zCoA>C`6|QEq1eV92k*7m>G65*&@&6)aC&e}G zI)pf-Za|N`DT&Cn1J|o`19mumxW~hiKiKyc-P`S@q)rdTo84@QI@;0yXrG%9uhI>A zG5QHb6s4=<6xy{1 z@NMxEkryp{LS44%z$3lP^cX!9+2-;CTt3wM4(k*#C{aiIiLuB>jJj;KPhPzIC00bL zU3a#;aJld94lCW=`4&aAy8M7PY=HQ>O%$YEP4c4UY#CRxfgbE~(|uiI=YS8q;O9y6 zmIkXzR`}p7ti|PrM3a}WMnR=3NVnWdAAR>b9X@)DKL6=YsvmH%?I24wdq?Gh54_;# z$?_LvgjEdspdQlft#4CQ z`2Zyvy?*)N1Ftw|{_hakhG9WjS?Az@I@+IZ8JbWewR!XUK4&6346+d#~gsE0SY(LX8&JfY>Aj)RxGy96nwhs2rv zzW6pTnMpFkDSkT*a*6Dx|u@ds6ISVn0@^RmIsKZ5Y;bazbc;tTSq(kg(=481ODrPyNB6n z-$+U}(w$m6U6H$w17Bw+wDaFIe~GvNMYvnw31MpY0eQKT9l>SU``8k7w4)z!GZKMI z#_cEKq7k~i%nlK@6c-K?+R;B#5$?T#YpKD`t_4bAs^#E+@5QW$@OX3*`;(#{U^d-vY)&xEE>n5lYl&T?Amke9$Lam@{1K@O ze*LXqlKQHiv=gx+V^Cbb2?z@ISBQ*3amF;9UJ3SBg(N|710TLamQmYZ&Qjn2LuO<* zCZlB4n%@pc&7NNnY1}x+NWpHlq`OJEo|`aYN9<`RBUB+79g;>dgb6YlfN#kGL?lO_ z!6~M^7sOnbsUkKk<@Ysie&`G>ruxH&Mgy&8;i=A zB9OO!xR{AyODw>DS-q5YM{0ExFEAzt zm>RdS+ssW(-8|?xr0(?$vBVB*%(xDLtq3Hf0I5yFm<_g=W2`QWAax{1rWVH=I!VrP zs(rTFX@W#t$hXNvbgX`gK&^w_YD;CQ!B@e0QbLIWaKAXQe2-kkloo;{iF#6}z!4=W zi$giRj1{ zt;2w`VSCF#WE&*ev7jpsC=6175@(~nTE2;7M-L((0bH@yG}-TB$R~WXd?tA$s3|%y zA`9$sA(>F%J3ioz<-LJl*^o1|w84l>HBR`>3l9c8$5Xr@xCiIQ7{x$fMCzOk_-M=% z+{a_Q#;42`#KfUte@$NT77uaTz?b-fBe)1s5XE$yA79fm?KqM^VgLXD07*qoM6N<$ Ef<_J(9smFU literal 0 HcmV?d00001