Merge branch 'master' into feature/favorite_summits

pull/12/head
Manuel Kasper 2022-08-22 10:28:36 +02:00
commit 3d0da6ca54
60 zmienionych plików z 42126 dodań i 8367 usunięć

5
.env 100644
Wyświetl plik

@ -0,0 +1,5 @@
VUE_APP_API_URL="https://api.sotl.as"
VUE_APP_WSS_URL="wss://api.sotl.as"
VUE_APP_PHOTOS_URL="https://photos.sotl.as"
VUE_APP_PHOTOS_ORIGINAL_URL="https://sotlas-photos.s3.eu-central-003.backblazeb2.com/original"
VUE_APP_ELEVATION_API_URL="https://ele.sotl.as/api"

39580
package-lock.json wygenerowano

Plik diff jest za duży Load Diff

Wyświetl plik

@ -4,6 +4,7 @@
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"prebuild": "vsvg -s ./svg-icons -t ./src/compiled-icons",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"generate-icons": "vsvg -s ./svg-icons -t ./src/compiled-icons",
@ -21,7 +22,7 @@
"@mapbox/mapbox-gl-draw": "github:manuelkasper/mapbox-gl-draw#sotlas",
"@mapbox/togeojson": "^0.16.0",
"@tmcw/togeojson": "^3.2.0",
"axios": "^0.21.1",
"axios": "^0.27.2",
"buefy": "^0.8.20",
"cheap-ruler": "^2.5.1",
"core-js": "^2.6.12",
@ -35,17 +36,18 @@
"moment": "^2.29.1",
"node-vincenty": "0.0.6",
"photoswipe": "^4.1.3",
"proj4": "^2.7.2",
"togpx": "^0.5.4",
"vue": "^2.6.12",
"vue": "^2.7.8",
"vue-clipboard2": "^0.3.1",
"vue-debounce": "^2.6.0",
"vue-filepond": "^6.0.3",
"vue-infinite-loading": "^2.4.5",
"vue-lazy-youtube-video": "^2.3.0",
"vue-mapbox": "github:manuelkasper/vue-mapbox#fix-layer-remove",
"vue-mapbox": "github:manuelkasper/vue-mapbox#sotlas",
"vue-match-media": "^1.0.3",
"vue-native-websocket": "^2.0.14",
"vue-router": "^3.5.1",
"vue-native-websocket": "^2.0.15",
"vue-router": "^3.5.4",
"vuedraggable": "^2.24.3",
"vuex": "^3.6.2"
},
@ -58,8 +60,8 @@
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.2.3",
"git-revision-webpack-plugin": "^3.0.6",
"node-sass": "^4.14.1",
"sass-loader": "^7.3.1",
"node-sass": "^6.0.1",
"sass-loader": "^10.3.1",
"vue-svgicon": "^3.2.9",
"vue-template-compiler": "^2.6.12"
},

Wyświetl plik

@ -0,0 +1,324 @@
{
"version": 8,
"name": "norkart",
"metadata": {"maputnik:renderer": "mbgljs", "openmaptiles:version": "3.x"},
"center": [15.956668, 65.400009],
"zoom": 4,
"bearing": 0,
"pitch": 0,
"sources": {
"norkart": {
"type": "raster",
"tiles": [
"https://opencache.statkart.no/gatekeeper/gk/gk.open_gmaps?layers=topo4&zoom={z}&x={x}&y={y}"
],
"tileSize": 256,
"maxzoom": 20,
"bounds": [2, 57, 33, 72],
"attribution": "© Kartverket"
},
"summits": {
"type": "vector",
"url": "https://1.{mapServer}.map.sotl.as/data/summits.json"
},
"summits_inactive": {
"type": "vector",
"url": "https://1.{mapServer}.map.sotl.as/data/summits_inactive.json"
},
"regions": {
"type": "vector",
"url": "https://1.{mapServer}.map.sotl.as/data/regions.json"
},
"az": {
"type": "vector",
"url": "https://1.{mapServer}.map.sotl.as/data/az.json"
}
},
"sprite": "https://sotl.as/sprites",
"glyphs": "https://0.{mapServer}.map.sotl.as/fonts/{fontstack}/{range}.pbf",
"transition": {},
"layers": [
{
"id": "background",
"type": "background",
"layout": {"visibility": "visible"},
"paint": {"background-color": "rgba(255, 255, 255, 1)"}
},
{
"id": "norkart",
"type": "raster",
"source": "norkart",
"layout": {"visibility": "visible"},
"paint": {
"raster-opacity": 0.75,
"raster-resampling": "linear"
}
},
{
"id": "summits_az",
"type": "fill",
"metadata": {
"sotlas-map-option": "az"
},
"source": "az",
"source-layer": "az",
"layout": {"visibility": "none"},
"minzoom": 12,
"paint": {
"fill-antialias": false,
"fill-color": "rgba(255, 255, 0, 1)",
"fill-opacity": {"stops": [[12, 0], [12.5, 0.5]]}
}
},
{
"id": "summits_az_border",
"type": "line",
"metadata": {
"sotlas-map-option": "az"
},
"source": "az",
"source-layer": "az",
"layout": {"visibility": "none"},
"minzoom": 12,
"paint": {
"line-color": "rgba(235, 196, 0, 1)",
"line-opacity": {"stops": [[12, 0], [12.5, 0.5]]},
"line-width": {"stops": [[12, 1], [16, 3]]}
}
},
{
"id": "summits_selected",
"type": "circle",
"source": "summits",
"source-layer": "summits",
"filter": ["all", ["in", "code"]],
"layout": {"visibility": "visible"},
"paint": {
"circle-color": "rgba(2, 153, 243, 1)",
"circle-radius": {"stops": [[6, 15], [20, 50]]},
"circle-opacity": 0.75,
"circle-stroke-color": "rgba(210, 255, 0, 0.05)",
"circle-stroke-width": 0,
"circle-stroke-opacity": 1,
"circle-blur": 0.7
}
},
{
"id": "summits_names",
"type": "symbol",
"source": "summits",
"source-layer": "summits",
"minzoom": 10,
"maxzoom": 24,
"filter": ["all", ["in", "code"]],
"layout": {
"visibility": "visible",
"text-field": "{name}\n{code}\n{alt} m",
"text-size": {"stops": [[10, 10], [20, 16]]},
"text-font": ["Frutiger Neue Regular"],
"text-anchor": "bottom",
"text-offset": {"stops": [[10, [0, -1]], [20, [0, -2]]]},
"icon-size": 1,
"symbol-spacing": 250,
"symbol-avoid-edges": false,
"text-keep-upright": true,
"text-transform": "none",
"text-optional": false,
"text-allow-overlap": {"stops": [[18, false], [19, true]]},
"text-ignore-placement": false,
"text-justify": "center",
"text-rotate": 0
},
"paint": {
"text-color": "rgba(51, 51, 51, 1)",
"text-halo-color": "rgba(255, 255, 255, 1)",
"text-halo-width": 1,
"text-halo-blur": 1
}
},
{
"id": "summits_circles",
"type": "circle",
"source": "summits",
"source-layer": "summits",
"filter": ["all", ["in", "code"]],
"layout": {"visibility": "visible"},
"paint": {
"circle-stroke-color": "rgba(255, 255, 255, 1)",
"circle-color": [
"match",
["get", "points"],
[1],
"rgba(77, 122, 32, 1)",
[2],
"rgba(109, 165, 54, 1)",
[4],
"rgba(174, 167, 39, 1)",
[6],
"rgba(239, 168, 24, 1)",
[8],
"rgba(220, 93, 4, 1)",
[10],
"rgba(200, 16, 30, 1)",
"#000"
],
"circle-stroke-width": {"stops": [[4, 0], [15, 2]]},
"circle-radius": {"stops": [[0, 0.1], [10, 8], [22, 20]]}
}
},
{
"id": "summits_activations",
"type": "symbol",
"source": "summits",
"source-layer": "summits",
"minzoom": 10,
"maxzoom": 24,
"filter": ["all", ["in", "code"]],
"layout": {
"text-field": "{act}",
"text-font": ["Frutiger Neue Bold"],
"text-size": {"stops": [[10, 8], [20, 16]]},
"text-offset": [0,0.1]
},
"paint": {"text-color": "rgba(255, 255, 255, 1)"}
},
{
"id": "summits_highlight",
"type": "circle",
"source": "summits",
"source-layer": "summits",
"filter": ["all", ["in", "code"]],
"layout": {"visibility": "visible"},
"paint": {
"circle-color": "rgba(2, 243, 198, 1)",
"circle-radius": {"stops": [[6, 15], [20, 50]]},
"circle-opacity": 0.75,
"circle-blur": 0.7
}
},
{
"id": "summits_highlight_alerts",
"type": "circle",
"source": "summits",
"source-layer": "summits",
"filter": ["all", ["in", "code"]],
"layout": {"visibility": "visible"},
"paint": {
"circle-color": "rgba(210, 255, 0, 1)",
"circle-radius": {"stops": [[6, 15], [20, 50]]},
"circle-opacity": 0.55,
"circle-blur": 0.7
}
},
{
"id": "summits_inactive_names",
"type": "symbol",
"metadata": {
"sotlas-map-option": "inactive"
},
"source": "summits_inactive",
"source-layer": "summits_inactive",
"minzoom": 10,
"maxzoom": 24,
"filter": ["all", ["in", "code"]],
"layout": {
"visibility": "none",
"text-field": "{name}\n{code}\n{alt} m\n(inactive)",
"text-size": {"stops": [[10, 10], [20, 16]]},
"text-font": ["Frutiger Neue Regular"],
"text-anchor": "bottom",
"text-offset": {"stops": [[10, [0, -1]], [20, [0, -2]]]},
"icon-size": 1,
"symbol-spacing": 250,
"symbol-avoid-edges": false,
"text-keep-upright": true,
"text-transform": "none",
"text-optional": false,
"text-allow-overlap": {"stops": [[18, false], [19, true]]},
"text-ignore-placement": false,
"text-justify": "center",
"text-rotate": 0
},
"paint": {
"text-color": "rgba(51, 51, 51, 1)",
"text-halo-color": "rgba(255, 255, 255, 1)",
"text-halo-width": 1,
"text-halo-blur": 1,
"text-opacity": 1
}
},
{
"id": "summits_inactive_circles",
"type": "circle",
"metadata": {
"sotlas-map-option": "inactive"
},
"source": "summits_inactive",
"source-layer": "summits_inactive",
"filter": ["all", ["in", "code"]],
"layout": {"visibility": "none"},
"paint": {
"circle-stroke-color": "rgba(255, 255, 255, 1)",
"circle-color": [
"match",
["get", "points"],
[1],
"rgba(77, 122, 32, 0.5)",
[2],
"rgba(109, 165, 54, 0.5)",
[4],
"rgba(174, 167, 39, 0.5)",
[6],
"rgba(239, 168, 24, 0.5)",
[8],
"rgba(220, 93, 4, 0.5)",
[10],
"rgba(200, 16, 30, 0.5)",
"#000"
],
"circle-stroke-width": {"stops": [[4, 0], [15, 2]]},
"circle-radius": {"stops": [[0, 0.1], [10, 8], [22, 20]]}
}
},
{
"id": "regions_areas",
"type": "fill",
"metadata": {
"sotlas-map-option": "regions"
},
"source": "regions",
"source-layer": "areas",
"minzoom": 0,
"layout": {"visibility": "none"},
"paint": {
"fill-opacity": 0.1,
"fill-antialias": false,
"fill-color": "rgba(0, 0, 0, 1)"
}
},
{
"id": "regions_labels",
"type": "symbol",
"metadata": {
"sotlas-map-option": "regions"
},
"source": "regions",
"source-layer": "labels",
"layout": {
"visibility": "none",
"text-field": "{region}",
"text-anchor": "top-left",
"text-justify": "center",
"text-offset": [0.3, 0.3],
"text-font": ["Frutiger Neue Regular"],
"text-size": {"stops": [[6, 8], [10, 16]]}
},
"paint": {
"text-halo-color": "rgba(255, 255, 255, 1)",
"text-halo-width": 0.5,
"text-halo-blur": 1,
"text-translate": [0, 0]
}
}
]
}

Wyświetl plik

@ -2259,9 +2259,20 @@
"circle-color": "rgba(2, 243, 198, 1)",
"circle-radius": {"stops": [[6, 15], [20, 50]]},
"circle-opacity": 0.75,
"circle-stroke-color": "rgba(210, 255, 0, 0.05)",
"circle-stroke-width": 0,
"circle-stroke-opacity": 1,
"circle-blur": 0.7
}
},
{
"id": "summits_highlight_alerts",
"type": "circle",
"source": "summits",
"source-layer": "summits",
"filter": ["all", ["in", "code"]],
"layout": {"visibility": "visible"},
"paint": {
"circle-color": "rgba(210, 255, 0, 1)",
"circle-radius": {"stops": [[6, 15], [20, 50]]},
"circle-opacity": 0.55,
"circle-blur": 0.7
}
},

BIN
src/assets/sac.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 4.7 KiB

Wyświetl plik

@ -0,0 +1 @@
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" width="292" height="227" viewBox="0 0 292 227" xmlns="http://www.w3.org/2000/svg"><g fill="#29bdfe" fill-rule="nonzero"><path d="m0 43.287v175.006c0 5.721 5.776 9.632 11.087 7.51l69.766-31.755v-194.048l-70.686 28.273c-6.126 2.451-10.166 8.415-10.167 15.014z"/><path d="m97.024 194.048 97.024 32.341v-194.048l-97.024-32.341z"/><path d="m279.984.586-69.766 31.755v194.048l70.686-28.273c6.128-2.45 10.167-8.415 10.168-15.014v-175.007c0-5.72-5.776-9.631-11.088-7.509z"/></g></svg>

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 567 B

Wyświetl plik

