diff --git a/cmd/webserver.go b/cmd/webserver.go
index 2366942f..a314944f 100644
--- a/cmd/webserver.go
+++ b/cmd/webserver.go
@@ -160,6 +160,7 @@ func startWebServer(c *cli.Context) error {
config.MapProvider == settings.OpenTopoMapProvider ||
config.MapProvider == settings.OPNVKarteMapProvider ||
config.MapProvider == settings.CyclOSMMapProvider ||
+ config.MapProvider == settings.CartoDBMapProvider ||
config.MapProvider == settings.TomTomMapProvider ||
config.MapProvider == settings.CustomProvider {
proxyRoute.GET("/map/tile/:zoomLevel/:coordinateX/:fileName", bindProxy(api.MapImages.MapTileImageProxyHandler))
diff --git a/conf/ezbookkeeping.ini b/conf/ezbookkeeping.ini
index e306545b..34b40fc7 100644
--- a/conf/ezbookkeeping.ini
+++ b/conf/ezbookkeeping.ini
@@ -153,6 +153,7 @@ enable_export = true
# "opentopomap": https://opentopomap.org
# "opnvkarte": https://publictransportmap.org
# "cyclosm": https://www.cyclosm.org
+# "cartodb": https://carto.com/basemaps
# "tomtom": https://www.tomtom.com
# "googlemap": https://map.google.com
# "baidumap": https://map.baidu.com
@@ -161,7 +162,7 @@ enable_export = true
# Leave blank if you want to disable map
map_provider = openstreetmap
-# Set to true to use the ezbookkeeping server to proxy map data requests, for "openstreetmap", "openstreetmap_humanitarian", "opentopomap", "opnvkarte", "cyclosm", "tomtom" or "custom"
+# Set to true to use the ezbookkeeping server to proxy map data requests, for "openstreetmap", "openstreetmap_humanitarian", "opentopomap", "opnvkarte", "cyclosm", "cartodb", "tomtom" or "custom"
map_data_fetch_proxy = false
# For "tomtom" only, TomTom map API key, please visit https://developer.tomtom.com/how-to-get-tomtom-api-key
diff --git a/pkg/api/map_image_proxies.go b/pkg/api/map_image_proxies.go
index 13796959..09e315c6 100644
--- a/pkg/api/map_image_proxies.go
+++ b/pkg/api/map_image_proxies.go
@@ -11,12 +11,13 @@ import (
"github.com/mayswind/ezbookkeeping/pkg/settings"
)
-const openStreetMapTileImageUrlFormat = "https://tile.openstreetmap.org/{z}/{x}/{y}.png" // https://tile.openstreetmap.org/{z}/{x}/{y}.png
-const openStreetMapHumanitarianStyleTileImageUrlFormat = "https://a.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png" // https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png
-const openTopoMapTileImageUrlFormat = "https://tile.opentopomap.org/{z}/{x}/{y}.png" // https://tile.opentopomap.org/{z}/{x}/{y}.png
-const opnvKarteMapTileImageUrlFormat = "https://tileserver.memomaps.de/tilegen/{z}/{x}/{y}.png" // https://tileserver.memomaps.de/tilegen/{z}/{x}/{y}.png
-const cyclOSMMapTileImageUrlFormat = "https://a.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png" // https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png
-const tomtomMapTileImageUrlFormat = "https://api.tomtom.com/map/1/tile/basic/main/{z}/{x}/{y}.png" // https://api.tomtom.com/map/{versionNumber}/tile/{layer}/{style}/{z}/{x}/{y}.png?key={key}&language={language}
+const openStreetMapTileImageUrlFormat = "https://tile.openstreetmap.org/{z}/{x}/{y}.png" // https://tile.openstreetmap.org/{z}/{x}/{y}.png
+const openStreetMapHumanitarianStyleTileImageUrlFormat = "https://a.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png" // https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png
+const openTopoMapTileImageUrlFormat = "https://tile.opentopomap.org/{z}/{x}/{y}.png" // https://tile.opentopomap.org/{z}/{x}/{y}.png
+const opnvKarteMapTileImageUrlFormat = "https://tileserver.memomaps.de/tilegen/{z}/{x}/{y}.png" // https://tileserver.memomaps.de/tilegen/{z}/{x}/{y}.png
+const cyclOSMMapTileImageUrlFormat = "https://a.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png" // https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png
+const cartoDBMapTileImageUrlFormat = "https://a.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{scale}.png" // https://{s}.basemaps.cartocdn.com/{style}/{z}/{x}/{y}{scale}.png
+const tomtomMapTileImageUrlFormat = "https://api.tomtom.com/map/1/tile/basic/main/{z}/{x}/{y}.png" // https://api.tomtom.com/map/{versionNumber}/tile/{layer}/{style}/{z}/{x}/{y}.png?key={key}&language={language}
// MapImageProxy represents map image proxy
type MapImageProxy struct {
@@ -41,6 +42,7 @@ func (p *MapImageProxy) MapTileImageProxyHandler(c *core.Context) (*httputil.Rev
fileName := c.Param("fileName")
fileNameParts := strings.Split(fileName, ".")
coordinateY := fileNameParts[0]
+ scale := c.Query("scale")
if len(fileNameParts) != 2 || fileNameParts[len(fileNameParts)-1] != "png" {
return nil, errs.ErrImageExtensionNotSupported
@@ -56,6 +58,8 @@ func (p *MapImageProxy) MapTileImageProxyHandler(c *core.Context) (*httputil.Rev
targetUrl = opnvKarteMapTileImageUrlFormat
} else if mapProvider == settings.CyclOSMMapProvider {
targetUrl = cyclOSMMapTileImageUrlFormat
+ } else if mapProvider == settings.CartoDBMapProvider {
+ targetUrl = cartoDBMapTileImageUrlFormat
} else if mapProvider == settings.TomTomMapProvider {
targetUrl = tomtomMapTileImageUrlFormat + "?key=" + settings.Container.Current.TomTomMapAPIKey
language := c.Query("language")
@@ -74,6 +78,7 @@ func (p *MapImageProxy) MapTileImageProxyHandler(c *core.Context) (*httputil.Rev
imageRawUrl = strings.Replace(imageRawUrl, "{z}", zoomLevel, -1)
imageRawUrl = strings.Replace(imageRawUrl, "{x}", coordinateX, -1)
imageRawUrl = strings.Replace(imageRawUrl, "{y}", coordinateY, -1)
+ imageRawUrl = strings.Replace(imageRawUrl, "{scale}", scale, -1)
imageUrl, _ := url.Parse(imageRawUrl)
req.URL = imageUrl
diff --git a/pkg/middlewares/server_settings_cookie.go b/pkg/middlewares/server_settings_cookie.go
index b17f4592..5290964b 100644
--- a/pkg/middlewares/server_settings_cookie.go
+++ b/pkg/middlewares/server_settings_cookie.go
@@ -29,6 +29,7 @@ func ServerSettingsCookie(config *settings.Config) core.MiddlewareHandlerFunc {
config.MapProvider == settings.OpenTopoMapProvider ||
config.MapProvider == settings.OPNVKarteMapProvider ||
config.MapProvider == settings.CyclOSMMapProvider ||
+ config.MapProvider == settings.CartoDBMapProvider ||
config.MapProvider == settings.TomTomMapProvider ||
config.MapProvider == settings.CustomProvider) {
settingsArr = append(settingsArr, buildBooleanSetting("mp", config.EnableMapDataFetchProxy))
diff --git a/pkg/settings/setting.go b/pkg/settings/setting.go
index 6c6c6508..48db9d7b 100644
--- a/pkg/settings/setting.go
+++ b/pkg/settings/setting.go
@@ -74,8 +74,9 @@ const (
OpenTopoMapProvider string = "opentopomap"
OPNVKarteMapProvider string = "opnvkarte"
CyclOSMMapProvider string = "cyclosm"
- GoogleMapProvider string = "googlemap"
+ CartoDBMapProvider string = "cartodb"
TomTomMapProvider string = "tomtom"
+ GoogleMapProvider string = "googlemap"
BaiduMapProvider string = "baidumap"
AmapProvider string = "amap"
CustomProvider string = "custom"
@@ -541,10 +542,12 @@ func loadMapConfiguration(config *Config, configFile *ini.File, sectionName stri
config.MapProvider = OPNVKarteMapProvider
} else if mapProvider == CyclOSMMapProvider {
config.MapProvider = CyclOSMMapProvider
- } else if mapProvider == GoogleMapProvider {
- config.MapProvider = GoogleMapProvider
+ } else if mapProvider == CartoDBMapProvider {
+ config.MapProvider = CartoDBMapProvider
} else if mapProvider == TomTomMapProvider {
config.MapProvider = TomTomMapProvider
+ } else if mapProvider == GoogleMapProvider {
+ config.MapProvider = GoogleMapProvider
} else if mapProvider == BaiduMapProvider {
config.MapProvider = BaiduMapProvider
} else if mapProvider == AmapProvider {
diff --git a/src/consts/map.js b/src/consts/map.js
index 3e51e29d..0a4e422f 100644
--- a/src/consts/map.js
+++ b/src/consts/map.js
@@ -39,6 +39,14 @@ const leafletTileSources = {
defaultZoomLevel: 14,
attribution : 'CyclOSM | Map data: © OpenStreetMap contributors'
},
+ 'cartodb': {
+ tileUrlFormat: 'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png',
+ tileUrlSubDomains: 'abcd',
+ minZoom: 1,
+ maxZoom: 20,
+ defaultZoomLevel: 14,
+ attribution : '© OpenStreetMap, © CARTO'
+ },
'tomtom': {
tileUrlFormat: 'https://{s}.api.tomtom.com/map/1/tile/basic/main/{z}/{x}/{y}.png',
tileUrlSubDomains: 'abcd',