@ -1,124 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="120.58959mm"
height="19.343578mm"
viewBox="0 0 120.58959 19.343578"
version="1.1"
id="svg8"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="sotlas.svg">
<defs
id="defs2">
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath5259">
<use
x="0"
y="0"
xlink:href="#g5255"
id="use5261"
width="100%"
height="100%" />
</clipPath>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4"
inkscape:cx="185.55186"
inkscape:cy="66.811867"
inkscape:document-units="mm"
inkscape:current-layer="text12"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1329"
inkscape:window-x="0"
inkscape:window-y="1"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-78.247876,-11.392425)">
<g
aria-label="SOTLAS"
style="font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:1.25;font-family:sans-serif;letter-spacing:0.63764584px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
id="text12">
<path
d="m 120.40386,17.005825 q -0.0508,-1.1684 -0.508,-2.032 -0.4318,-0.8636 -1.1938,-1.4478 -0.762,-0.5842 -1.8288,-0.8636 -1.0414,-0.3048 -2.286,-0.3048 -0.762,0 -1.651,0.1778 -0.8636,0.1778 -1.6256,0.635 -0.7366,0.4318 -1.2192,1.1938 -0.4826,0.7366 -0.4826,1.8542 0,1.0922 0.5334,1.778 0.5334,0.6858 1.397,1.1176 0.8636,0.4064 1.9812,0.6604 1.1176,0.254 2.2606,0.4826 1.1684,0.2286 2.2606,0.5588 1.1176,0.3048 1.9812,0.8636 0.889,0.5334 1.4224,1.4224 0.5334,0.8636 0.5334,2.1844 0,1.4224 -0.6096,2.3876 -0.6096,0.9652 -1.5494,1.5748 -0.9144,0.6096 -2.0574,0.8636 -1.1176,0.2794 -2.159,0.2794 -1.6002,0 -2.9972,-0.3556 -1.397,-0.3302 -2.4384,-1.0922 -1.0414,-0.7874 -1.651,-2.0066 -0.5842,-1.2192 -0.5588,-2.9718 h 1.1176 q -0.0762,1.4986 0.4318,2.54 0.508,1.016 1.397,1.6764 0.9144,0.6604 2.1336,0.9652 1.2192,0.2794 2.5654,0.2794 0.8128,0 1.7272,-0.2032 0.9398,-0.2032 1.7018,-0.6858 0.7874,-0.4826 1.2954,-1.27 0.5334,-0.7874 0.5334,-1.9812 0,-1.143 -0.5334,-1.8542 -0.5334,-0.7366 -1.4224,-1.1684 -0.8636,-0.4572 -1.9812,-0.7112 -1.0922,-0.2794 -2.2606,-0.508 -1.143,-0.2286 -2.2606,-0.5334 -1.1176,-0.3048 -1.9812,-0.8128 -0.8636,-0.5334 -1.397,-1.3462 -0.5334,-0.8382 -0.5334,-2.1336 0,-1.2954 0.5334,-2.2098 0.5588,-0.9398 1.4224,-1.4986 0.889,-0.5842 1.9812,-0.8382 1.0922,-0.2794 2.159,-0.2794 1.4224,0 2.6416,0.3302 1.2446,0.3048 2.159,0.9906 0.9398,0.6604 1.4986,1.7272 0.5588,1.0668 0.635,2.5654 z"
style="fill:#29bdfe;fill-opacity:1"
id="path873"
inkscape:connector-curvature="0" />
<path
d="m 141.02509,20.892025 q 0,1.9812 -0.5842,3.7338 -0.5842,1.7272 -1.7018,3.0226 -1.0922,1.27 -2.6924,2.0066 -1.6002,0.7366 -3.6322,0.7366 -2.032,0 -3.6576,-0.7366 -1.6002,-0.7366 -2.7178,-2.0066 -1.0922,-1.2954 -1.6764,-3.0226 -0.5842,-1.7526 -0.5842,-3.7338 0,-1.9812 0.5842,-3.7084 0.5842,-1.7526 1.6764,-3.0226 1.1176,-1.2954 2.7178,-2.032 1.6256,-0.7366 3.6576,-0.7366 2.032,0 3.6322,0.7366 1.6002,0.7366 2.6924,2.032 1.1176,1.27 1.7018,3.0226 0.5842,1.7272 0.5842,3.7084 z m -16.129,0 q 0,1.7526 0.508,3.302 0.508,1.5494 1.4732,2.7178 0.9652,1.143 2.3622,1.8288 1.397,0.6858 3.175,0.6858 1.778,0 3.1496,-0.6858 1.397,-0.6858 2.3622,-1.8288 0.9652,-1.1684 1.4732,-2.7178 0.508,-1.5494 0.508,-3.302 0,-1.7526 -0.508,-3.302 -0.508,-1.5494 -1.4732,-2.6924 -0.9652,-1.1684 -2.3622,-1.8542 -1.3716,-0.6858 -3.1496,-0.6858 -1.778,0 -3.175,0.6858 -1.397,0.6858 -2.3622,1.8542 -0.9652,1.143 -1.4732,2.6924 -0.508,1.5494 -0.508,3.302 z"
style="fill:#29bdfe;fill-opacity:1"
id="path875"
inkscape:connector-curvature="0" />
<path
d="m 140.42045,12.789425 v -0.9652 h 13.8938 v 0.9652 h -6.4008 v 17.1704 h -1.1176 v -17.1704 z"
style="fill:#29bdfe;fill-opacity:1"
id="path877"
inkscape:connector-curvature="0" />
<path
d="m 155.59715,11.824225 h 1.1176 v 17.1704 h 10.287 v 0.9652 h -11.4046 z"
style="letter-spacing:2.04787493px;fill:#016490;fill-opacity:1"
id="path879"
inkscape:connector-curvature="0" />
<path
d="m 175.72983,11.824225 h 1.2192 l 7.1628,18.1356 h -1.1938 l -2.286,-5.8166 h -8.6868 l -2.3114,5.8166 h -1.1938 z m 4.5466,11.3538 -3.8862,-10.2616 h -0.0508 l -4.0386,10.2616 z"
style="fill:#29bdfe;fill-opacity:1"
id="path881"
inkscape:connector-curvature="0" />
<path
d="m 197.26267,17.005825 q -0.0508,-1.1684 -0.508,-2.032 -0.4318,-0.8636 -1.1938,-1.4478 -0.76199,-0.5842 -1.82879,-0.8636 -1.0414,-0.3048 -2.286,-0.3048 -0.762,0 -1.651,0.1778 -0.8636,0.1778 -1.6256,0.635 -0.7366,0.4318 -1.2192,1.1938 -0.4826,0.7366 -0.4826,1.8542 0,1.0922 0.5334,1.778 0.5334,0.6858 1.397,1.1176 0.8636,0.4064 1.9812,0.6604 1.1176,0.254 2.2606,0.4826 1.1684,0.2286 2.2606,0.5588 1.11759,0.3048 1.98119,0.8636 0.889,0.5334 1.4224,1.4224 0.5334,0.8636 0.5334,2.1844 0,1.4224 -0.6096,2.3876 -0.6096,0.9652 -1.5494,1.5748 -0.9144,0.6096 -2.05739,0.8636 -1.1176,0.2794 -2.159,0.2794 -1.6002,0 -2.9972,-0.3556 -1.397,-0.3302 -2.4384,-1.0922 -1.0414,-0.7874 -1.651,-2.0066 -0.5842,-1.2192 -0.5588,-2.9718 h 1.1176 q -0.0762,1.4986 0.4318,2.54 0.508,1.016 1.397,1.6764 0.9144,0.6604 2.1336,0.9652 1.2192,0.2794 2.5654,0.2794 0.8128,0 1.7272,-0.2032 0.93979,-0.2032 1.70179,-0.6858 0.7874,-0.4826 1.2954,-1.27 0.5334,-0.7874 0.5334,-1.9812 0,-1.143 -0.5334,-1.8542 -0.5334,-0.7366 -1.4224,-1.1684 -0.86359,-0.4572 -1.98119,-0.7112 -1.0922,-0.2794 -2.2606,-0.508 -1.143,-0.2286 -2.2606,-0.5334 -1.1176,-0.3048 -1.9812,-0.8128 -0.8636,-0.5334 -1.397,-1.3462 -0.5334,-0.8382 -0.5334,-2.1336 0,-1.2954 0.5334,-2.2098 0.5588,-0.9398 1.4224,-1.4986 0.889,-0.5842 1.9812,-0.8382 1.0922,-0.2794 2.159,-0.2794 1.4224,0 2.6416,0.3302 1.24459,0.3048 2.15899,0.9906 0.9398,0.6604 1.4986,1.7272 0.5588,1.0668 0.635,2.5654 z"
style="font-style:normal;font-variant:normal;font-weight:200;font-stretch:normal;font-size:25.39999962px;font-family:'Helvetica Neue';-inkscape-font-specification:'Helvetica Neue Ultra-Light';letter-spacing:0px;stroke-width:0.26458332;fill:#016490;fill-opacity:1"
id="path883"
inkscape:connector-curvature="0" />
<g
id="g5255"
inkscape:label="Clip">
<path
inkscape:connector-curvature="0"
style="fill:#29bdfe;fill-opacity:1;stroke-width:0.01132015"
d="M 78.247876,15.233355 V 30.05059 c 0,0.484324 0.48903,0.815479 0.938699,0.635783 l 5.906871,-2.688598 V 11.568408 l -5.98474,2.39381 a 1.3693707,1.3693707 0 0 0 -0.86083,1.271137 z"
id="path3324" />
<path
inkscape:connector-curvature="0"
style="fill:#29bdfe;fill-opacity:1;stroke-width:0.01132015"
d="m 86.46256,27.997775 8.214684,2.738229 V 14.306636 L 86.46256,11.568408 Z"
id="path3322" />
<path
inkscape:connector-curvature="0"
style="fill:#29bdfe;fill-opacity:1;stroke-width:0.01132015"
d="m 101.95323,11.618038 -5.906873,2.688598 v 16.429368 l 5.984743,-2.393811 a 1.3689428,1.3689428 0 0 0 0.86083,-1.271136 V 12.253821 c 0,-0.484324 -0.48903,-0.815479 -0.9387,-0.635783 z"
id="path2" />
</g>
</g>
</g>
</svg>
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" width="1425" height="229" viewBox="0 0 1425 229" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero"><g fill="#29bdfe"><path d="m497.905 66.3c-.4-9.2-2.4-17.2-6-24-3.4-6.8-8.1-12.5-14.1-17.1s-13.2-8-21.6-10.2c-8.2-2.4-17.2-3.6-27-3.6-6 0-12.5.7-19.5 2.1-6.8 1.4-13.2 3.9-19.2 7.5-5.8 3.4-10.6 8.1-14.4 14.1-3.8 5.8-5.7 13.1-5.7 21.9 0 8.6 2.1 15.6 6.3 21s9.7 9.8 16.5 13.2c6.8 3.2 14.6 5.8 23.4 7.8s17.7 3.9 26.7 5.7c9.2 1.8 18.1 4 26.7 6.6 8.8 2.4 16.6 5.8 23.4 10.2 7 4.2 12.6 9.8 16.8 16.8 4.2 6.8 6.3 15.4 6.3 25.8 0 11.2-2.4 20.6-7.2 28.2s-10.9 13.8-18.3 18.6c-7.2 4.8-15.3 8.2-24.3 10.2-8.8 2.2-17.3 3.3-25.5 3.3-12.6 0-24.4-1.4-35.4-4.2-11-2.6-20.6-6.9-28.8-12.9-8.2-6.2-14.7-14.1-19.5-23.7-4.6-9.6-6.8-21.3-6.6-35.1h13.2c-.6 11.8 1.1 21.8 5.1 30 4 8 9.5 14.6 16.5 19.8 7.2 5.2 15.6 9 25.2 11.4 9.6 2.2 19.7 3.3 30.3 3.3 6.4 0 13.2-.8 20.4-2.4 7.4-1.6 14.1-4.3 20.1-8.1 6.2-3.8 11.3-8.8 15.3-15 4.2-6.2 6.3-14 6.3-23.4 0-9-2.1-16.3-6.3-21.9-4.2-5.8-9.8-10.4-16.8-13.8-6.8-3.6-14.6-6.4-23.4-8.4-8.6-2.2-17.5-4.2-26.7-6-9-1.8-17.9-3.9-26.7-6.3s-16.6-5.6-23.4-9.6c-6.8-4.2-12.3-9.5-16.5-15.9-4.2-6.6-6.3-15-6.3-25.2s2.1-18.9 6.3-26.1c4.4-7.4 10-13.3 16.8-17.7 7-4.6 14.8-7.9 23.4-9.9 8.6-2.2 17.1-3.3 25.5-3.3 11.2 0 21.6 1.3 31.2 3.9 9.8 2.4 18.3 6.3 25.5 11.7 7.4 5.2 13.3 12 17.7 20.4s6.9 18.5 7.5 30.3z"/><path d="m741.463 112.2c0 15.6-2.3 30.3-6.9 44.1-4.6 13.6-11.3 25.5-20.1 35.7-8.6 10-19.2 17.9-31.8 23.7s-26.9 8.7-42.9 8.7-30.4-2.9-43.2-8.7c-12.6-5.8-23.3-13.7-32.1-23.7-8.6-10.2-15.2-22.1-19.8-35.7-4.6-13.8-6.9-28.5-6.9-44.1s2.3-30.2 6.9-43.8c4.6-13.8 11.2-25.7 19.8-35.7 8.8-10.2 19.5-18.2 32.1-24 12.8-5.8 27.2-8.7 43.2-8.7s30.3 2.9 42.9 8.7 23.2 13.8 31.8 24c8.8 10 15.5 21.9 20.1 35.7 4.6 13.6 6.9 28.2 6.9 43.8zm-190.5 0c0 13.8 2 26.8 6 39s9.8 22.9 17.4 32.1c7.6 9 16.9 16.2 27.9 21.6s23.5 8.1 37.5 8.1 26.4-2.7 37.2-8.1c11-5.4 20.3-12.6 27.9-21.6 7.6-9.2 13.4-19.9 17.4-32.1s6-25.2 6-39-2-26.8-6-39-9.8-22.8-17.4-31.8c-7.6-9.2-16.9-16.5-27.9-21.9-10.8-5.4-23.2-8.1-37.2-8.1s-26.5 2.7-37.5 8.1-20.3 12.7-27.9 21.9c-7.6 9-13.4 19.6-17.4 31.8s-6 25.2-6 39z"/><path d="m734.322 16.5v-11.4h164.1v11.4h-75.6v202.8h-13.2v-202.8z"/></g><path d="m913.574 5.1h13.2v202.8h121.5v11.4h-134.7v-214.2z" fill="#016490"/><path d="m1151.36 5.1h14.4l84.6 214.2h-14.1l-27-68.7h-102.6l-27.3 68.7h-14.1l86.1-214.2zm53.7 134.1-45.9-121.2h-.6l-47.7 121.2z" fill="#29bdfe"/><path d="m1405.69 66.3c-.4-9.2-2.4-17.2-6-24-3.4-6.8-8.1-12.5-14.1-17.1s-13.2-8-21.6-10.2c-8.2-2.4-17.2-3.6-27-3.6-6 0-12.5.7-19.5 2.1-6.8 1.4-13.2 3.9-19.2 7.5-5.8 3.4-10.6 8.1-14.4 14.1-3.8 5.8-5.7 13.1-5.7 21.9 0 8.6 2.1 15.6 6.3 21s9.7 9.8 16.5 13.2c6.8 3.2 14.6 5.8 23.4 7.8s17.7 3.9 26.7 5.7c9.2 1.8 18.1 4 26.7 6.6 8.8 2.4 16.6 5.8 23.4 10.2 7 4.2 12.6 9.8 16.8 16.8 4.2 6.8 6.3 15.4 6.3 25.8 0 11.2-2.4 20.6-7.2 28.2s-10.9 13.8-18.3 18.6c-7.2 4.8-15.3 8.2-24.3 10.2-8.8 2.2-17.3 3.3-25.5 3.3-12.6 0-24.4-1.4-35.4-4.2-11-2.6-20.6-6.9-28.8-12.9-8.2-6.2-14.7-14.1-19.5-23.7-4.6-9.6-6.8-21.3-6.6-35.1h13.2c-.6 11.8 1.1 21.8 5.1 30 4 8 9.5 14.6 16.5 19.8 7.2 5.2 15.6 9 25.2 11.4 9.6 2.2 19.7 3.3 30.3 3.3 6.4 0 13.2-.8 20.4-2.4 7.4-1.6 14.1-4.3 20.1-8.1 6.2-3.8 11.3-8.8 15.3-15 4.2-6.2 6.3-14 6.3-23.4 0-9-2.1-16.3-6.3-21.9-4.2-5.8-9.8-10.4-16.8-13.8-6.8-3.6-14.6-6.4-23.4-8.4-8.6-2.2-17.5-4.2-26.7-6-9-1.8-17.9-3.9-26.7-6.3s-16.6-5.6-23.4-9.6c-6.8-4.2-12.3-9.5-16.5-15.9-4.2-6.6-6.3-15-6.3-25.2s2.1-18.9 6.3-26.1c4.4-7.4 10-13.3 16.8-17.7 7-4.6 14.8-7.9 23.4-9.9 8.6-2.2 17.1-3.3 25.5-3.3 11.2 0 21.6 1.3 31.2 3.9 9.8 2.4 18.3 6.3 25.5 11.7 7.4 5.2 13.3 12 17.7 20.4s6.9 18.5 7.5 30.3z" fill="#016490"/><path d="m0 45.365v175.007c0 5.72 5.776 9.632 11.087 7.509l69.766-31.755v-194.047l-70.686 28.273c-6.126 2.45-10.166 8.415-10.167 15.013z" fill="#29bdfe"/><path d="m97.024 196.126 97.024 32.341v-194.047l-97.024-32.341z" fill="#29bdfe"/><path d="m279.984 2.665-69.766 31.755v194.047l70.686-28.273c6.128-2.449 10.167-8.414 10.168-15.013v-175.007c0-5.72-5.776-9.632-11.088-7.509z" fill="#29bdfe"/></g></svg>

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 8.2 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 4.0 KiB

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,456 @@
{
"version": 8,
"name": "swisstopo_aerial",
"metadata": {"maputnik:renderer": "mbgljs", "openmaptiles:version": "3.x"},
"center": [7.969664962869274, 47.021278030856564],
"zoom": 9.333879434342306,
"bearing": 0,
"pitch": 0,
"sources": {
"swisstopo": {
"type": "raster",
"tiles": [
"https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.swissimage/default/current/3857/{z}/{x}/{y}.jpeg"
],
"tileSize": 256,
"maxzoom": 19,
"bounds": [5.140242, 45.398181, 11.47757, 48.230651],
"attribution": "© swisstopo"
},
"hiking_trails_raster": {
"type": "raster",
"tiles": [
"https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.swisstlm3d-wanderwege/default/current/3857/{z}/{x}/{y}.png"
],
"tileSize": 256,
"maxzoom": 18,
"bounds": [5.140242, 45.398181, 11.47757, 48.230651]
},
"skiing_trails_raster": {
"type": "raster",
"tiles": [
"https://wmts.geo.admin.ch/1.0.0/ch.swisstopo-karto.skitouren/default/current/3857/{z}/{x}/{y}.png"
],
"tileSize": 256,
"maxzoom": 17,
"bounds": [5.140242, 45.398181, 11.47757, 48.230651]
},
"snowshoe_trails_raster": {
"type": "raster",
"tiles": [
"https://wmts.geo.admin.ch/1.0.0/ch.swisstopo-karto.schneeschuhrouten/default/current/3857/{z}/{x}/{y}.png"
],
"tileSize": 256,
"maxzoom": 17,
"bounds": [5.140242, 45.398181, 11.47757, 48.230651]
},
"wildlife_areas": {
"type": "raster",
"tiles": [
"https://wmts.geo.admin.ch/1.0.0/ch.bafu.wrz-wildruhezonen_portal/default/current/3857/{z}/{x}/{y}.png"
],
"tileSize": 256,
"maxzoom": 18,
"bounds": [5.140242, 45.398181, 11.47757, 48.230651]
},
"wildlife_reserves": {
"type": "raster",
"tiles": [
"https://wmts.geo.admin.ch/1.0.0/ch.bafu.wrz-jagdbanngebiete_select/default/current/3857/{z}/{x}/{y}.png"
],
"tileSize": 256,
"maxzoom": 18,
"bounds": [5.140242, 45.398181, 11.47757, 48.230651]
},
"slope_classes": {
"type": "raster",
"tiles": [
"https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.hangneigung-ueber_30/default/current/3857/{z}/{x}/{y}.png"
],
"tileSize": 256,
"maxzoom": 14,
"bounds": [5.140242, 45.398181, 11.47757, 48.230651]
},
"summits": {
"type": "vector",
"url": "https://1.{mapServer}.map.sotl.as/data/summits.json"
},
"summits_inactive": {
"type": "vector",
"url": "https://1.{mapServer}.map.sotl.as/data/summits_inactive.json"
},
"regions": {
"type": "vector",
"url": "https://1.{mapServer}.map.sotl.as/data/regions.json"
},
"az": {
"type": "vector",
"url": "https://1.{mapServer}.map.sotl.as/data/az.json"
}
},
"sprite": "https://vectortiles.geo.admin.ch/styles/ch.swisstopo.leichte-basiskarte.vt/sprite/sprite",
"glyphs": "https://vectortiles.geo.admin.ch/fonts/{fontstack}/{range}.pbf",
"transition": {},
"layers": [
{
"id": "background",
"type": "background",
"layout": {"visibility": "visible"},
"paint": {"background-color": "rgba(255, 255, 255, 1)"}
},
{
"id": "swisstopo",
"type": "raster",
"source": "swisstopo",
"layout": {"visibility": "visible"},
"paint": {
"raster-opacity": 1.0,
"raster-resampling": "linear"
}
},
{
"id": "wildlife_areas",
"type": "raster",
"metadata": {
"sotlas-map-option": "wildlife"
},
"source": "wildlife_areas",
"layout": {"visibility": "none"},
"paint": {
"raster-opacity": 0.6,
"raster-resampling": "linear"
}
},
{
"id": "wildlife_reserves",
"type": "raster",
"metadata": {
"sotlas-map-option": "wildlife"
},
"source": "wildlife_reserves",
"layout": {"visibility": "none"},
"paint": {
"raster-opacity": 0.6,
"raster-resampling": "linear"
}
},
{
"id": "summits_az",
"type": "fill",
"metadata": {
"sotlas-map-option": "az"
},
"source": "az",
"source-layer": "az",
"layout": {"visibility": "none"},
"minzoom": 12,
"paint": {
"fill-antialias": false,
"fill-color": "rgba(255, 255, 0, 1)",
"fill-opacity": {"stops": [[12, 0], [12.5, 0.5]]}
}
},
{
"id": "summits_az_border",
"type": "line",
"metadata": {
"sotlas-map-option": "az"
},
"source": "az",
"source-layer": "az",
"layout": {"visibility": "none"},
"minzoom": 12,
"paint": {
"line-color": "rgba(235, 196, 0, 1)",
"line-opacity": {"stops": [[12, 0], [12.5, 0.5]]},
"line-width": {"stops": [[12, 1], [16, 3]]}
}
},
{
"id": "slope_classes",
"type": "raster",
"metadata": {
"sotlas-map-option": "slope_classes"
},
"source": "slope_classes",
"layout": {"visibility": "none"},
"paint": {
"raster-opacity": 0.3,
"raster-resampling": "nearest"
}
},
{
"id": "hiking_trails_raster",
"type": "raster",
"metadata": {
"sotlas-map-option": "difficulty"
},
"source": "hiking_trails_raster",
"layout": {"visibility": "none"},
"paint": {
"raster-opacity": 0.6,
"raster-resampling": "linear"
}
},
{
"id": "skiing_trails_raster",
"type": "raster",
"metadata": {
"sotlas-map-option": "skiing"
},
"source": "skiing_trails_raster",
"layout": {"visibility": "none"},
"paint": {
"raster-opacity": 0.6,
"raster-resampling": "linear"
}
},
{
"id": "snowshoe_trails_raster",
"type": "raster",
"metadata": {
"sotlas-map-option": "snowshoe"
},
"source": "snowshoe_trails_raster",
"layout": {"visibility": "none"},
"paint": {
"raster-opacity": 0.6,
"raster-resampling": "linear"
}
},
{
"id": "summits_selected",
"type": "circle",
"source": "summits",
"source-layer": "summits",
"filter": ["all", ["in", "code"]],
"layout": {"visibility": "visible"},
"paint": {
"circle-color": "rgba(2, 153, 243, 1)",
"circle-radius": {"stops": [[6, 15], [20, 50]]},
"circle-opacity": 0.75,
"circle-stroke-color": "rgba(210, 255, 0, 0.05)",
"circle-stroke-width": 0,
"circle-stroke-opacity": 1,
"circle-blur": 0.7
}
},
{
"id": "summits_names",
"type": "symbol",
"source": "summits",
"source-layer": "summits",
"minzoom": 10,
"maxzoom": 24,
"filter": ["all", ["in", "code"]],
"layout": {
"visibility": "visible",
"text-field": "{name}\n{code}\n{alt} m",
"text-size": {"stops": [[10, 10], [20, 16]]},
"text-font": ["Frutiger Neue Regular"],
"text-anchor": "bottom",
"text-offset": {"stops": [[10, [0, -1]], [20, [0, -2]]]},
"icon-size": 1,
"symbol-spacing": 250,
"symbol-avoid-edges": false,
"text-keep-upright": true,
"text-transform": "none",
"text-optional": false,
"text-allow-overlap": {"stops": [[18, false], [19, true]]},
"text-ignore-placement": false,
"text-justify": "center",
"text-rotate": 0
},
"paint": {
"text-color": "rgba(255, 255, 255, 1)",
"text-halo-color": "rgba(51, 51, 51, 1)",
"text-halo-width": 1,
"text-halo-blur": 1
}
},
{
"id": "summits_circles",
"type": "circle",
"source": "summits",
"source-layer": "summits",
"filter": ["all", ["in", "code"]],
"layout": {"visibility": "visible"},
"paint": {
"circle-stroke-color": "rgba(255, 255, 255, 1)",
"circle-color": [
"match",
["get", "points"],
[1],
"rgba(77, 122, 32, 1)",
[2],
"rgba(109, 165, 54, 1)",
[4],
"rgba(174, 167, 39, 1)",
[6],
"rgba(239, 168, 24, 1)",
[8],
"rgba(220, 93, 4, 1)",
[10],
"rgba(200, 16, 30, 1)",
"#000"
],
"circle-stroke-width": {"stops": [[4, 0], [15, 2]]},
"circle-radius": {"stops": [[0, 0.1], [10, 8], [22, 20]]}
}
},
{
"id": "summits_activations",
"type": "symbol",
"source": "summits",
"source-layer": "summits",
"minzoom": 10,
"maxzoom": 24,
"filter": ["all", ["in", "code"]],
"layout": {
"text-field": "{act}",
"text-font": ["Frutiger Neue Bold"],
"text-size": {"stops": [[10, 8], [20, 16]]},
"text-offset": [0,0.1]
},
"paint": {"text-color": "rgba(255, 255, 255, 1)"}
},
{
"id": "summits_highlight",
"type": "circle",
"source": "summits",
"source-layer": "summits",
"filter": ["all", ["in", "code"]],
"layout": {"visibility": "visible"},
"paint": {
"circle-color": "rgba(2, 243, 198, 1)",
"circle-radius": {"stops": [[6, 15], [20, 50]]},
"circle-opacity": 0.75,
"circle-blur": 0.7
}
},
{
"id": "summits_highlight_alerts",
"type": "circle",
"source": "summits",
"source-layer": "summits",
"filter": ["all", ["in", "code"]],
"layout": {"visibility": "visible"},
"paint": {
"circle-color": "rgba(210, 255, 0, 1)",
"circle-radius": {"stops": [[6, 15], [20, 50]]},
"circle-opacity": 0.55,
"circle-blur": 0.7
}
},
{
"id": "summits_inactive_names",
"type": "symbol",
"metadata": {
"sotlas-map-option": "inactive"
},
"source": "summits_inactive",
"source-layer": "summits_inactive",
"minzoom": 10,
"maxzoom": 24,
"filter": ["all", ["in", "code"]],
"layout": {
"visibility": "none",
"text-field": "{name}\n{code}\n{alt} m\n(inactive)",
"text-size": {"stops": [[10, 10], [20, 16]]},
"text-font": ["Frutiger Neue Regular"],
"text-anchor": "bottom",
"text-offset": {"stops": [[10, [0, -1]], [20, [0, -2]]]},
"icon-size": 1,
"symbol-spacing": 250,
"symbol-avoid-edges": false,
"text-keep-upright": true,
"text-transform": "none",
"text-optional": false,
"text-allow-overlap": {"stops": [[18, false], [19, true]]},
"text-ignore-placement": false,
"text-justify": "center",
"text-rotate": 0
},
"paint": {
"text-color": "rgba(51, 51, 51, 1)",
"text-halo-color": "rgba(255, 255, 255, 1)",
"text-halo-width": 1,
"text-halo-blur": 1,
"text-opacity": 1
}
},
{
"id": "summits_inactive_circles",
"type": "circle",
"metadata": {
"sotlas-map-option": "inactive"
},
"source": "summits_inactive",
"source-layer": "summits_inactive",
"filter": ["all", ["in", "code"]],
"layout": {"visibility": "none"},
"paint": {
"circle-stroke-color": "rgba(255, 255, 255, 1)",
"circle-color": [
"match",
["get", "points"],
[1],
"rgba(77, 122, 32, 0.5)",
[2],
"rgba(109, 165, 54, 0.5)",
[4],
"rgba(174, 167, 39, 0.5)",
[6],
"rgba(239, 168, 24, 0.5)",
[8],
"rgba(220, 93, 4, 0.5)",
[10],
"rgba(200, 16, 30, 0.5)",
"#000"
],
"circle-stroke-width": {"stops": [[4, 0], [15, 2]]},
"circle-radius": {"stops": [[0, 0.1], [10, 8], [22, 20]]}
}
},
{
"id": "regions_areas",
"type": "fill",
"metadata": {
"sotlas-map-option": "regions"
},
"source": "regions",
"source-layer": "areas",
"minzoom": 0,
"layout": {"visibility": "none"},
"paint": {
"fill-opacity": 0.15,
"fill-antialias": false,
"fill-color": "rgba(255, 255, 255, 1)"
}
},
{
"id": "regions_labels",
"type": "symbol",
"metadata": {
"sotlas-map-option": "regions"
},
"source": "regions",
"source-layer": "labels",
"layout": {
"visibility": "none",
"text-field": "{region}",
"text-anchor": "top-left",
"text-justify": "center",
"text-offset": [0.3, 0.3],
"text-font": ["Frutiger Neue Regular"],
"text-size": {"stops": [[6, 8], [10, 16]]}
},
"paint": {
"text-halo-color": "rgba(255, 255, 255, 1)",
"text-halo-width": 0.5,
"text-halo-blur": 1,
"text-translate": [0, 0]
}
}
]
}

Wyświetl plik

@ -13,7 +13,9 @@
"https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.pixelkarte-farbe/default/current/3857/{z}/{x}/{y}.jpeg"
],
"tileSize": 256,
"maxzoom": 19
"maxzoom": 19,
"bounds": [5.140242, 45.398181, 11.47757, 48.230651],
"attribution": "© swisstopo"
},
"hiking_trails_raster": {
"type": "raster",
@ -21,7 +23,8 @@
"https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.swisstlm3d-wanderwege/default/current/3857/{z}/{x}/{y}.png"
],
"tileSize": 256,
"maxzoom": 18
"maxzoom": 18,
"bounds": [5.140242, 45.398181, 11.47757, 48.230651]
},
"skiing_trails_raster": {
"type": "raster",
@ -29,7 +32,8 @@
"https://wmts.geo.admin.ch/1.0.0/ch.swisstopo-karto.skitouren/default/current/3857/{z}/{x}/{y}.png"
],
"tileSize": 256,
"maxzoom": 17
"maxzoom": 17,
"bounds": [5.140242, 45.398181, 11.47757, 48.230651]
},
"snowshoe_trails_raster": {
"type": "raster",
@ -37,7 +41,8 @@
"https://wmts.geo.admin.ch/1.0.0/ch.swisstopo-karto.schneeschuhrouten/default/current/3857/{z}/{x}/{y}.png"
],
"tileSize": 256,
"maxzoom": 17
"maxzoom": 17,
"bounds": [5.140242, 45.398181, 11.47757, 48.230651]
},
"wildlife_areas": {
"type": "raster",
@ -45,7 +50,8 @@
"https://wmts.geo.admin.ch/1.0.0/ch.bafu.wrz-wildruhezonen_portal/default/current/3857/{z}/{x}/{y}.png"
],
"tileSize": 256,
"maxzoom": 18
"maxzoom": 18,
"bounds": [5.140242, 45.398181, 11.47757, 48.230651]
},
"wildlife_reserves": {
"type": "raster",
@ -53,7 +59,8 @@
"https://wmts.geo.admin.ch/1.0.0/ch.bafu.wrz-jagdbanngebiete_select/default/current/3857/{z}/{x}/{y}.png"
],
"tileSize": 256,
"maxzoom": 18
"maxzoom": 18,
"bounds": [5.140242, 45.398181, 11.47757, 48.230651]
},
"slope_classes": {
"type": "raster",
@ -61,7 +68,8 @@
"https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.hangneigung-ueber_30/default/current/3857/{z}/{x}/{y}.png"
],
"tileSize": 256,
"maxzoom": 14
"maxzoom": 14,
"bounds": [5.140242, 45.398181, 11.47757, 48.230651]
},
"summits": {
"type": "vector",
@ -74,9 +82,13 @@
"regions": {
"type": "vector",
"url": "https://1.{mapServer}.map.sotl.as/data/regions.json"
},
"az": {
"type": "vector",
"url": "https://1.{mapServer}.map.sotl.as/data/az.json"
}
},
"sprite": "https://vectortiles.geo.admin.ch/styles/ch.swisstopo.leichte-basiskarte.vt/v1.0.0/sprite/sprite",
"sprite": "https://vectortiles.geo.admin.ch/styles/ch.swisstopo.leichte-basiskarte.vt/sprite/sprite",
"glyphs": "https://vectortiles.geo.admin.ch/fonts/{fontstack}/{range}.pbf",
"transition": {},
"layers": [
@ -122,6 +134,38 @@
"raster-resampling": "linear"
}
},
{
"id": "summits_az",
"type": "fill",
"metadata": {
"sotlas-map-option": "az"
},
"source": "az",
"source-layer": "az",
"layout": {"visibility": "none"},
"minzoom": 12,
"paint": {
"fill-antialias": false,
"fill-color": "rgba(255, 255, 0, 1)",
"fill-opacity": {"stops": [[12, 0], [12.5, 0.5]]}
}
},
{
"id": "summits_az_border",
"type": "line",
"metadata": {
"sotlas-map-option": "az"
},
"source": "az",
"source-layer": "az",
"layout": {"visibility": "none"},
"minzoom": 12,
"paint": {
"line-color": "rgba(235, 196, 0, 1)",
"line-opacity": {"stops": [[12, 0], [12.5, 0.5]]},
"line-width": {"stops": [[12, 1], [16, 3]]}
}
},
{
"id": "slope_classes",
"type": "raster",
@ -281,9 +325,20 @@
"circle-color": "rgba(2, 243, 198, 1)",
"circle-radius": {"stops": [[6, 15], [20, 50]]},
"circle-opacity": 0.75,
"circle-stroke-color": "rgba(210, 255, 0, 0.05)",
"circle-stroke-width": 0,
"circle-stroke-opacity": 1,
"circle-blur": 0.7
}
},
{
"id": "summits_highlight_alerts",
"type": "circle",
"source": "summits",
"source-layer": "summits",
"filter": ["all", ["in", "code"]],
"layout": {"visibility": "visible"},
"paint": {
"circle-color": "rgba(210, 255, 0, 1)",
"circle-radius": {"stops": [[6, 15], [20, 50]]},
"circle-opacity": 0.55,
"circle-blur": 0.7
}
},

Wyświetl plik

@ -0,0 +1,324 @@
{
"version": 8,
"name": "toposvalbard",
"metadata": {"maputnik:renderer": "mbgljs", "openmaptiles:version": "3.x"},
"center": [16.765892, 78.112112],
"zoom": 6,
"bearing": 0,
"pitch": 0,
"sources": {
"toposvalbard": {
"type": "raster",
"tiles": [
"https://geodata.npolar.no/arcgis/rest/services/Basisdata/NP_Basiskart_Svalbard_WMTS_3857/MapServer/tile/{z}/{y}/{x}"
],
"tileSize": 256,
"maxzoom": 13,
"bounds": [7.4670, 73.7357, 36.0502, 81.1569],
"attribution": "© Norwegian Polar Institute"
},
"summits": {
"type": "vector",
"url": "https://1.{mapServer}.map.sotl.as/data/summits.json"
},
"summits_inactive": {
"type": "vector",
"url": "https://1.{mapServer}.map.sotl.as/data/summits_inactive.json"
},
"regions": {
"type": "vector",
"url": "https://1.{mapServer}.map.sotl.as/data/regions.json"
},
"az": {
"type": "vector",
"url": "https://1.{mapServer}.map.sotl.as/data/az.json"
}
},
"sprite": "https://sotl.as/sprites",
"glyphs": "https://0.{mapServer}.map.sotl.as/fonts/{fontstack}/{range}.pbf",
"transition": {},
"layers": [
{
"id": "background",
"type": "background",
"layout": {"visibility": "visible"},
"paint": {"background-color": "rgba(255, 255, 255, 1)"}
},
{
"id": "toposvalbard",
"type": "raster",
"source": "toposvalbard",
"layout": {"visibility": "visible"},
"paint": {
"raster-opacity": 0.75,
"raster-resampling": "linear"
}
},
{
"id": "summits_az",
"type": "fill",
"metadata": {
"sotlas-map-option": "az"
},
"source": "az",
"source-layer": "az",
"layout": {"visibility": "none"},
"minzoom": 12,
"paint": {
"fill-antialias": false,
"fill-color": "rgba(255, 255, 0, 1)",
"fill-opacity": {"stops": [[12, 0], [12.5, 0.5]]}
}
},
{
"id": "summits_az_border",
"type": "line",
"metadata": {
"sotlas-map-option": "az"
},
"source": "az",
"source-layer": "az",
"layout": {"visibility": "none"},
"minzoom": 12,
"paint": {
"line-color": "rgba(235, 196, 0, 1)",
"line-opacity": {"stops": [[12, 0], [12.5, 0.5]]},
"line-width": {"stops": [[12, 1], [16, 3]]}
}
},
{
"id": "summits_selected",
"type": "circle",
"source": "summits",
"source-layer": "summits",
"filter": ["all", ["in", "code"]],
"layout": {"visibility": "visible"},
"paint": {
"circle-color": "rgba(2, 153, 243, 1)",
"circle-radius": {"stops": [[6, 15], [20, 50]]},
"circle-opacity": 0.75,
"circle-stroke-color": "rgba(210, 255, 0, 0.05)",
"circle-stroke-width": 0,
"circle-stroke-opacity": 1,
"circle-blur": 0.7
}
},
{
"id": "summits_names",
"type": "symbol",
"source": "summits",
"source-layer": "summits",
"minzoom": 10,
"maxzoom": 24,
"filter": ["all", ["in", "code"]],
"layout": {
"visibility": "visible",
"text-field": "{name}\n{code}\n{alt} m",
"text-size": {"stops": [[10, 10], [20, 16]]},
"text-font": ["Frutiger Neue Regular"],
"text-anchor": "bottom",
"text-offset": {"stops": [[10, [0, -1]], [20, [0, -2]]]},
"icon-size": 1,
"symbol-spacing": 250,
"symbol-avoid-edges": false,
"text-keep-upright": true,
"text-transform": "none",
"text-optional": false,
"text-allow-overlap": {"stops": [[18, false], [19, true]]},
"text-ignore-placement": false,
"text-justify": "center",
"text-rotate": 0
},
"paint": {
"text-color": "rgba(51, 51, 51, 1)",
"text-halo-color": "rgba(255, 255, 255, 1)",
"text-halo-width": 1,
"text-halo-blur": 1
}
},
{
"id": "summits_circles",
"type": "circle",
"source": "summits",
"source-layer": "summits",
"filter": ["all", ["in", "code"]],
"layout": {"visibility": "visible"},
"paint": {
"circle-stroke-color": "rgba(255, 255, 255, 1)",
"circle-color": [
"match",
["get", "points"],
[1],
"rgba(77, 122, 32, 1)",
[2],
"rgba(109, 165, 54, 1)",
[4],
"rgba(174, 167, 39, 1)",
[6],
"rgba(239, 168, 24, 1)",
[8],
"rgba(220, 93, 4, 1)",
[10],
"rgba(200, 16, 30, 1)",
"#000"
],
"circle-stroke-width": {"stops": [[4, 0], [15, 2]]},
"circle-radius": {"stops": [[0, 0.1], [10, 8], [22, 20]]}
}
},
{
"id": "summits_activations",
"type": "symbol",
"source": "summits",
"source-layer": "summits",
"minzoom": 10,
"maxzoom": 24,
"filter": ["all", ["in", "code"]],
"layout": {
"text-field": "{act}",
"text-font": ["Frutiger Neue Bold"],
"text-size": {"stops": [[10, 8], [20, 16]]},
"text-offset": [0,0.1]
},
"paint": {"text-color": "rgba(255, 255, 255, 1)"}
},
{
"id": "summits_highlight",
"type": "circle",
"source": "summits",
"source-layer": "summits",
"filter": ["all", ["in", "code"]],
"layout": {"visibility": "visible"},
"paint": {
"circle-color": "rgba(2, 243, 198, 1)",
"circle-radius": {"stops": [[6, 15], [20, 50]]},
"circle-opacity": 0.75,
"circle-blur": 0.7
}
},
{
"id": "summits_highlight_alerts",
"type": "circle",
"source": "summits",
"source-layer": "summits",
"filter": ["all", ["in", "code"]],
"layout": {"visibility": "visible"},
"paint": {
"circle-color": "rgba(210, 255, 0, 1)",
"circle-radius": {"stops": [[6, 15], [20, 50]]},
"circle-opacity": 0.55,
"circle-blur": 0.7
}
},
{
"id": "summits_inactive_names",
"type": "symbol",
"metadata": {
"sotlas-map-option": "inactive"
},
"source": "summits_inactive",
"source-layer": "summits_inactive",
"minzoom": 10,
"maxzoom": 24,
"filter": ["all", ["in", "code"]],
"layout": {
"visibility": "none",
"text-field": "{name}\n{code}\n{alt} m\n(inactive)",
"text-size": {"stops": [[10, 10], [20, 16]]},
"text-font": ["Frutiger Neue Regular"],
"text-anchor": "bottom",
"text-offset": {"stops": [[10, [0, -1]], [20, [0, -2]]]},
"icon-size": 1,
"symbol-spacing": 250,
"symbol-avoid-edges": false,
"text-keep-upright": true,
"text-transform": "none",
"text-optional": false,
"text-allow-overlap": {"stops": [[18, false], [19, true]]},
"text-ignore-placement": false,
"text-justify": "center",
"text-rotate": 0
},
"paint": {
"text-color": "rgba(51, 51, 51, 1)",
"text-halo-color": "rgba(255, 255, 255, 1)",
"text-halo-width": 1,
"text-halo-blur": 1,
"text-opacity": 1
}
},
{
"id": "summits_inactive_circles",
"type": "circle",
"metadata": {
"sotlas-map-option": "inactive"
},
"source": "summits_inactive",
"source-layer": "summits_inactive",
"filter": ["all", ["in", "code"]],
"layout": {"visibility": "none"},
"paint": {
"circle-stroke-color": "rgba(255, 255, 255, 1)",
"circle-color": [
"match",
["get", "points"],
[1],
"rgba(77, 122, 32, 0.5)",
[2],
"rgba(109, 165, 54, 0.5)",
[4],
"rgba(174, 167, 39, 0.5)",
[6],
"rgba(239, 168, 24, 0.5)",
[8],
"rgba(220, 93, 4, 0.5)",
[10],
"rgba(200, 16, 30, 0.5)",
"#000"
],
"circle-stroke-width": {"stops": [[4, 0], [15, 2]]},
"circle-radius": {"stops": [[0, 0.1], [10, 8], [22, 20]]}
}
},
{
"id": "regions_areas",
"type": "fill",
"metadata": {
"sotlas-map-option": "regions"
},
"source": "regions",
"source-layer": "areas",
"minzoom": 0,
"layout": {"visibility": "none"},
"paint": {
"fill-opacity": 0.1,
"fill-antialias": false,
"fill-color": "rgba(0, 0, 0, 1)"
}
},
{
"id": "regions_labels",
"type": "symbol",
"metadata": {
"sotlas-map-option": "regions"
},
"source": "regions",
"source-layer": "labels",
"layout": {
"visibility": "none",
"text-field": "{region}",
"text-anchor": "top-left",
"text-justify": "center",
"text-offset": [0.3, 0.3],
"text-font": ["Frutiger Neue Regular"],
"text-size": {"stops": [[6, 8], [10, 16]]}
},
"paint": {
"text-halo-color": "rgba(255, 255, 255, 1)",
"text-halo-width": 0.5,
"text-halo-blur": 1,
"text-translate": [0, 0]
}
}
]
}

Wyświetl plik

@ -180,6 +180,15 @@ export default {
.then(response => {
this.$store.dispatch('reloadAlerts')
})
.catch(err => {
this.$buefy.dialog.alert({
title: 'Error',
message: 'Could not delete spot: ' + err.message,
type: 'is-danger',
ariaRole: 'alertdialog',
ariaModal: true
})
})
}
})
}

Wyświetl plik

@ -17,7 +17,23 @@ export default {
type: Boolean,
default: false
},
stacked: Boolean
height: {
type: [String, Number],
default: 250
},
spaceRatio: {
type: Number,
default: 0.3
},
yMarkers: {
type: Array
},
stacked: Boolean,
colors: Array,
yAxisMode: {
type: String,
default: 'span'
}
},
methods: {
updateChart () {
@ -47,17 +63,20 @@ export default {
this.chart = new Chart(this.$refs.chart, {
data: {
labels,
datasets: datasets
datasets: datasets,
yMarkers: this.yMarkers
},
type: 'bar',
height: 250,
height: parseInt(this.height),
colors: this.colors,
barOptions: {
spaceRatio: 0.3,
spaceRatio: this.spaceRatio,
stacked: this.stacked
},
axisOptions: {
xAxisMode: 'tick',
xIsSeries: this.xIsSeries
xIsSeries: this.xIsSeries,
yAxisMode: this.yAxisMode
}
})
}

Wyświetl plik

@ -28,17 +28,20 @@ export default {
},
mounted () {
if (this.homeQth === null) {
this.$keycloak.loadUserProfile()
.success(profile => {
if (profile.attributes.Lat && profile.attributes.Lat[0] && profile.attributes.Lon && profile.attributes.Lon[0]) {
this.$store.commit('setHomeQth', {
latitude: parseFloat(profile.attributes.Lat[0]),
longitude: parseFloat(profile.attributes.Lon[0])
this.$keycloak.updateToken(60)
.success(() => {
this.$keycloak.loadUserProfile()
.success(profile => {
if (profile.attributes.Lat && profile.attributes.Lat[0] && profile.attributes.Lon && profile.attributes.Lon[0]) {
this.$store.commit('setHomeQth', {
latitude: parseFloat(profile.attributes.Lat[0]),
longitude: parseFloat(profile.attributes.Lon[0])
})
this.calculate()
} else {
this.$store.commit('setHomeQth', undefined)
}
})
this.calculate()
} else {
this.$store.commit('setHomeQth', undefined)
}
})
} else {
this.calculate()

Wyświetl plik

@ -8,7 +8,7 @@
<router-link :to="makeActivatorLink(props.row.otherCallsign.toUpperCase())">{{ props.row.otherCallsign.toUpperCase() }}</router-link>
</b-table-column>
<b-table-column field="band" label="Band" :custom-sort="sortBand" sortable numeric>
{{ bandForFrequency(props.row.band.replace('MHz', '')) }}
{{ bandForDbFrequency(props.row.band) }}
</b-table-column>
<b-table-column field="mode" label="Mode" sortable>
<ModeLabel :mode="props.row.mode" />
@ -31,8 +31,8 @@ export default {
},
methods: {
sortBand (a, b, isAsc) {
let fa = parseFloat(a.band.replace('MHz', ''))
let fb = parseFloat(b.band.replace('MHz', ''))
let fa = this.dbFrequencyToMHz(a.band)
let fb = this.dbFrequencyToMHz(b.band)
if (fa < fb) {
return (isAsc ? -1 : 1)
} else if (fa === fb) {

Wyświetl plik

@ -26,6 +26,7 @@
import Maidenhead from 'maidenhead'
import axios from 'axios'
import AltitudeLabel from './AltitudeLabel.vue'
import proj4 from 'proj4'
export default {
name: 'Coordinates',
@ -33,6 +34,7 @@ export default {
props: {
latitude: Number,
longitude: Number,
altitude: Number,
reference: String,
showMaidenhead: Boolean,
showElevation: Boolean
@ -40,7 +42,7 @@ export default {
computed: {
filteredActions () {
return this.actions.filter(action => {
return (action.url() !== null)
return (action.url() !== undefined)
})
},
maidenhead () {
@ -51,6 +53,30 @@ export default {
mounted () {
this.loadElevation()
},
created () {
proj4.defs('EPSG:29900', '+proj=tmerc +lat_0=53.5 +lon_0=-8 +k=1.000035 +x_0=200000 +y_0=250000 +ellps=mod_airy +towgs84=482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15 +units=m +no_defs')
proj4.defs('EPSG:3812', '+proj=lcc +lat_1=49.83333333333334 +lat_2=51.16666666666666 +lat_0=50.797815 +lon_0=4.359215833333333 +x_0=649328 +y_0=665262 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:3111', '+proj=lcc +lat_1=-36 +lat_2=-38 +lat_0=-37 +lon_0=145 +x_0=2500000 +y_0=2500000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:5316', '+proj=tmerc +lat_0=0 +lon_0=-7 +k=0.999997 +x_0=200000 +y_0=-6000000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:3346', '+proj=tmerc +lat_0=0 +lon_0=24 +k=0.9998 +x_0=500000 +y_0=0 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:3057', '+proj=lcc +lat_1=64.25 +lat_2=65.75 +lat_0=65 +lon_0=-19 +x_0=500000 +y_0=500000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:3059', '+proj=tmerc +lat_0=0 +lon_0=24 +k=0.9996 +x_0=500000 +y_0=-6000000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:2056', '+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=2600000 +y_0=1200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:2039', '+proj=tmerc +lat_0=31.73439361111111 +lon_0=35.20451694444445 +k=1.0000067 +x_0=219529.584 +y_0=626907.39 +ellps=GRS80 +towgs84=-48,55,52,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:3006', '+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:25832', '+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:29900', '+proj=tmerc +lat_0=53.5 +lon_0=-8 +k=1.000035 +x_0=200000 +y_0=250000 +ellps=mod_airy +towgs84=482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15 +units=m +no_defs')
proj4.defs('EPSG:3812', '+proj=lcc +lat_1=49.83333333333334 +lat_2=51.16666666666666 +lat_0=50.797815 +lon_0=4.359215833333333 +x_0=649328 +y_0=665262 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:3111', '+proj=lcc +lat_1=-36 +lat_2=-38 +lat_0=-37 +lon_0=145 +x_0=2500000 +y_0=2500000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:5316', '+proj=tmerc +lat_0=0 +lon_0=-7 +k=0.999997 +x_0=200000 +y_0=-6000000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:3346', '+proj=tmerc +lat_0=0 +lon_0=24 +k=0.9998 +x_0=500000 +y_0=0 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:3057', '+proj=lcc +lat_1=64.25 +lat_2=65.75 +lat_0=65 +lon_0=-19 +x_0=500000 +y_0=500000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:3059', '+proj=tmerc +lat_0=0 +lon_0=24 +k=0.9996 +x_0=500000 +y_0=-6000000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:2056', '+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=2600000 +y_0=1200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:2039', '+proj=tmerc +lat_0=31.73439361111111 +lon_0=35.20451694444445 +k=1.0000067 +x_0=219529.584 +y_0=626907.39 +ellps=GRS80 +towgs84=-48,55,52,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:3006', '+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
proj4.defs('EPSG:25832', '+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
},
watch: {
latitude () {
this.loadElevation()
@ -77,10 +103,14 @@ export default {
if (!this.latitude || !this.longitude || !this.showElevation) {
return
}
axios.post('https://ele.sotl.as/api', [[this.latitude, this.longitude]])
axios.post(process.env.VUE_APP_ELEVATION_API_URL, [[this.latitude, this.longitude]])
.then(result => {
this.elevation = Math.round(result.data[0])
})
},
convertLatLonToGrid (lat, lon, epsg) {
let inp = [lon, lat]
return proj4(epsg, inp)
}
},
data () {
@ -88,66 +118,226 @@ export default {
elevation: null,
actions: [
{
name: 'swisstopo',
name: 'Geoportail (FR)',
url: () => {
if (this.latitude >= 45.7 && this.latitude <= 47.85 && this.longitude >= 5.9 && this.longitude <= 10.9) {
return `https://map.geo.admin.ch/?swisssearch=${this.latitude},${this.longitude}`
if (this.reference && this.reference.match('^F[LKR]*/')) {
return `https://www.geoportail.gouv.fr/carte?c=${this.longitude},${this.latitude}&z=15&l0=GEOGRAPHICALGRIDSYSTEMS.MAPS.SCAN-EXPRESS.STANDARD::GEOPORTAIL:OGC:WMTS(1)&l1=GEOGRAPHICALGRIDSYSTEMS.PLANIGN::GEOPORTAIL:OGC:WMTS(1)&l2=GEOGRAPHICALGRIDSYSTEMS.MAPS.SCAN25TOUR::GEOPORTAIL:OGC:WMTS(1)&l3=GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2::GEOPORTAIL:OGC:WMTS(1)&l4=GEOGRAPHICALGRIDSYSTEMS.MAPS::GEOPORTAIL:OGC:WMTS(1)&permalink=yes`
}
return null
}
},
{
name: 'BayernAtlas',
name: 'IGN',
url: () => {
if (this.latitude >= 47.25 && this.latitude <= 50.6 && this.longitude >= 9.6 && this.longitude <= 13.85) {
return `https://geoportal.bayern.de/bayernatlas?lon=${this.longitude}&lat=${this.latitude}&zoom=10`
if (this.reference && this.reference.match('^(EA[1-9]|ZB2)/')) {
return `https://www.ign.es/iberpix2/visor/?&x=${this.longitude}&y=${this.latitude}&level=15&srid=4258&visible=MTN`
}
return null
}
},
{
name: 'CalTopo',
name: 'GSI Maps',
url: () => {
if (this.latitude >= 14 && this.longitude >= -169 && this.longitude <= -52) {
if (this.reference && this.reference.match('^JA[568]*/')) {
return `https://maps.gsi.go.jp/#16/${this.latitude}/${this.longitude}/`
}
}
},
{
name: 'Norgeskart',
url: () => {
if (this.reference && this.reference.match('^LA/')) {
return `https://www.norgeskart.no/#!?project=norgeskart&layers=1004&zoom=12&sok=${this.latitude},${this.longitude}`
}
}
},
{
name: 'TopoMap NZ',
url: () => {
if (this.reference && this.reference.match('^ZL[13789]/')) {
return `https://www.topomap.co.nz/NZTopoMap?v=2&ll=${this.latitude},${this.longitude}&z=15`
}
}
},
{
name: 'CalTopo (NA)',
url: () => {
if (this.reference && this.reference.match('^[WK]|^VE|^XE')) {
return `https://caltopo.com/map.html#ll=${this.latitude},${this.longitude}&z=15&b=t&o=f16a%2Cr&n=1,0.25`
}
return null
}
},
{
name: 'OS Maps',
name: 'Geoportal Bayern',
url: () => {
if (this.latitude >= 49.8 && this.latitude <= 60 && this.longitude >= -9 && this.longitude <= 2) {
return `https://osmaps.ordnancesurvey.co.uk/${this.latitude},${this.longitude},15/pin`
if (this.reference && this.reference.match('^(DL/|DM/BM)')) {
let p = this.convertLatLonToGrid(this.latitude, this.longitude, 'EPSG:25832')
return `https://geoportal.bayern.de/bayernatlas/index.html?zoom=12&lang=de&topic=ba&bgLayer=tk&E=${p[0]}&N=${p[1]}&catalogNodes=122`
}
return null
}
},
{
name: 'Geoportal (HR)',
name: 'maps.rlp.de',
url: () => {
if (this.latitude >= 42.396 && this.latitude <= 46.324 && this.longitude >= 13.789 && this.longitude <= 18.497) {
return `https://geoportal.dgu.hr/#/?lng=${this.longitude}&lat=${this.latitude}&zoom=7`
if (this.reference && this.reference.match('^DM/RP')) {
let p = this.convertLatLonToGrid(this.latitude, this.longitude, 'EPSG:25832')
return `https://maps.rlp.de/?layerIDs=152,3&visibility=true,true&transparency=0,0&center=${p[0]},${p[1]}&zoomlevel=8`
}
return null
}
},
{
name: 'LocationSA',
name: 'Karten des BKG',
url: () => {
if (this.latitude >= -38.062 && this.latitude <= -25.957 && this.longitude >= 128.957 && this.longitude <= 140.953) {
return `http://location.sa.gov.au/viewer/?map=topographic&x=${this.longitude}&y=${this.latitude}&z=17`
if (this.reference && this.reference.match('^D[LM]/')) {
let p = this.convertLatLonToGrid(this.latitude, this.longitude, 'EPSG:25832')
return `https://sg.geodatenzentrum.de/web_bkg_webmap/applications/bkgmaps/minimal.html?zoom=11&lat=${p[1]}&lon=${p[0]}&layers=B000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFT`
}
}
},
{
name: 'UK OS Map (Bing)',
url: () => {
if (this.reference && this.reference.match('^G$|^G[^IJU]+')) {
return `https://www.bing.com/maps?osid=93955629-66b5-4407-9864-aff11618f451&cp=${this.latitude}~${this.longitude}&lvl=15&style=s&v=2&sV=2&form=S00027`
}
}
},
{
name: 'OSNI',
url: () => {
if (this.reference && this.reference.match('^GI/')) {
let p = this.convertLatLonToGrid(this.latitude, this.longitude, 'EPSG:29900')
return `https://maps.spatialni.gov.uk/?marker=${p[0]},${p[1]},29900,g,,g&level=7`
}
}
},
{
name: 'Geoportail (LX)',
url: () => {
if (this.reference && this.reference.match('^LX/')) {
let p = this.convertLatLonToGrid(this.latitude, this.longitude, 'EPSG:3857')
return `https://map.geoportail.lu/theme/main?version=3&zoom=16&X=${p[0]}&Y=${p[1]}&lang=fr&rotation=0&layers=206&opacities=1&bgLayer=blank`
}
}
},
{
name: 'Geoportal (LT)',
url: () => {
if (this.reference && this.reference.match('^LY/')) {
let p = this.convertLatLonToGrid(this.latitude, this.longitude, 'EPSG:3346')
return `https://www.geoportal.lt/map/#s=3346&x=${p[0]}&y=${p[1]}&l=8&b=default`
}
return null
}
},
{
name: 'SK Geodesy',
url: () => {
if (this.latitude >= 47.776 && this.latitude <= 49.534 && this.longitude >= 17.041 && this.longitude <= 22.581) {
if (this.reference && this.reference.match('^OM/')) {
return `https://zbgis.skgeodesy.sk/mkzbgis?bm=zbgis&z=16&c=${this.longitude},${this.latitude}#`
}
return null
}
},
{
name: 'NGI',
url: () => {
if (this.reference && this.reference.match('^ON/')) {
let p = this.convertLatLonToGrid(this.latitude, this.longitude, 'EPSG:3812')
return `https://topomapviewer.ngi.be/?l=en&x=${p[0]}&y=${p[1]}&zoom=9&baseLayer=classic.maps`
}
}
},
{
name: 'Basemap.at',
url: () => {
if (this.reference && this.reference.match('^OE/')) {
let p = this.convertLatLonToGrid(this.latitude, this.longitude, 'EPSG:3857')
return `https://basemap.at/bmapp/index.html#{%22center%22:[${p[0]},${p[1]}],%22zoom%22:16,%22rotation%22:0,%22layers%22:%220100000000%22}`
}
}
},
{
name: 'Føroyakort',
url: () => {
if (this.reference && this.reference.match('^OY/')) {
let p = this.convertLatLonToGrid(this.latitude, this.longitude, 'EPSG:5316')
return `https://kort.foroyakort.fo/kort/?center=${p[0]},${p[1]},5316&level=9`
}
}
},
{
name: 'Kortasjá',
url: () => {
if (this.reference && this.reference.match('^TF/')) {
let p = this.convertLatLonToGrid(this.latitude, this.longitude, 'EPSG:3057')
return `https://kortasja.lmi.is/mapview/?application=kortasja&lang=is&center=${p[0]},${p[1]}&zoom=11&layers=219,225,228,286,221 X`
}
}
},
{
name: 'SIXmaps',
url: () => {
if (this.reference && this.reference.match('^VK[12]/')) {
let p = this.convertLatLonToGrid(this.latitude, this.longitude, 'EPSG:3857')
return `https://portal.spatial.nsw.gov.au/portal/apps/webappviewer/index.html?center=${p[0]},${p[1]},102100&level=16`
}
}
},
{
name: 'MapshareVIC',
url: () => {
if (this.reference && this.reference.match('^VK3/')) {
let p = this.convertLatLonToGrid(this.latitude, this.longitude, 'EPSG:3111')
return `https://mapshare.vic.gov.au/MapshareVic/?layerTheme=5&scale=3000&basemap=bWFwc2NhcGUgY29sb3Vy&center=${p[0]},${p[1]}`
}
}
},
{
name: 'QTopo',
url: () => {
if (this.reference && this.reference.match('^VK4/')) {
let p = this.convertLatLonToGrid(this.latitude, this.longitude, 'EPSG:3857')
return `https://qtopo.information.qld.gov.au/?center=${p[0]},${p[1]},102100&level=16`
}
}
},
{
name: 'LocationSA',
url: () => {
if (this.reference && this.reference.match('^VK5/')) {
return `https://location.sa.gov.au/viewer/?map=topographic&x=${this.longitude}&y=${this.latitude}&z=16&uids=&pinx=${this.longitude}&piny=${this.latitude}&pinTitle=&pinText=%%sumCode%%`
}
}
},
{
name: 'LGIA',
url: () => {
if (this.reference && this.reference.match('^YL/')) {
let p = this.convertLatLonToGrid(this.latitude, this.longitude, 'EPSG:3059')
return `https://kartes.lgia.gov.lv/karte/?x=${p[1]}&y=${p[0]}&lx=5565.0&ly=3130.313&l=1,8,9,10,13,14,15,40,51,62,63,64,65,66,67,68,69,70`
}
}
},
{
name: 'Govmap',
url: () => {
if (this.reference && this.reference.match('^4X/')) {
let p = this.convertLatLonToGrid(this.latitude, this.longitude, 'EPSG:2039')
return `https://www.govmap.gov.il/?c=${p[0]},${p[1]}&z=4&b=9`
}
}
},
{
name: 'Geoportal (HR)',
url: () => {
if (this.reference && this.reference.match('^9A/')) {
return `https://geoportal.dgu.hr/#/?lng=${this.longitude}&lat=${this.latitude}&zoom=7`
}
}
},
{
name: 'swisstopo',
url: () => {
if (this.latitude >= 45.7 && this.latitude <= 47.85 && this.longitude >= 5.9 && this.longitude <= 10.9) {
return `https://map.geo.admin.ch/?swisssearch=${this.latitude},${this.longitude}`
}
}
},
{
@ -156,7 +346,6 @@ export default {
if (this.latitude >= 74.117 && this.latitude <= 80.948 && this.longitude >= 7.338 && this.longitude <= 33.631) {
return `https://toposvalbard.npolar.no/?lat=${this.latitude.toFixed(6)}&long=${this.longitude.toFixed(6)}&zoom=8&layer=map`
}
return null
}
},
{
@ -165,7 +354,6 @@ export default {
if (this.latitude >= 70.795 && this.latitude <= 71.175 && this.longitude >= -9.253 && this.longitude <= -7.838) {
return `https://topojanmayen.npolar.no/?lat=${this.latitude.toFixed(6)}&long=${this.longitude.toFixed(6)}&zoom=8&layer=map`
}
return null
}
},
{
@ -180,6 +368,30 @@ export default {
return `https://www.bing.com/maps?cp=${this.latitude}~${this.longitude}&lvl=15&style=s&v=2`
}
},
{
name: 'Gaia GPS',
url: () => {
return `https://www.gaiagps.com/map/?loc=14/${this.longitude}/${this.latitude}&layer=GaiaTopoRasterMeters`
}
},
{
name: 'Mapy.cz',
url: () => {
return `https://en.mapy.cz/turisticka?x=${this.longitude}&y=${this.latitude}&z=17`
}
},
{
name: 'FatMap',
url: () => {
let cameraAltitude = 10000
if (this.altitude) {
cameraAltitude = Math.round((this.altitude * 2) * 3.28)
} else if (this.elevation) {
cameraAltitude = Math.round((this.elevation * 2) * 3.28)
}
return `https://fatmap.com/adventures/@${this.latitude},${this.longitude},${cameraAltitude},-66,-12,satellite`
}
},
{
name: 'OpenStreetMap',
url: () => {
@ -192,6 +404,14 @@ export default {
return `https://www.opentopomap.org/#marker=16/${this.latitude}/${this.longitude}`
}
},
{
name: 'Activation Zone Estimator',
url: () => {
if (this.reference) {
return `https://activation.zone/?summitRef=${this.reference}`
}
}
},
{
name: 'SummitPost',
url: () => {
@ -204,7 +424,6 @@ export default {
if (this.reference) {
return `https://summits.sota.org.uk/summit/${this.reference}`
}
return null
}
},
{
@ -213,7 +432,6 @@ export default {
if (this.reference) {
return `https://www.sotamaps.org/summit/${this.reference}`
}
return null
}
},
{

Wyświetl plik

@ -7,18 +7,19 @@ export default {
name: 'DistanceLabel',
props: {
distance: Number,
highPrecision: Boolean
highPrecision: Boolean,
smallUnits: Boolean
},
computed: {
displayDistance () {
if (this.$store.state.altitudeUnits === 'ft') {
if (this.highPrecision && this.distance < (1000 / 3.28084)) {
if (this.smallUnits || (this.highPrecision && this.distance < (1000 / 3.28084))) {
return Math.round(this.distance * 3.28084) + ' ft'
} else {
return (this.distance * 0.000621371).toFixed(1) + ' mi'
}
} else {
if (this.highPrecision && this.distance < 1000) {
if (this.smallUnits || (this.highPrecision && this.distance < 1000)) {
return Math.round(this.distance) + ' m'
} else {
return (this.distance / 1000).toFixed(1) + ' km'

Wyświetl plik

@ -4,6 +4,7 @@
<b-button slot="trigger" type="is-info" size="is-small" outlined icon-left="file-download" icon-right="angle-down">Download</b-button>
<b-dropdown-item has-link><a :href="makeUrlForType('gpx')">GPX file</a></b-dropdown-item>
<b-dropdown-item has-link><a :href="makeUrlForType('kml')">KML file</a></b-dropdown-item>
<b-dropdown-item has-link><a :href="makeUrlForType('geojson')">GeoJSON file</a></b-dropdown-item>
<b-dropdown-item separator />
<b-dropdown-item custom disabled><b>Label options</b></b-dropdown-item>
<b-dropdown-item custom><b-checkbox v-model="nameopts" native-value="name">Summit name</b-checkbox></b-dropdown-item>

Wyświetl plik

@ -10,7 +10,7 @@
<b-field label="Summit reference" :message="summitDisplay" :type="summitType" :class="summitLabelClass" expanded>
<b-field>
<b-input type="text" ref="summitCode" v-model="summitCode" placeholder="XX/YY-000" :loading="summitLoading" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" required />
<b-input type="text" class="summit-code" ref="summitCode" v-model="summitCode" placeholder="XX/YY-000" :loading="summitLoading" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" required />
<p class="control">
<NearbySummitsList @summitSelected="onSummitSelected" />
</p>
@ -154,7 +154,7 @@ export default {
if (matches) {
this.summitCode = (matches[1] + '/' + matches[2] + '-' + matches[3]).toUpperCase()
this.summitLoading = true
axios.get('https://api.sotl.as/summits/' + this.summitCode)
axios.get(process.env.VUE_APP_API_URL + '/summits/' + this.summitCode)
.then(response => {
this.summitLoading = false
this.summitInvalid = false
@ -248,6 +248,15 @@ export default {
this.$store.dispatch('reloadAlerts')
this.$parent.close()
})
.catch(err => {
this.$buefy.dialog.alert({
title: 'Error',
message: 'Could not post alert: ' + err.message,
type: 'is-danger',
ariaRole: 'alertdialog',
ariaModal: true
})
})
.finally(() => {
this.posting = false
})

Wyświetl plik

@ -10,7 +10,7 @@
<b-field label="Summit reference" :message="summitDisplay" :type="summitType" :class="summitLabelClass" expanded>
<b-field>
<b-input type="text" ref="summitCode" v-model="summitCode" placeholder="XX/YY-000" :loading="summitLoading" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" required />
<b-input type="text" class="summit-code" ref="summitCode" v-model="summitCode" placeholder="XX/YY-000" :loading="summitLoading" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" required />
<p class="control">
<NearbySummitsList @summitSelected="onSummitSelected" />
</p>
@ -19,7 +19,7 @@
<b-field label="Frequency" :message="maybeKhz ? 'Do you really mean ' + frequency + ' MHz, or are you missing a dot?' : ''" :type="maybeKhz ? 'is-warning' : ''">
<b-field :type="maybeKhz ? 'is-warning' : ''">
<b-input v-model="frequency" type="number" step="any" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" required />
<FrequencyInput v-model="frequency" />
<p class="control">
<span class="button is-static">MHz</span>
</p>
@ -49,10 +49,11 @@ import utils from '../mixins/utils.js'
import prefs from '../mixins/prefs.js'
import sotawatch from '../mixins/sotawatch.js'
import NearbySummitsList from './NearbySummitsList.vue'
import FrequencyInput from './FrequencyInput.vue'
export default {
components: {
NearbySummitsList
NearbySummitsList, FrequencyInput
},
mixins: [utils, prefs, sotawatch],
props: {
@ -140,7 +141,7 @@ export default {
if (matches) {
this.summitCode = (matches[1] + '/' + matches[2] + '-' + matches[3]).toUpperCase()
this.summitLoading = true
axios.get('https://api.sotl.as/summits/' + this.summitCode)
axios.get(process.env.VUE_APP_API_URL + '/summits/' + this.summitCode)
.then(response => {
this.summitLoading = false
this.summitInvalid = false
@ -217,6 +218,15 @@ export default {
this.$parent.close()
})
.catch(err => {
this.$buefy.dialog.alert({
title: 'Error',
message: 'Could not post spot: ' + err.message,
type: 'is-danger',
ariaRole: 'alertdialog',
ariaModal: true
})
})
.finally(() => {
this.posting = false
})

Wyświetl plik

@ -0,0 +1,23 @@
<template>
<b-input :value="value" type="number" inputmode="decimal" lang="en_EN" step="any" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" required @keydown.native="frequencyKeydown" @input="updateValue" />
</template>
<script>
export default {
props: {
value: String
},
methods: {
updateValue (value) {
this.$emit('input', value)
},
frequencyKeydown (event) {
if (event.keyCode === 188) {
event.target.value += '.'
event.preventDefault()
return false
}
}
}
}
</script>

Wyświetl plik

@ -28,6 +28,18 @@ export default {
suffixY: {
type: String,
default: ''
},
height: {
type: [String, Number],
default: 250
},
spline: {
type: [String, Number],
default: 0
},
regionFill: {
type: Boolean,
default: true
}
},
methods: {
@ -61,7 +73,7 @@ export default {
datasets: datasets
},
type: 'line',
height: 250,
height: parseInt(this.height),
colors: ['red'],
axisOptions: {
xAxisMode: 'tick',
@ -69,7 +81,8 @@ export default {
},
lineOptions: {
hideDots: true,
regionFill: true
regionFill: this.regionFill,
spline: parseInt(this.spline)
},
tooltipOptions: {
formatTooltipX: d => d + this.suffixX,

Wyświetl plik

@ -10,12 +10,15 @@ export default {
inject: ['map'],
methods: {
downloadMap () {
let link = document.createElement('a')
link.download = 'map.png'
link.href = this.map.getCanvas().toDataURL()
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
this.map.once('render', () => {
let link = document.createElement('a')
link.download = 'map.png'
link.href = this.map.getCanvas().toDataURL()
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
})
this.map._render()
}
}
}

Wyświetl plik

@ -2,6 +2,7 @@
<div>
<div v-if="chartData || loading" class="elevation-chart">
<div class="elevation-controls">
<div v-if="ascent !== null && descent !== null" class="adescent-info"> <DistanceLabel :distance="ascent" small-units /> <DistanceLabel :distance="descent" small-units /></div>
<b-button size="is-small" type="is-text" icon-left="window-close" @click="hideElevationProfile" />
</div>
<b-loading :active="loading" :is-full-page="false" />
@ -19,10 +20,11 @@ import moment from 'moment'
import axios from 'axios'
import utils from '../mixins/utils.js'
import LineChart from './LineChart.vue'
import DistanceLabel from './DistanceLabel.vue'
import { gpx, kml } from '@tmcw/togeojson'
export default {
components: { LineChart },
components: { LineChart, DistanceLabel },
inject: ['map'],
mixins: [utils],
mounted () {
@ -394,7 +396,7 @@ export default {
}
this.loading = true
axios.post('https://ele.sotl.as/api', eleCoordinates)
axios.post(process.env.VUE_APP_ELEVATION_API_URL, eleCoordinates)
.then(result => {
this.chartData = result.data.map((elevation, i) => {
return {
@ -402,6 +404,21 @@ export default {
elevation: this.renderElevation(elevation)
}
})
let ascent = 0
let descent = 0
let lastElevation = null
result.data.forEach(elevation => {
if (lastElevation !== null) {
if (lastElevation < elevation) {
ascent += elevation - lastElevation
} else {
descent += lastElevation - elevation
}
}
lastElevation = elevation
})
this.ascent = ascent
this.descent = descent
this.loading = false
})
.finally(() => {
@ -410,6 +427,8 @@ export default {
},
hideElevationProfile () {
this.chartData = null
this.ascent = null
this.descent = null
},
renderElevation (elevation) {
if (this.$store.state.altitudeUnits === 'ft') {
@ -449,6 +468,8 @@ export default {
data () {
return {
chartData: null,
ascent: null,
descent: null,
loading: false,
selectedFeatureId: null
}
@ -474,4 +495,11 @@ export default {
right: 0px;
z-index: 10;
}
.adescent-info {
padding-top: 0.3em;
color: #777;
display: inline-block;
font-size: 0.8rem;
white-space: nowrap;
}
</style>

Wyświetl plik

@ -138,7 +138,7 @@ export default {
let filterPromises = []
if (this.activationsEnabled) {
if (this.activationsFrom && this.activationsTo && this.activationsTo < this.activationsFrom) {
if (this.activationsFrom && this.activationsTo && parseInt(this.activationsTo) < parseInt(this.activationsFrom)) {
let tmp = this.activationsFrom
this.activationsFrom = this.activationsTo
this.activationsTo = tmp
@ -152,7 +152,7 @@ export default {
}
if (this.pointsEnabled) {
if (this.pointsFrom && this.pointsTo && this.pointsTo < this.pointsFrom) {
if (this.pointsFrom && this.pointsTo && parseInt(this.pointsTo) < parseInt(this.pointsFrom)) {
let tmp = this.pointsFrom
this.pointsFrom = this.pointsTo
this.pointsTo = tmp
@ -172,7 +172,7 @@ export default {
if (this.altitudeTo) {
this.altitudeTo = parseInt(this.altitudeTo)
}
if (this.altitudeFrom && this.altitudeTo && this.altitudeTo < this.altitudeFrom) {
if (this.altitudeFrom && this.altitudeTo && parseInt(this.altitudeTo) < parseInt(this.altitudeFrom)) {
let tmp = this.altitudeFrom
this.altitudeFrom = this.altitudeTo
this.altitudeTo = tmp

Wyświetl plik

@ -15,34 +15,35 @@
<b-field grouped>
<b-checkbox v-model="mapOptions.regions" size="is-small" @input="setMapOption('regions', $event)">Regions</b-checkbox>
</b-field>
<b-field v-if="mapType !== 'swisstopo_raster'" grouped>
<b-field v-if="mapType === 'openmaptiles' || mapType === 'swisstopo_vector'" grouped>
<b-checkbox v-model="mapOptions.contours" size="is-small" @input="setMapOption('contours', $event)">Contour lines</b-checkbox>
</b-field>
<b-field v-if="mapType !== 'swisstopo_raster'" grouped>
<b-field v-if="mapType === 'openmaptiles' || mapType === 'swisstopo_vector'" grouped>
<b-checkbox v-model="mapOptions.hillshading" size="is-small" @input="setMapOption('hillshading', $event)">Hillshading</b-checkbox>
</b-field>
<b-field v-if="mapType.startsWith('swisstopo')" grouped>
<b-checkbox v-model="mapOptions.az" size="is-small" @input="setMapOption('az', $event)">
Activation zones
<b-icon pack="fas" icon="info-circle" size="is-small" type="is-info" @click.native="showActivationZoneInfo" />
</b-checkbox>
</b-field>
</div>
<div class="map-option">
<template v-if="mapType === 'swisstopo' || mapType === 'swisstopo_raster'">
<div class="map-option" v-if="mapType !== 'toposvalbard' && mapType !== 'norkart'">
<b-field grouped>
<b-checkbox v-model="mapOptions.difficulty" size="is-small" @input="setMapOption('difficulty', $event)">Hiking difficulty</b-checkbox>
</b-field>
<template v-if="mapType.startsWith('swisstopo')">
<b-field grouped>
<b-checkbox v-model="mapOptions.difficulty" size="is-small" @input="setMapOption('difficulty', $event)">Wanderwege</b-checkbox>
<b-checkbox v-model="mapOptions.skiing" size="is-small" @input="setMapOption('skiing', $event)">Ski routes</b-checkbox>
</b-field>
<b-field grouped>
<b-checkbox v-model="mapOptions.skiing" size="is-small" @input="setMapOption('skiing', $event)">Skirouten</b-checkbox>
<b-checkbox v-model="mapOptions.snowshoe" size="is-small" @input="setMapOption('snowshoe', $event)">Snowshoe routes</b-checkbox>
</b-field>
<b-field grouped>
<b-checkbox v-model="mapOptions.snowshoe" size="is-small" @input="setMapOption('snowshoe', $event)">Schneeschuhrouten</b-checkbox>
<b-checkbox v-model="mapOptions.slope_classes" size="is-small" @input="setMapOption('slope_classes', $event)">Slope classes over 30°</b-checkbox>
</b-field>
<b-field grouped>
<b-checkbox v-model="mapOptions.slope_classes" size="is-small" @input="setMapOption('slope_classes', $event)">Hangneigungsklassen über 30°</b-checkbox>
</b-field>
<b-field grouped>
<b-checkbox v-model="mapOptions.wildlife" size="is-small" @input="setMapOption('wildlife', $event)">Wildruhezonen und Schutzgebiete</b-checkbox>
</b-field>
</template>
<template v-else>
<b-field grouped>
<b-checkbox v-model="mapOptions.difficulty" size="is-small" @input="setMapOption('difficulty', $event)">Hiking difficulty</b-checkbox>
<b-checkbox v-model="mapOptions.wildlife" size="is-small" @input="setMapOption('wildlife', $event)">Wildlife reserves and areas</b-checkbox>
</b-field>
</template>
</div>
@ -50,6 +51,9 @@
<b-field grouped>
<b-checkbox v-model="mapOptions.spots" size="is-small" @input="setMapOption('spots', $event)">Recent spots</b-checkbox>
</b-field>
<b-field grouped>
<b-checkbox v-model="mapOptions.alerts" size="is-small" @input="setMapOption('alerts', $event)">Alerts</b-checkbox>
</b-field>
<b-field grouped>
<b-checkbox v-model="mapOptions.inactive" size="is-small" @input="setMapOption('inactive', $event)">Inactive summits</b-checkbox>
</b-field>
@ -73,6 +77,7 @@ import mapstyle from '../mixins/mapstyle.js'
import prefs from '../mixins/prefs.js'
const RECENT_SPOT_AGE = 30 * 60 * 1000
const MAX_ALERT_AGE = 3 * 60 * 60 * 1000
export default {
name: 'MapOptionsControl',
@ -103,6 +108,14 @@ export default {
return spot.summit.code
})
},
alerts () {
let now = moment.utc()
return this.$store.state.alerts.filter(alert => {
return (now.diff(alert.dateActivated) < MAX_ALERT_AGE)
}).map(alert => {
return alert.summit.code
})
},
mapType: {
get () {
return this.$store.state.mapType
@ -122,9 +135,16 @@ export default {
},
immediate: true
},
alerts: {
handler () {
this.updateAlerts()
},
immediate: true
},
mapOptions: {
handler () {
this.updateRecentSpots()
this.updateAlerts()
},
deep: true
},
@ -148,14 +168,35 @@ export default {
this.map.setFilter('summits_highlight', ['in', 'code'])
}
},
updateAlerts () {
if (this.mapOptions.alerts) {
this.map.setFilter('summits_highlight_alerts', ['in', 'code', ...this.alerts])
} else {
this.map.setFilter('summits_highlight_alerts', ['in', 'code'])
}
},
spotsShown () {
return this.mapOptions.spots
},
alertsShown () {
return this.mapOptions.alerts
},
openCloseMapOptions () {
this.open = !this.open
},
setMapOption (option, value) {
this.$store.commit('setMapOption', { option, value })
},
showActivationZoneInfo (event) {
event.preventDefault()
this.$buefy.dialog.alert({
title: 'Activation zones',
message: '<p style="margin-bottom: 0.5em">The activation zones for HB/HB0 have been calculated using <a href="https://www.swisstopo.admin.ch/de/geodata/height/alti3d.html" target="_blank">swissALTI3D</a> data from swisstopo (spatial resolution 0.5 m, accuracy ± 0.3 – 3 m (1σ) depending on the region).</p><p style="font-size: 0.8em">The activator is always responsible for ensuring that the operation takes place within the activation zone.</p>',
type: 'is-info',
hasIcon: true,
icon: 'info-circle',
iconPack: 'fas'
})
}
}
}

Wyświetl plik

@ -41,6 +41,18 @@ export default {
mixins: [tracks],
computed: {
trackLayer () {
let lineColor = '#1cd60d'
let lineOpacity = 0.75
let lineWidth = 3
if (this.route.highlight === true) {
lineColor = '#4fe005'
lineOpacity = 0.85
lineWidth = 4.5
} else if (this.route.highlight === false) {
lineColor = '#86bc6b'
lineOpacity = 0.25
}
return {
type: 'line',
layout: {
@ -48,9 +60,9 @@ export default {
'line-cap': 'round'
},
paint: {
'line-color': this.route.highlight ? '#ff0000' : '#245acd',
'line-width': 3,
'line-opacity': 0.75
'line-color': lineColor,
'line-width': lineWidth,
'line-opacity': lineOpacity
}
}
},

Wyświetl plik

@ -1,5 +1,5 @@
<template>
<MglMap v-if="(mapCenter || bounds) && mapStyle" :mapStyle="mapStyle" :bounds="bounds" :fitBoundsOptions="fitBoundsOptions" :center="mapCenter" :zoom="12.5" :attributionControl="false" @load="onMapLoaded" @click="onMapClicked" @contextmenu="onMapRightClicked" @idle="onMapIdle">
<MglMap v-if="(mapCenter || bounds) && mapStyle" :key="mapKey" :mapStyle="mapStyle" :bounds="bounds" :fitBoundsOptions="fitBoundsOptions" :center="mapCenter" :zoom="12.5" :attributionControl="false" @load="onMapLoaded" @click="onMapClicked" @contextmenu="onMapRightClicked" @idle="onMapIdle">
<MglGeolocateControl v-if="!$mq.mobile || isEnlarged" :positionOptions="{ enableHighAccuracy: true }" :fitBoundsOptions="{ maxZoom: 12.5 }" :trackUserLocation="true" position="top-right" />
<MglNavigationControl v-if="!$mq.mobile" position="top-right" :showCompass="false" />
<MglScaleControl v-if="!$mq.mobile || isEnlarged" position="bottom-left" />
@ -101,6 +101,13 @@ export default {
mapOptions.regions = false
mapOptions.inactive = this.showInactiveSummits
return mapOptions
},
mapKey () {
if (this.summit) {
return this.summit.code
} else {
return undefined
}
}
},
methods: {

Wyświetl plik

@ -1,10 +1,16 @@
<template>
<b-navbar wrapper-class="container" :fixed-top="true" :close-on-click="false" :isActive.sync="burgerActive">
<template #brand>
<b-navbar-item tag="router-link" to="/about"><img src="../assets/sotlas.svg" alt="Logo"></b-navbar-item>
<b-navbar-item tag="router-link" to="/about">
<img v-if="$mq.widescreen" src="../assets/sotlas.svg" alt="Logo">
<img v-else src="../assets/sotlas-icon.svg" alt="Logo">
</b-navbar-item>
<b-navbar-item class="clock" tag="div">
<font-awesome-icon :icon="['far', 'clock']" class="faicon" /> {{ clock }}
</b-navbar-item>
<b-navbar-item tag="router-link" to="/solar_history">
<SolarData />
</b-navbar-item>
</template>
<template #end>
<b-navbar-item tag="div">
@ -30,6 +36,7 @@
import moment from 'moment'
import SearchField from '../components/SearchField.vue'
import LoginButton from '../components/LoginButton.vue'
import SolarData from '../components/SolarData.vue'
import utils from '../mixins/utils.js'
import EventBus from '../event-bus'
@ -37,7 +44,7 @@ export default {
name: 'NavBar',
mixins: [ utils ],
components: {
SearchField, LoginButton
SearchField, LoginButton, SolarData
},
props: {
query: {

Wyświetl plik

@ -1,5 +1,5 @@
<template>
<b-dropdown ref="dropdown" aria-role="list" position="is-bottom-left" class="nearby-summits">
<b-dropdown ref="dropdown" aria-role="list" position="is-bottom-left" class="nearby-summits" append-to-body>
<b-button slot="trigger" icon-right="angle-down" :loading="loading" @click.stop="clickButton">Nearby</b-button>
<b-dropdown-item v-for="summit in nearbySummits" :key="summit.code" aria-role="listitem" @click="clickSummit(summit)">
<div class="summit-title"><div class="summit-name">{{ summit.name }}</div><div class="summit-alt"><AltitudeLabel :altitude="summit.altitude" /></div></div>
@ -28,7 +28,7 @@ export default {
this.loading = true
navigator.geolocation.getCurrentPosition(
position => {
axios.get('https://api.sotl.as/summits/near', { params: { lat: position.coords.latitude, lon: position.coords.longitude, limit: 5, maxDistance: 100000 } })
axios.get(process.env.VUE_APP_API_URL + '/summits/near', { params: { lat: position.coords.latitude, lon: position.coords.longitude, limit: 5, maxDistance: 100000 } })
.then(response => {
if (response.data.length === 0) {
alert('No summits within 100 km.')

Wyświetl plik

@ -47,7 +47,7 @@ export default {
if (res.data.length > 0 && !res.data[0].coordinates && !this.gpsNotificationShown) {
this.$buefy.dialog.alert({
title: 'No GPS information',
message: '<p>Your photo has been uploaded successfully, but did not contain GPS coordinates in its metadata (Exif header). If possible, try uploading original full-resolution files from your camera. SOTLAS will automatically reduce the resolution if needed, and will use the GPS coordinates to show the photos on the map if the position is accurate enough.</p><p><small>This alert will not appear again for future uploads with missing GPS information.</small></p>',
message: '<p>Your photo has been uploaded successfully, but did not contain GPS coordinates in its metadata (Exif header). If possible, try uploading original full-resolution files from your camera, and use your computer instead of your mobile phone to upload the photos (as mobile browsers will often strip metadata while uploading).</p><p>SOTLAS will automatically reduce the resolution if needed, and will use the GPS coordinates to show the photos on the map if the position is accurate enough.</p><p><small>This alert will not appear again for future uploads with missing GPS information.</small></p>',
type: 'is-info',
hasIcon: true,
icon: 'info-circle',

Wyświetl plik

@ -5,11 +5,11 @@
{{ props.row.TimeOfDay }}
</b-table-column>
<b-table-column field="OtherCallsign" label="Callsign" class="nowrap" sortable>
<CountryFlag :country="isoCodeForCallsign(props.row.OtherCallsign)" class="flag" />
<router-link :to="makeActivatorLink(props.row.OtherCallsign)">{{ props.row.OtherCallsign }}</router-link>
<CountryFlag :country="isoCodeForCallsign(props.row.OtherCallsign.trim())" class="flag" />
<router-link :to="makeActivatorLink(props.row.OtherCallsign.trim())">{{ props.row.OtherCallsign.trim() }}</router-link>
</b-table-column>
<b-table-column field="Band" label="Band" :custom-sort="sortBand" class="nowrap" sortable numeric>
{{ bandForFrequency(props.row.Band.replace('MHz', '')) }}
{{ bandForDbFrequency(props.row.Band) }}
</b-table-column>
<b-table-column field="Mode" label="Mode" class="mode nowrap" sortable>
<ModeLabel :mode="props.row.Mode" />
@ -40,8 +40,8 @@ export default {
mixins: [utils],
methods: {
sortBand (a, b, isAsc) {
let fa = parseFloat(a.Band.replace('MHz', ''))
let fb = parseFloat(b.Band.replace('MHz', ''))
let fa = this.dbFrequencyToMHz(a.Band)
let fb = this.dbFrequencyToMHz(b.Band)
if (fa < fb) {
return (isAsc ? -1 : 1)
} else if (fa === fb) {

Wyświetl plik

@ -86,7 +86,7 @@ export default {
}
@media screen and (min-width: 1024px) and (max-width: 1215px) {
.search-input {
max-width: 11rem;
max-width: 14rem;
}
}
</style>

Wyświetl plik

@ -0,0 +1,88 @@
<template>
<div class="solar-container" v-if="latest !== null">
<div><label>SFI</label>{{ latest.sfi }}</div>
<div><label>SN</label>{{ latest.r }}</div>
<div :class="[kAttribute]"><label>K</label>{{ latest.k }}</div>
<div><label>A</label>{{ latest.a }}</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'SolarData',
mounted () {
this.loadSolarData()
},
computed: {
kAttribute () {
if (this.latest === null) {
return ''
}
if (this.latest.k <= 2) {
return 'k-quiet'
} else if (this.latest.k === 3) {
return 'k-unsettled'
} else if (this.latest.k === 4) {
return 'k-active'
} else if (this.latest.k <= 7) {
return 'k-storm'
} else {
return 'k-severestorm'
}
}
},
methods: {
loadSolarData () {
axios.get(process.env.VUE_APP_API_URL + '/solardata/latest')
.then(response => {
this.latest = response.data
})
}
},
data () {
return {
latest: null
}
}
}
</script>
<style scoped>
.solar-container {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(2, 1fr);
grid-column-gap: 0.3rem;
font-size: 0.8rem;
line-height: 1.05rem;
background-color: #eee;
border-radius: 10px;
padding: 0.15rem 0.4rem;
font-weight: bold;
text-align: right;
}
.solar-container label {
font-size: 0.7rem;
margin-right: 0.2rem;
font-weight: normal;
opacity: 0.6;
}
.solar-container .k-quiet {
color: #106f06;
}
.solar-container .k-unsettled {
color: #817f03;
}
.solar-container .k-active {
color: #8c5903;
}
.solar-container .k-storm {
color: #8d0002;
}
.solar-container .k-severestorm {
color: #7e0053;
}
</style>

Wyświetl plik

@ -192,6 +192,15 @@ export default {
.then(response => {
this.$store.commit('deleteSpot', spot)
})
.catch(err => {
this.$buefy.dialog.alert({
title: 'Error',
message: 'Could not delete spot: ' + err.message,
type: 'is-danger',
ariaRole: 'alertdialog',
ariaModal: true
})
})
}
})
}

Wyświetl plik

@ -13,6 +13,7 @@
<tr><th>Activations</th><td>{{ summit.activationCount }}</td></tr>
<tr v-if="summit.activationDate"><th>Last activation</th><td>{{ summit.activationDate | formatActivationDate }} (<router-link :to="makeActivatorLink(summit.activationCall)">{{ summit.activationCall }}</router-link>)</td></tr>
<tr v-if="lastSpot"><th>Last spot</th><td><span v-html="formatTimeDay(lastSpot.timeStamp)" />: <router-link :to="makeActivatorLink(lastSpot.activatorCallsign)">{{ lastSpot.activatorCallsign }}</router-link>, {{ lastSpot.frequency }} <ModeLabel :mode="lastSpot.mode" /></td></tr>
<tr v-if="nextAlert" class="nextAlert"><th>Next alert</th><td><span v-html="formatDateTimeRelative(nextAlert.dateActivated)" />: <router-link :to="makeActivatorLink(nextAlert.activatorCallsign)">{{ nextAlert.activatorCallsign }}</router-link><div v-if="nextAlert.frequency" class="alertFrequencies">{{ nextAlert.frequency }}</div><div v-if="nextAlert.comments" class="alertComments">{{ nextAlert.comments }}</div></td></tr>
</table>
<div class="buttons">
<b-button v-if="!minimizePopup" size="is-small" icon-left="window-close" @click="$emit('close')">Close</b-button>
@ -36,7 +37,8 @@ export default {
name: 'SummitPopup',
props: {
summit: Object,
lastSpot: Object
lastSpot: Object,
nextAlert: Object
},
mixins: [utils, coverphoto],
components: {
@ -97,6 +99,25 @@ export default {
.summitPopup.minimize .summitCode {
display: none;
}
.summitPopup .nextAlert >>> .date-small {
font-size: 100%;
min-width: 0;
}
.summitPopup .alertFrequencies {
font-size: 0.9em;
margin-top: 0.1em;
max-width: 25em;
overflow: hidden;
text-overflow: ellipsis;
}
.summitPopup .alertComments {
font-size: 0.9em;
margin-top: 0.1em;
max-width: 25em;
color: #777;
overflow: hidden;
text-overflow: ellipsis;
}
.photo {
width: 300px;
padding-bottom: 0.5em;

Wyświetl plik

@ -32,7 +32,7 @@
{{ props.row.publicTransport.description }}
</div>
</div>
<article class="routeDescr" v-html="linkifyCoordinates(props.row.description)" />
<article class="routeDescr" v-html="linkifyCoordinates(props.row.htmlDescription ? props.row.htmlDescription : props.row.description)" />
<div class="author">by {{ props.row.author }}</div>
<div class="track-download" v-if="props.row.track">
<TrackLink :route="props.row" :summit="summit"><font-awesome-icon :icon="['far', 'file-download']" class="fa-icon" /> Download track (.gpx)</TrackLink>

Wyświetl plik

@ -38,7 +38,7 @@ export default {
mounted () {
if (!localStorage.getItem('swisstopoInfoShown')) {
// Check if we are in Switzerland
axios.get('https://api.sotl.as/my_country')
axios.get(process.env.VUE_APP_API_URL + '/my_country')
.then(response => {
if (response.data.country === 'CH') {
this.active = true

Wyświetl plik

@ -4,10 +4,11 @@
<script>
import tracks from '../mixins/tracks.js'
import utils from '../mixins/utils.js'
export default {
name: 'TrackLink',
mixins: [tracks],
mixins: [tracks, utils],
props: {
route: Object,
summit: Object
@ -42,8 +43,9 @@ export default {
</link>
</metadata>
<trk>
<name>${this.route.title}</name>
<name>${this.escapeHtml(this.route.title)}</name>
<src>${this.route.author}</src>
<desc>${this.escapeHtml(this.route.description)}</desc>
<trkseg>
${trkpts.join('\n')}
</trkseg>

Wyświetl plik

@ -15,7 +15,8 @@ import { faCheck, faCheckCircle, faInfoCircle, faExclamationTriangle, faExclamat
faSnowflake, faWindowMinimize, faWindowMaximize, faWindowClose, faExpandArrows, faLocation, faCalendarCheck, faComment, faSpinner,
faBookUser, faBookmark, faTag } from '@fortawesome/pro-regular-svg-icons'
import { faMap, faCheckCircle as fasCheckCircle, faChevronCircleDown as fasChevronCircleDown, faChevronCircleUp as fasChevronCircleUp,
faParking, faSquare, faBus, faHiking, faCircle, faCamera, faCameraHome, faVolume, faVolumeMute, faCog, faCaretDown as fasCaretDown, faLocationArrow as fasLocationArrow } from '@fortawesome/pro-solid-svg-icons'
faParking, faSquare, faBus, faHiking, faCircle, faCamera, faCameraHome, faVolume, faVolumeMute, faCog, faCaretDown as fasCaretDown,
faLocationArrow as fasLocationArrow, faInfoCircle as fasInfoCircle } from '@fortawesome/pro-solid-svg-icons'
import { faWikipediaW, faGoogle, faGithub } from '@fortawesome/free-brands-svg-icons'
import { FontAwesomeIcon, FontAwesomeLayers } from '@fortawesome/vue-fontawesome'
import '@/assets/global.css'
@ -29,7 +30,8 @@ library.add(faCheck, faCheckCircle, faInfoCircle, faExclamationTriangle, faExcla
faExchange, faGlobe, faCalendarDay, faTrashAlt, faEdit, faClone, farCheckCircle, faArrowsH, faArrowsAlt,
faSnowflake, faWindowMinimize, faWindowMaximize, faWindowClose, faExpandArrows, faLocation, faCalendarCheck, faComment, faSpinner,
faBookUser, faBookmark, faTag)
library.add(faMap, fasCheckCircle, fasChevronCircleDown, fasChevronCircleUp, faParking, faSquare, faBus, faHiking, faCircle, faCamera, faCameraHome, faVolume, faVolumeMute, faCog, fasCaretDown, fasLocationArrow)
library.add(faMap, fasCheckCircle, fasChevronCircleDown, fasChevronCircleUp, faParking, faSquare, faBus, faHiking, faCircle, faCamera,
faCameraHome, faVolume, faVolumeMute, faCog, fasCaretDown, fasLocationArrow, fasInfoCircle)
library.add(faWikipediaW, faGoogle, faGithub)
Vue.component('font-awesome-icon', FontAwesomeIcon)
Vue.component('font-awesome-layers', FontAwesomeLayers)
@ -106,6 +108,7 @@ function startVue () {
mq: {
mobile: '(max-width: 768px)',
desktop: '(min-width: 1024px)',
widescreen: '(min-width: 1216px)',
fullhd: '(min-width: 1408px)'
}
}).$mount('#app')

Wyświetl plik

@ -5,7 +5,7 @@ export default {
mixins: [ssoauth],
methods: {
loadActivations (callsign) {
return axios.get('https://api.sotl.as/activations/' + callsign)
return axios.get(process.env.VUE_APP_API_URL + '/activations/' + callsign)
.then(response => {
return response.data
})
@ -34,20 +34,20 @@ export default {
uploadPhoto (summitCode, file, progress, cancelToken) {
let formData = new FormData()
formData.append('photo', file)
return this.axiosAuth.post('https://api.sotl.as/photos/summits/' + summitCode + '/upload', formData, {
return this.axiosAuth.post(process.env.VUE_APP_API_URL + '/photos/summits/' + summitCode + '/upload', formData, {
headers: { 'Content-Type': 'multipart/form-data' },
onUploadProgress: progress,
cancelToken
})
},
deletePhoto (summitCode, filename) {
return this.axiosAuth.delete('https://api.sotl.as/photos/summits/' + summitCode + '/' + filename)
return this.axiosAuth.delete(process.env.VUE_APP_API_URL + '/photos/summits/' + summitCode + '/' + filename)
},
editPhoto (summitCode, filename, data) {
return this.axiosAuth.post('https://api.sotl.as/photos/summits/' + summitCode + '/' + filename, data)
return this.axiosAuth.post(process.env.VUE_APP_API_URL + '/photos/summits/' + summitCode + '/' + filename, data)
},
reorderPhotos (summitCode, filenames) {
return this.axiosAuth.post('https://api.sotl.as/photos/summits/' + summitCode + '/reorder', { filenames })
return this.axiosAuth.post(process.env.VUE_APP_API_URL + '/photos/summits/' + summitCode + '/reorder', { filenames })
}
}
}

Wyświetl plik

@ -12,7 +12,7 @@ export default {
if (mapServerOverride && mapServerOverride !== 'test') {
this.mapServer = mapServerOverride
} else {
axios.get('https://api.sotl.as/map_server')
axios.get(process.env.VUE_APP_API_URL + '/map_server')
.then(response => {
if (response.data.mapServer) {
this.mapServer = response.data.mapServer
@ -99,7 +99,14 @@ export default {
'eu': 'Europe (Switzerland)',
'us': 'US (California)'
},
mapTypes: { 'openmaptiles': 'OpenMapTiles', 'swisstopo': 'swisstopo (Vector)', 'swisstopo_raster': 'swisstopo (Raster)' },
mapTypes: {
'openmaptiles': 'OpenMapTiles',
'swisstopo': 'swisstopo (Vector)',
'swisstopo_raster': 'swisstopo (Raster)',
'swisstopo_aerial': 'swisstopo (Aerial)',
'toposvalbard': 'TopoSvalbard',
'norkart': 'Norkart'
},
initialMapOptions: null
}
}

Wyświetl plik

@ -1,7 +1,11 @@
export default {
methods: {
photoSrc (photo, size) {
return 'https://images.sotl.as/photos/' + size + '/' + photo.filename.substring(0, 2) + '/' + photo.filename
if (size === 'original') {
return process.env.VUE_APP_PHOTOS_ORIGINAL_URL + '/' + photo.filename
} else {
return process.env.VUE_APP_PHOTOS_URL + '/' + size + '/' + photo.filename
}
}
}
}

Wyświetl plik

@ -48,7 +48,8 @@ export default {
routes.push({
id: track.hdr_id,
title: track.track_title,
description: '<p>' + this.escapeHtml(track.track_notes) + '</p><p><small>Track imported from <a href="https://www.sotamaps.org" target="_blank">SMP</a></small></p>',
htmlDescription: '<p>' + this.escapeHtml(track.track_notes) + '</p><p><small>Track imported from <a href="https://www.sotamaps.org" target="_blank">SMP</a></small></p>',
description: track.track_notes,
author: track.callsign,
distance,
ascent,

Wyświetl plik

@ -5,7 +5,7 @@ export default {
mixins: [ssoauth],
methods: {
loadActivations (callsign) {
return axios.get('https://api.sotl.as/activations/' + callsign)
return axios.get(process.env.VUE_APP_API_URL + '/activations/' + callsign)
.then(response => {
return response.data
})

Wyświetl plik

@ -19,7 +19,10 @@ let bands = [
{ from: 900, to: 928, band: '33cm' },
{ from: 1200, to: 1400, band: '23cm' },
{ from: 2300, to: 2450, band: '13cm' },
{ from: 3300, to: 3500, band: '9cm' }
{ from: 3300, to: 3500, band: '9cm' },
{ from: 5600, to: 5925, band: '5cm' },
{ from: 10000, to: 10500, band: '3cm' },
{ from: 24000, to: 24250, band: '1.2cm' }
]
let continents = {
@ -212,6 +215,21 @@ export default {
return undefined
}
},
bandForDbFrequency (dbFrequency) {
return this.bandForFrequency(this.dbFrequencyToMHz(dbFrequency))
},
dbFrequencyToMHz (dbFrequency) {
let matches = /^([0-9.]+)([GM]Hz)$/.exec(dbFrequency)
if (matches) {
let multiplier = 1
if (matches[2] === 'GHz') {
multiplier = 1000
}
return parseFloat(matches[1]) * multiplier
} else {
return dbFrequency
}
},
escapeHtml (unsafe) {
if (unsafe === undefined || unsafe === null) {
return ''

Wyświetl plik

@ -18,6 +18,7 @@ import SotaSpots from './views/SotaSpots.vue'
import RBNSpots from './views/RBNSpots.vue'
import Alerts from './views/Alerts.vue'
import NewPhotos from './views/NewPhotos.vue'
import SolarHistory from './views/SolarHistory.vue'
Vue.use(Router)
@ -173,6 +174,10 @@ let router = new Router({
path: '/new_photos',
component: NewPhotos
},
{
path: '/solar_history',
component: SolarHistory
},
{
path: '*',
component: NotFound,

Wyświetl plik

@ -29,6 +29,7 @@ let mapOptions = {
regions: false,
contours: true,
hillshading: true,
az: true,
difficulty: true,
spots: false,
inactive: false,
@ -199,7 +200,7 @@ function loadAlerts (noCache) {
if (noCache) {
params.noCache = 1
}
axios.get('https://api.sotl.as/alerts', { params })
axios.get(process.env.VUE_APP_API_URL + '/alerts', { params })
.then(response => {
store.commit('setAlerts', response.data)
})
@ -208,7 +209,7 @@ function loadAlerts (noCache) {
loadAlerts(false)
setInterval(loadAlerts, ALERT_UPDATE_INTERVAL)
Vue.use(VueNativeSock, 'wss://api.sotl.as/ws', {
Vue.use(VueNativeSock, process.env.VUE_APP_WSS_URL + '/ws', {
format: 'json',
store,
reconnection: true,

Wyświetl plik

@ -7,8 +7,13 @@
<div class="container content">
<p>SOTA Atlas (SOTLAS) is created and maintained by Manuel Kasper, HB9DQM (<a href="mailto:mk@neon1.net">mk@neon1.net</a>).</p>
<p>Code contributed by: <a href="https://github.com/m1hax">@m1hax</a>, <a href="https://github.com/summitsontheair">@summitsontheair</a>,
<a href="https://github.com/vk3arr">@vk3arr</a>,
Simon G4TJC
</p>
<p>
Summit database © 2002-2020 Summits on the Air.<br />
Summit database © 2002-2021 Summits on the Air.<br />
Summits on the Air, SOTA and the SOTA Logo are trademarks of the Programme.
</p>
@ -27,7 +32,7 @@
</p>
<p>
Icons made by <a href="https://www.flaticon.com/authors/nikita-golubev" title="Nikita Golubev">Nikita Golubev</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a> are licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a>
Icons made by <a href="https://www.flaticon.com/authors/nikita-golubev" title="Nikita Golubev">Nikita Golubev</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a> are licensed by <a href="https://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a>
</p>
<p>Technologies used:

Wyświetl plik

@ -263,6 +263,45 @@ export default {
associations.add(activation.summit.code.substring(0, activation.summit.code.indexOf('/')))
})
return associations.size
},
activationsMapBounds () {
let minLat, minLon, maxLat, maxLon
this.activations.forEach(activation => {
if (!minLat || activation.summit.coordinates.latitude < minLat) {
minLat = activation.summit.coordinates.latitude
}
if (!maxLat || activation.summit.coordinates.latitude > maxLat) {
maxLat = activation.summit.coordinates.latitude
}
if (!minLon || activation.summit.coordinates.longitude < minLon) {
minLon = activation.summit.coordinates.longitude
}
if (!maxLon || activation.summit.coordinates.longitude > maxLon) {
maxLon = activation.summit.coordinates.longitude
}
})
// Some padding
let latDiff = maxLat - minLat
let lonDiff = maxLon - minLon
minLat -= (latDiff * 0.05)
maxLat += (latDiff * 0.05)
minLon -= (lonDiff * 0.05)
maxLon += (lonDiff * 0.05)
minLat = Math.max(Math.min(minLat, 90), -90)
maxLat = Math.max(Math.min(maxLat, 90), -90)
minLon = Math.max(Math.min(minLon, 180), -180)
maxLon = Math.max(Math.min(maxLon, 180), -180)
return [[minLon, minLat], [maxLon, maxLat]]
},
activationsMapFilter () {
let summits = new Set()
this.activations.forEach(activation => {
summits.add(activation.summit.code)
})
return ['in', 'code', ...summits]
}
},
watch: {
@ -301,7 +340,7 @@ export default {
this.databaseError = false
let loads = []
axios.get('https://api.sotl.as/activators/' + this.callsign)
axios.get(process.env.VUE_APP_API_URL + '/activators/' + this.callsign)
.then(response => {
if (response) {
this.activator = response.data

Wyświetl plik

@ -63,7 +63,7 @@ export default {
methods: {
loadData () {
this.loading = true
axios.get('https://api.sotl.as/activators/search', { params: { q: this.filter, skip: (this.curPage - 1) * this.perPage, limit: this.perPage, sort: this.sortField, sortDirection: this.sortDirection } })
axios.get(process.env.VUE_APP_API_URL + '/activators/search', { params: { q: this.filter, skip: (this.curPage - 1) * this.perPage, limit: this.perPage, sort: this.sortField, sortDirection: this.sortDirection } })
.then(response => {
this.activators = response.data.activators
this.total = response.data.total

Wyświetl plik

@ -79,7 +79,7 @@ export default {
},
loadAssociation () {
this.loadingComponent = this.$buefy.loading.open({ canCancel: true })
axios.get('https://api.sotl.as/associations/' + this.associationCode)
axios.get(process.env.VUE_APP_API_URL + '/associations/' + this.associationCode)
.then(response => {
this.association = response.data
document.title = this.association.name + ' (' + this.associationCode + ') - SOTLAS'
@ -104,7 +104,7 @@ export default {
})
},
exportUrlPrefix () {
return `https://api.sotl.as/geoexport/associations/${this.associationCode}`
return process.env.VUE_APP_API_URL + '/geoexport/associations/' + this.associationCode
},
myActivationsPerRegion () {
if (!this.$store.state.myActivatedSummits) {

Wyświetl plik

@ -49,7 +49,7 @@ export default {
mounted () {
document.title = 'Associations - SOTLAS'
this.loadingComponent = this.$buefy.loading.open({ canCancel: true })
axios.get('https://api.sotl.as/associations/all')
axios.get(process.env.VUE_APP_API_URL + '/associations/all')
.then(response => {
this.associations = response.data
this.loadingComponent.close()

Wyświetl plik

@ -1,6 +1,6 @@
<template>
<div class="map-layout" ref="mapLayout">
<MglMap v-if="showMap && mapStyle" :mapStyle="mapStyle" :bounds.sync="bounds" :fitBoundsOptions="fitBoundsOptions" :center="center" :zoom="zoom" :dragRotate="false" :preserveDrawingBuffer="!$mq.mobile" :attributionControl="false" class="map" @load="onMapLoaded" @click="onMapClicked" @contextmenu="onMapRightClicked">
<MglMap v-if="showMap && mapStyle" :mapStyle="mapStyle" :bounds.sync="bounds" :fitBoundsOptions="fitBoundsOptions" :center="center" :zoom="zoom" :dragRotate="false" :attributionControl="false" class="map" @load="onMapLoaded" @click="onMapClicked" @contextmenu="onMapRightClicked">
<MglGeolocateControl :positionOptions="{ enableHighAccuracy: true }" :fitBoundsOptions="{ maxZoom: 12.5 }" :trackUserLocation="true" position="top-right" />
<MglNavigationControl position="top-right" :showCompass="false" />
<MglScaleControl position="bottom-left" />
@ -20,7 +20,7 @@
</div>
</MglPopup>
<SummitPopup v-if="summit" :summit="summit" :lastSpot="lastSummitSpot" @close="onPopupClosed" />
<SummitPopup v-if="summit" :summit="summit" :lastSpot="lastSummitSpot" :nextAlert="nextSummitAlert" @close="onPopupClosed" />
<MapRoute v-for="route in persistentRoutes" :key="route.id" :route="route" />
@ -101,7 +101,7 @@ export default {
} catch (e) {}
this.showMap = true
} else {
axios.get('https://api.sotl.as/my_coordinates')
axios.get(process.env.VUE_APP_API_URL + '/my_coordinates')
.then(response => {
if (response.data.latitude && response.data.longitude) {
this.center = [response.data.longitude, response.data.latitude]
@ -194,6 +194,28 @@ export default {
return null
}
},
nextSummitAlert () {
if (!this.summit) {
return null
}
let alerts = this.$store.state.alerts.filter(alert => {
return (alert.summit.code === this.summit.code)
}).sort((a, b) => {
if (a.dateActivated > b.dateActivated) {
return 1
} else if (a.dateActivated < b.dateActivated) {
return -1
} else {
return 0
}
})
if (alerts.length > 0) {
return alerts[0]
} else {
return null
}
},
mapOptions () {
return this.$store.state.mapOptions
}
@ -324,7 +346,7 @@ export default {
})
},
fetchSummit (summitCode) {
return axios.get('https://api.sotl.as/summits/' + summitCode)
return axios.get(process.env.VUE_APP_API_URL + '/summits/' + summitCode)
.then(response => {
let summit = response.data
summit.photo = null
@ -332,7 +354,7 @@ export default {
})
},
fetchAssociation (associationCode) {
return axios.get('https://api.sotl.as/associations/' + associationCode)
return axios.get(process.env.VUE_APP_API_URL + '/associations/' + associationCode)
.then(response => {
return response.data
})

Wyświetl plik

@ -64,7 +64,7 @@ export default {
if (this.selectedAssociations.length > 0) {
associations = this.selectedAssociations.join('|')
}
axios.get('https://api.sotl.as/summits/recent_photos/' + associations + '/' + this.days, { params: recentPhotosParams })
axios.get(process.env.VUE_APP_API_URL + '/summits/recent_photos/' + associations + '/' + this.days, { params: recentPhotosParams })
.then(response => {
this.loadingComponent.close()
this.summits = response.data.slice(0, -1)
@ -72,7 +72,7 @@ export default {
})
},
loadAssociations () {
axios.get('https://api.sotl.as/associations/all')
axios.get(process.env.VUE_APP_API_URL + '/associations/all')
.then(response => {
this.associations = response.data
})

Wyświetl plik

@ -74,7 +74,7 @@ export default {
})
},
exportUrlPrefix () {
return `https://api.sotl.as/geoexport/regions/${this.regionCode}`
return process.env.VUE_APP_API_URL + '/geoexport/regions/' + this.regionCode
},
exportUrlParams () {
return (this.showInactive ? { inactive: 1 } : {})
@ -101,6 +101,8 @@ export default {
},
watch: {
regionCode () {
this.association = {}
this.summits = []
this.loadRegion()
},
showActivatedThisYear () {
@ -123,7 +125,7 @@ export default {
loadRegion () {
let loads = []
this.loadingComponent = this.$buefy.loading.open({ canCancel: true })
loads.push(axios.get('https://api.sotl.as/associations/' + this.associationCode)
loads.push(axios.get(process.env.VUE_APP_API_URL + '/associations/' + this.associationCode)
.then(response => {
this.association = response.data
document.title = this.region.name + ' (' + this.associationCode + '/' + this.region.code + ') - SOTLAS'
@ -134,7 +136,7 @@ export default {
}
}))
loads.push(axios.get('https://api.sotl.as/regions/' + this.regionCode)
loads.push(axios.get(process.env.VUE_APP_API_URL + '/regions/' + this.regionCode)
.then(response => {
let now = moment()
if (response.data.length === 0) {

Wyświetl plik

@ -131,11 +131,20 @@ export default {
this.userTags = []
}
loads.push(axios.get('https://api.sotl.as/activators/search', { params: { q, limit: this.limit } })
loads.push(axios.get(process.env.VUE_APP_API_URL + '/activators/search', { params: { q, limit: this.limit } })
.then(response => {
this.activators = response.data.activators
}))
loads.push(axios.get(process.env.VUE_APP_API_URL + '/summits/search', { params: { q, limit: this.limit } })
.then(response => {
let now = moment()
response.data.forEach(summit => {
summit.isValid = (moment(summit.validFrom).isBefore(now) && moment(summit.validTo).isAfter(now))
})
this.summits = response.data
}))
Promise.all(loads)
.then(() => {
this.loadingComponent.close()

Wyświetl plik

@ -0,0 +1,87 @@
<template>
<PageLayout>
<template v-slot:title>Solar Data</template>
<template>
<section class="section">
<div class="container content">
<LineChart class="solar-chart" v-if="solarHistory !== null" :data="solarHistory" labelField="dateFormatted" valueField="sfi" valueFieldB="r" name="SFI" nameB="SN" :xIsSeries="true" :regionFill="false" spline="1" height="400" />
<BarChart class="solar-chart" v-if="solarHistory !== null" :data="solarHistory" labelField="dateFormatted" valueField="k" name="K" :xIsSeries="true" spline="1" height="200" :spaceRatio="0.5" :colors="['blue']" />
</div>
</section>
</template>
</PageLayout>
</template>
<script>
import axios from 'axios'
import moment from 'moment'
import PageLayout from '../components/PageLayout.vue'
import LineChart from '../components/LineChart.vue'
import BarChart from '../components/BarChart.vue'
export default {
name: 'SolarHistory',
components: { PageLayout, LineChart, BarChart },
methods: {
loadHistory () {
// Fetch data from last 30 days
axios.get(process.env.VUE_APP_API_URL + '/solardata/history/720')
.then(response => {
this.loadingComponent.close()
// Average data per day
let dataPerDay = {}
response.data.forEach(ent => {
if (!dataPerDay[ent.date]) {
dataPerDay[ent.date] = {
sfi: ent.sfi,
r: ent.r,
k: ent.k,
count: 1
}
} else {
dataPerDay[ent.date].sfi += ent.sfi
dataPerDay[ent.date].r += ent.r
dataPerDay[ent.date].k += ent.k
dataPerDay[ent.date].count++
}
})
let chartData = []
Object.entries(dataPerDay).forEach(([date, ent]) => {
chartData.push({
date,
dateFormatted: moment.utc(date).format('D MMM'),
sfi: Math.round(ent.sfi / ent.count),
r: Math.round(ent.r / ent.count),
k: Math.round(ent.k / ent.count)
})
})
this.solarHistory = chartData.sort((a, b) => {
if (a.date < b.date) {
return -1
} else if (a.date > b.date) {
return 1
} else {
return 0
}
})
})
this.loadingComponent = this.$buefy.loading.open({ canCancel: true })
}
},
mounted () {
document.title = 'Solar Data History - SOTLAS'
this.loadHistory()
},
data () {
return {
solarHistory: null
}
}
}
</script>

Wyświetl plik

@ -58,10 +58,12 @@
</div>
</div>
<div v-if="!enlargeMap" class="column">
<div>Coordinates: <Coordinates v-if="summit.coordinates" :latitude="summit.coordinates.latitude" :longitude="summit.coordinates.longitude" :reference="summit.code" /></div>
<div>Coordinates: <Coordinates v-if="summit.coordinates" :latitude="summit.coordinates.latitude" :longitude="summit.coordinates.longitude" :altitude="summit.altitude" :reference="summit.code" /></div>
<div>Locator: <span class="locator">{{ locator }}</span></div>
<div v-if="authenticated && summit.coordinates">Distance/Bearing: <Bearing :latitude="summit.coordinates.latitude" :longitude="summit.coordinates.longitude" /></div>
<div v-if="firstActivations">First activation:
<div v-if="$keycloak && $keycloak.authenticated && summit.coordinates">Distance/Bearing: <Bearing :latitude="summit.coordinates.latitude" :longitude="summit.coordinates.longitude" /></div>
<div v-if="firstActivations">
<span v-if="firstActivations.activators.length == 1">First activation: </span>
<span v-else>First day's activations: </span>
<span v-for="(activator, index) in firstActivations.activators" :key="activator.userId"><router-link :to="makeActivatorLinkUserId(activator.userId)"><strong>{{ activator.callsign }}</strong></router-link>{{ index !== firstActivations.activators.length - 1 ? ' & ' : '' }}</span>
<span class="has-text-grey"> on {{ firstActivations.date | formatActivationDate }}</span></div>
@ -167,6 +169,7 @@ import AlertsList from '../components/AlertsList.vue'
import EditAlert from '../components/EditAlert.vue'
import EditSpot from '../components/EditSpot.vue'
import HikrIcon from '../assets/hikr.png'
import SACIcon from '../assets/sac.png'
import SotatrailsIcon from '../assets/sotatrails.png'
import EventBus from '../event-bus'
import api from '../mixins/api.js'
@ -236,13 +239,21 @@ export default {
url: this.wikipediaPhoto.link
})
}
if (this.summit.code && this.summit.code.startsWith('HB')) {
resources.push({
iconImg: SACIcon,
prefix: 'SAC-Tourenportal',
title: this.summit.name + ' (' + this.summit.altitude + ' m)',
url: 'https://www.sac-cas.ch/de/suche/?tx_solr[filter][0]=type%3Atour_destination&tx_solr[q]=' + encodeURIComponent(this.summit.name)
})
}
if (this.summit.code && this.summit.code.match(/^(HB|OE|DL|DM)/)) {
let hikrSummitName = this.summit.name.replace(/\/.*$/, '')
resources.push({
iconImg: HikrIcon,
prefix: 'Hikr.org',
title: hikrSummitName + ' (' + this.summit.altitude + ' m)',
url: 'http://www.hikr.org/dir/?adv=1&piz_name=' + encodeURIComponent(hikrSummitName) + '&piz_height_min=' + (this.summit.altitude - 50) + '&piz_height_max=' + (this.summit.altitude + 50) + '&piz_type=peak&piz_order=piz_name&action=search'
url: 'https://www.hikr.org/dir/?adv=1&piz_name=' + encodeURIComponent(hikrSummitName) + '&piz_height_min=' + (this.summit.altitude - 50) + '&piz_height_max=' + (this.summit.altitude + 50) + '&piz_type=peak&piz_order=piz_name&action=search'
})
}
resources.push({
@ -359,10 +370,10 @@ export default {
}
// Make a dummy POST to the summit URL to invalidate the browser's cache for future page loads
axios.post('https://api.sotl.as/summits/' + this.summitCode)
axios.post(process.env.VUE_APP_API_URL + '/summits/' + this.summitCode)
}
loads.push(axios.get('https://api.sotl.as/summits/' + this.summitCode, options)
loads.push(axios.get(process.env.VUE_APP_API_URL + '/summits/' + this.summitCode, options)
.then(response => {
this.summit = response.data
document.title = this.summit.name + ' (' + this.summit.code + ') - SOTLAS'
@ -373,7 +384,7 @@ export default {
}
}))
loads.push(axios.get('https://api.sotl.as/associations/' + this.summitCode.substr(0, this.summitCode.indexOf('/')))
loads.push(axios.get(process.env.VUE_APP_API_URL + '/associations/' + this.summitCode.substr(0, this.summitCode.indexOf('/')))
.then(response => {
this.association = response.data
}))
@ -427,9 +438,9 @@ export default {
this.loadingComponent = this.$buefy.loading.open({ canCancel: false })
// Make a dummy POST to the summit URL to invalidate the browser's cache for future page loads
axios.post('https://api.sotl.as/summits/' + this.summitCode)
axios.post(process.env.VUE_APP_API_URL + '/summits/' + this.summitCode)
axios.get('https://api.sotl.as/summits/' + this.summitCode, { params: { t: new Date().getTime() } })
axios.get(process.env.VUE_APP_API_URL + '/summits/' + this.summitCode, { params: { t: new Date().getTime() } })
.then(response => {
this.summit = response.data
})
@ -459,9 +470,21 @@ export default {
},
routeDetailsOpen (route) {
this.$set(route, 'highlight', true)
this.routes.forEach(curRoute => {
if (curRoute.highlight !== true) {
this.$set(curRoute, 'highlight', false)
}
})
},
routeDetailsClose (route) {
this.$set(route, 'highlight', false)
// If all route highlights are false, set them all to null
if (this.routes.every(curRoute => curRoute.highlight === false)) {
this.routes.forEach(curRoute => {
this.$set(curRoute, 'highlight', null)
})
}
},
mapReposition (coordinates) {
if (coordinates) {