qwc2 2025.10.9 → 2025.10.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/actions/display.js +30 -1
  2. package/actions/editing.js +22 -1
  3. package/actions/layerinfo.js +13 -1
  4. package/actions/layers.js +213 -3
  5. package/actions/localConfig.js +58 -1
  6. package/actions/locale.js +21 -1
  7. package/actions/locate.js +26 -1
  8. package/actions/logging.js +10 -1
  9. package/actions/map.js +105 -2
  10. package/actions/measurement.js +12 -1
  11. package/actions/processNotifications.js +37 -1
  12. package/actions/redlining.js +18 -1
  13. package/actions/redliningPick.js +12 -1
  14. package/actions/search.js +12 -1
  15. package/actions/serviceinfo.js +12 -1
  16. package/actions/task.js +55 -3
  17. package/actions/theme.js +339 -19
  18. package/actions/windows.js +164 -5
  19. package/components/AppMenu.js +435 -3
  20. package/components/AttributeForm.js +928 -32
  21. package/components/AttributeTableWidget.js +1105 -13
  22. package/components/AutoEditForm.js +189 -3
  23. package/components/CoordinateDisplayer.js +78 -2
  24. package/components/EditComboField.js +190 -6
  25. package/components/EditUploadField.js +315 -3
  26. package/components/ExportSelection.js +203 -2
  27. package/components/FullscreenSwitcher.js +90 -3
  28. package/components/Icon.js +81 -2
  29. package/components/IdentifyViewer.js +1161 -6
  30. package/components/ImportLayer.js +718 -20
  31. package/components/LayerInfoWindow.js +145 -2
  32. package/components/LinkFeatureForm.js +246 -5
  33. package/components/MapButton.js +88 -2
  34. package/components/MapSelection.js +287 -8
  35. package/components/MessageBar.js +68 -2
  36. package/components/NumericInputWindow.js +359 -2
  37. package/components/PickFeature.js +266 -2
  38. package/components/PluginsContainer.js +227 -8
  39. package/components/PrintSelection.js +620 -49
  40. package/components/ProcessNotifications.js +104 -2
  41. package/components/QtDesignerForm.js +1137 -18
  42. package/components/ResizeableWindow.js +591 -8
  43. package/components/SearchBox.js +1307 -20
  44. package/components/ServiceInfoWindow.js +107 -2
  45. package/components/SideBar.js +204 -4
  46. package/components/StandardApp.js +381 -20
  47. package/components/Swipeable.js +15 -1
  48. package/components/TaskBar.js +85 -2
  49. package/components/ThemeLayersListWindow.js +216 -4
  50. package/components/ThemeList.js +381 -7
  51. package/components/Toolbar.js +106 -2
  52. package/components/WindowManager.js +178 -2
  53. package/components/map/OlLayer.js +257 -6
  54. package/components/map/OlMap.js +405 -5
  55. package/components/map/layers/BingLayer.js +31 -2
  56. package/components/map/layers/GoogleLayer.js +222 -19
  57. package/components/map/layers/GraticuleLayer.js +21 -1
  58. package/components/map/layers/ImageLayer.js +15 -1
  59. package/components/map/layers/MVTLayer.js +52 -2
  60. package/components/map/layers/OSMLayer.js +24 -2
  61. package/components/map/layers/OverlayLayer.js +55 -3
  62. package/components/map/layers/VectorLayer.js +173 -8
  63. package/components/map/layers/WFSLayer.js +220 -6
  64. package/components/map/layers/WMSLayer.js +180 -6
  65. package/components/map/layers/WMTSLayer.js +67 -3
  66. package/components/map/layers/XYZLayer.js +24 -2
  67. package/components/map/layers/index.js +28 -1
  68. package/components/map3d/EditDataset3D.js +190 -3
  69. package/components/map3d/HeightProfile3D.js +402 -3
  70. package/components/map3d/ImportObjects3D.js +162 -2
  71. package/components/map3d/Map3D.js +1304 -38
  72. package/components/map3d/MapControls3D.js +392 -7
  73. package/components/map3d/SearchField3D.js +183 -11
  74. package/components/map3d/View3DSwitcher.js +98 -2
  75. package/components/map3d/drawtool/CreateTool3D.js +174 -4
  76. package/components/map3d/drawtool/EditTool3D.js +590 -6
  77. package/components/map3d/drawtool/NumericInput3D.js +336 -4
  78. package/components/map3d/layers/GeoTIFFLayer3D.js +15 -1
  79. package/components/map3d/layers/VectorLayer3D.js +53 -2
  80. package/components/map3d/layers/WFSLayer3D.js +109 -3
  81. package/components/map3d/layers/WMSLayer3D.js +70 -2
  82. package/components/map3d/layers/WMTSLayer3D.js +27 -3
  83. package/components/map3d/layers/index.js +14 -1
  84. package/components/map3d/utils/FirstPersonControls3D.js +423 -16
  85. package/components/map3d/utils/MiscUtils3D.js +221 -13
  86. package/components/map3d/utils/OrbitControls3D.js +176 -5
  87. package/components/map3d/utils/Tiles3DStyle.js +238 -9
  88. package/components/share/ShareLink.js +54 -2
  89. package/components/share/ShareQRCode.js +62 -2
  90. package/components/share/ShareSocials.js +125 -3
  91. package/components/timeline/FixedTimeline.js +236 -5
  92. package/components/timeline/InfiniteTimeline.js +347 -8
  93. package/components/timeline/TimelineFeaturesSlider.js +439 -5
  94. package/components/widgets/AccordeonWidget.js +96 -2
  95. package/components/widgets/ButtonBar.js +124 -2
  96. package/components/widgets/ColorButton.js +201 -3
  97. package/components/widgets/ComboBox.js +166 -2
  98. package/components/widgets/CopyButton.js +110 -2
  99. package/components/widgets/DateTimeInput.js +100 -3
  100. package/components/widgets/EditableSelect.js +230 -3
  101. package/components/widgets/FileSelector.js +128 -4
  102. package/components/widgets/Input.js +124 -2
  103. package/components/widgets/InputContainer.js +96 -2
  104. package/components/widgets/LayerCatalogWidget.js +219 -3
  105. package/components/widgets/MenuButton.js +157 -1
  106. package/components/widgets/ModalDialog.js +64 -2
  107. package/components/widgets/NavBar.js +119 -2
  108. package/components/widgets/NumberInput.js +226 -4
  109. package/components/widgets/PopupMenu.js +72 -1
  110. package/components/widgets/Primitives.js +6 -1
  111. package/components/widgets/ReCaptchaWidget.js +55 -1
  112. package/components/widgets/SearchWidget.js +255 -2
  113. package/components/widgets/Spinner.js +44 -2
  114. package/components/widgets/SuggestionInput.js +77 -2
  115. package/components/widgets/TextInput.js +308 -2
  116. package/components/widgets/ToggleSwitch.js +85 -2
  117. package/components/widgets/VectorLayerPicker.js +85 -3
  118. package/libs/openlayers.js +225 -5
  119. package/package.json +1 -1
  120. package/plugins/API.js +358 -15
  121. package/plugins/AttributeTable.js +109 -3
  122. package/plugins/Authentication.js +130 -5
  123. package/plugins/BackgroundSwitcher.js +218 -4
  124. package/plugins/Bookmark.js +289 -3
  125. package/plugins/BottomBar.js +298 -4
  126. package/plugins/CookiePopup.js +67 -3
  127. package/plugins/Cyclomedia.js +442 -5
  128. package/plugins/Editing.js +497 -9
  129. package/plugins/FeatureForm.js +366 -4
  130. package/plugins/FeatureSearch.js +458 -3
  131. package/plugins/GeometryDigitizer.js +664 -7
  132. package/plugins/HeightProfile.js +763 -15
  133. package/plugins/Help.js +102 -3
  134. package/plugins/HomeButton.js +80 -3
  135. package/plugins/Identify.js +543 -5
  136. package/plugins/LayerCatalog.js +215 -4
  137. package/plugins/LayerTree.js +1194 -6
  138. package/plugins/LocateButton.js +94 -3
  139. package/plugins/Map.js +320 -16
  140. package/plugins/MapCompare.js +94 -3
  141. package/plugins/MapCopyright.js +127 -5
  142. package/plugins/MapExport.js +613 -20
  143. package/plugins/MapFilter.js +868 -12
  144. package/plugins/MapInfoTooltip.js +277 -3
  145. package/plugins/MapLegend.js +253 -4
  146. package/plugins/MapTip.js +290 -4
  147. package/plugins/Measure.js +220 -4
  148. package/plugins/NewsPopup.js +137 -3
  149. package/plugins/OverviewMap.js +167 -7
  150. package/plugins/Panoramax.js +340 -2
  151. package/plugins/Portal.js +199 -4
  152. package/plugins/Print.js +1231 -15
  153. package/plugins/Redlining.js +750 -6
  154. package/plugins/Reports.js +332 -3
  155. package/plugins/Routing.js +1278 -15
  156. package/plugins/ScratchDrawing.js +173 -5
  157. package/plugins/Settings.js +241 -4
  158. package/plugins/Share.js +198 -3
  159. package/plugins/StartupMarker.js +84 -4
  160. package/plugins/TaskButton.js +88 -3
  161. package/plugins/ThemeSwitcher.js +164 -4
  162. package/plugins/TimeManager.js +971 -10
  163. package/plugins/TopBar.js +300 -7
  164. package/plugins/TourGuide.js +213 -2
  165. package/plugins/ValueTool.js +419 -4
  166. package/plugins/View3D.js +519 -14
  167. package/plugins/ZoomButtons.js +165 -3
  168. package/plugins/map/EditingSupport.js +199 -7
  169. package/plugins/map/LocateSupport.js +260 -4
  170. package/plugins/map/MeasurementSupport.js +216 -8
  171. package/plugins/map/RedliningPickSupport.js +201 -7
  172. package/plugins/map/RedliningSupport.js +726 -17
  173. package/plugins/map/SnapInteraction.js +101 -1
  174. package/plugins/map/SnapSupport.js +210 -2
  175. package/plugins/map/SnappingSupport.js +356 -17
  176. package/plugins/map3d/BackgroundSwitcher3D.js +44 -3
  177. package/plugins/map3d/BottomBar3D.js +118 -3
  178. package/plugins/map3d/Compare3D.js +422 -8
  179. package/plugins/map3d/Draw3D.js +353 -6
  180. package/plugins/map3d/ExportObjects3D.js +393 -18
  181. package/plugins/map3d/HideObjects3D.js +313 -12
  182. package/plugins/map3d/Identify3D.js +283 -12
  183. package/plugins/map3d/LayerTree3D.js +323 -3
  184. package/plugins/map3d/MapCopyright3D.js +128 -5
  185. package/plugins/map3d/MapExport3D.js +590 -10
  186. package/plugins/map3d/MapLight3D.js +553 -6
  187. package/plugins/map3d/Measure3D.js +571 -20
  188. package/plugins/map3d/OverviewMap3D.js +169 -3
  189. package/plugins/map3d/Settings3D.js +73 -3
  190. package/plugins/map3d/TopBar3D.js +207 -9
  191. package/plugins/redlining/RedliningBufferSupport.js +206 -3
  192. package/reducers/display.js +34 -2
  193. package/reducers/editing.js +68 -3
  194. package/reducers/index.js +9 -1
  195. package/reducers/layerinfo.js +26 -2
  196. package/reducers/layers.js +456 -9
  197. package/reducers/localConfig.js +122 -2
  198. package/reducers/locale.js +38 -2
  199. package/reducers/locate.js +40 -2
  200. package/reducers/map.js +176 -5
  201. package/reducers/measurement.js +42 -2
  202. package/reducers/processNotifications.js +49 -2
  203. package/reducers/redlining.js +50 -2
  204. package/reducers/redliningPick.js +27 -2
  205. package/reducers/search.js +20 -1
  206. package/reducers/serviceinfo.js +25 -2
  207. package/reducers/task.js +45 -2
  208. package/reducers/theme.js +51 -2
  209. package/reducers/windows.js +203 -2
  210. package/scripts/dist.sh +1 -1
  211. package/scripts/gen-plugin-docs.js +152 -2
  212. package/scripts/makeIconkit.js +85 -6
  213. package/scripts/themesConfig.js +742 -40
  214. package/scripts/updateTranslations.js +251 -10
  215. package/selectors/searchproviders.js +44 -2
  216. package/stores/StandardStore.js +42 -2
  217. package/utils/ConfigUtils.js +84 -3
  218. package/utils/CoordinatesUtils.js +234 -23
  219. package/utils/DxfUtils.js +237 -11
  220. package/utils/EditingInterface.js +421 -87
  221. package/utils/EditingUtils.js +357 -13
  222. package/utils/ElevationInterface.js +83 -22
  223. package/utils/FeatureStyles.js +429 -5
  224. package/utils/IdentifyUtils.js +443 -7
  225. package/utils/ImageEditor.js +79 -9
  226. package/utils/LayerUtils.js +1516 -50
  227. package/utils/LocaleUtils.js +117 -7
  228. package/utils/MapUtils.js +241 -59
  229. package/utils/MeasureUtils.js +323 -2
  230. package/utils/MiscUtils.js +189 -11
  231. package/utils/PermaLinkUtils.js +429 -6
  232. package/utils/PluginStore.js +27 -1
  233. package/utils/ResourceRegistry.js +15 -1
  234. package/utils/RoutingInterface.js +307 -7
  235. package/utils/SearchProviders.js +722 -19
  236. package/utils/ServiceLayerUtils.js +669 -14
  237. package/utils/Signal.js +32 -2
  238. package/utils/ThemeUtils.js +341 -7
  239. package/utils/VectorLayerUtils.js +589 -15
  240. package/utils/expr_grammar/grammar.js +2239 -2
  241. package/utils/expr_grammar/test.js +65 -3
@@ -5,23 +5,226 @@
5
5
  *
6
6
  * This source code is licensed under the BSD-style license found in the
7
7
  * LICENSE file in the root directory of this source tree.
8
- */import React from"react";import ol from"openlayers";var layersMap;var rendererItem;// internal state for visibility of all Google Maps layers in layer tree
9
- var layerVisibilities={};var gmaps={};var isTouchSupported="ontouchstart"in window;var startEvent=isTouchSupported?"touchstart":"mousedown";var moveEvent=isTouchSupported?"touchmove":"mousemove";var endEvent=isTouchSupported?"touchend":"mouseup";// NOTE: For the GoogleLayer to work, you MUST use EPSG:3857 as map projection and the google mercator scales:
8
+ */
9
+
10
+ import React from 'react';
11
+ import ol from 'openlayers';
12
+ var layersMap;
13
+ var rendererItem;
14
+ // internal state for visibility of all Google Maps layers in layer tree
15
+ var layerVisibilities = {};
16
+ var gmaps = {};
17
+ var isTouchSupported = 'ontouchstart' in window;
18
+ var startEvent = isTouchSupported ? 'touchstart' : 'mousedown';
19
+ var moveEvent = isTouchSupported ? 'touchmove' : 'mousemove';
20
+ var endEvent = isTouchSupported ? 'touchend' : 'mouseup';
21
+
22
+ // NOTE: For the GoogleLayer to work, you MUST use EPSG:3857 as map projection and the google mercator scales:
10
23
  // [591658711,295829355,147914678,73957339,36978669,18489335,9244667,4622334,2311167,1155583,577792,288896,144448,72224,36112,18056,9028,4514,2257,1128,564,282,141,71,35,18,9,4,2]
11
- export default{create:function create(options,map){var google=window.google;var mapId=map.get("id");if(mapId!=="map"){// ignore if not main map, e.g. overview
12
- return null}if(!layersMap){layersMap={HYBRID:google.maps.MapTypeId.HYBRID,SATELLITE:google.maps.MapTypeId.SATELLITE,ROADMAP:google.maps.MapTypeId.ROADMAP,TERRAIN:google.maps.MapTypeId.TERRAIN}}if(!gmaps[mapId]){gmaps[mapId]=new google.maps.Map(document.getElementById(mapId+"gmaps"),{disableDefaultUI:true,keyboardShortcuts:false,draggable:false,disableDoubleClickZoom:true,scrollwheel:false,streetViewControl:false,tilt:0})}gmaps[mapId].setMapTypeId(layersMap[options.name]);var mapContainer=document.getElementById(mapId+"gmaps");var setCenter=function setCenter(){if(mapContainer.style.visibility!=="hidden"){var center=ol.proj.transform(map.getView().getCenter(),"EPSG:3857","EPSG:4326");gmaps[mapId].setCenter(new google.maps.LatLng(center[1],center[0]))}};var setZoom=function setZoom(){if(mapContainer.style.visibility!=="hidden"){gmaps[mapId].setZoom(Math.round(map.getView().getZoom()))}};/**
13
- * @param point {array}: [x, y]
14
- * @param alpha {number}: rotation in degrees
15
- */var rotatePoint=function rotatePoint(point,alpha){var radAlpha=alpha*Math.PI/180;var x=point[0];var y=point[1];var rx=x*Math.cos(radAlpha)-y*Math.sin(radAlpha);var ry=x*Math.sin(radAlpha)+y*Math.cos(radAlpha);return[rx,ry]};/**
16
- * @param rotation {number}: rotation in degrees
17
- * @param size {array}: map size [w, h]
18
- */var calculateRotatedSize=function calculateRotatedSize(rotation,size){var w=size[0];var h=size[1];var vertices=[// [ x , y ]
19
- [w/2,h/2],[-w/2,h/2],[-w/2,-h/2],[w/2,-h/2]];var rVertices=vertices.map(function(p){return rotatePoint(p,rotation)});var Xs=rVertices.map(function(p){return p[0]});var Ys=rVertices.map(function(p){return p[1]});var maxX=Math.max.apply(null,Xs);var minX=Math.min.apply(null,Xs);var maxY=Math.max.apply(null,Ys);var minY=Math.min.apply(null,Ys);var H=Math.abs(maxY)+Math.abs(minY);var W=Math.abs(maxX)+Math.abs(minX);return{width:W,height:H}};var setRotation=function setRotation(){if(mapContainer.style.visibility!=="hidden"){var rotation=map.getView().getRotation()*180/Math.PI;mapContainer.style.transform="rotate("+rotation+"deg)";google.maps.event.trigger(gmaps[mapId],"resize")}};var setViewEventListeners=function setViewEventListeners(){var view=map.getView();view.on("change:center",setCenter);view.on("change:resolution",setZoom);view.on("change:rotation",setRotation)};map.on("change:view",setViewEventListeners);setViewEventListeners();setCenter();setZoom();var viewport=map.getViewport();var oldTrans=document.getElementById(mapId+"gmaps").style.transform;var mousedown=false;var mousemove=false;var resizeGoogleLayerIfRotated=function resizeGoogleLayerIfRotated(){var degrees=/[+-]?\d+\.?\d*/i;var newTrans=document.getElementById(mapId+"gmaps").style.transform;if(newTrans!==oldTrans&&newTrans.indexOf("rotate")!==-1){var rotation=parseFloat(newTrans.match(degrees)[0]);var size=calculateRotatedSize(-rotation,map.getSize());mapContainer.style.width=size.width+"px";mapContainer.style.height=size.height+"px";mapContainer.style.left=Math.round((map.getSize()[0]-size.width)/2)+"px";mapContainer.style.top=Math.round((map.getSize()[1]-size.height)/2)+"px";google.maps.event.trigger(gmaps[mapId],"resize");setCenter()}};viewport.addEventListener(startEvent,function(){mousedown=true});viewport.addEventListener(endEvent,function(){if(mousemove&&mousedown){resizeGoogleLayerIfRotated()}oldTrans=document.getElementById(mapId+"gmaps").style.transform;mousedown=false});viewport.addEventListener(moveEvent,function(){mousemove=mousedown});return null},render:function render(options,map){var mapId=map.get("id");if(mapId!=="map"){// ignore if not main map, e.g. overview
20
- return null}// the first item that call render will take control
21
- if(!rendererItem){rendererItem=options.name}var wrapperStyle={zIndex:-1,position:"fixed",left:0,right:0,top:0,bottom:0};var gmapsStyle={height:"100%"};var visibilityChanged=layerVisibilities[options.id]!==options.visibility;layerVisibilities[options.id]=options.visibility;if(options.visibility===true){var div=document.getElementById(mapId+"gmaps");if(div){// override div visibility
22
- div.style.visibility="visible"}if(gmaps[mapId]&&layersMap){gmaps[mapId].setMapTypeId(layersMap[options.name]);gmaps[mapId].setTilt(0);if(visibilityChanged){// update map extent when turning visibility on
23
- var center=ol.proj.transform(map.getView().getCenter(),"EPSG:3857","EPSG:4326");gmaps[mapId].setCenter(new window.google.maps.LatLng(center[1],center[0]));gmaps[mapId].setZoom(map.getView().getZoom())}}}else{gmapsStyle.visibility="hidden";// used only for the renered div
24
- }// To hide the map when visibility is set to false for every
25
- // instance of google layer
26
- if(rendererItem===options.name){// assume the first render the div for gmaps
27
- var _div=document.getElementById(mapId+"gmaps");if(_div){_div.style.visibility=options.visibility?"visible":"hidden"}return/*#__PURE__*/React.createElement("div",{style:wrapperStyle},/*#__PURE__*/React.createElement("div",{className:"fill",id:mapId+"gmaps",style:gmapsStyle}))}return null},update:function update(layer,newOptions,oldOptions,map){var mapId=map.get("id");var google=window.google;if(!oldOptions.visibility&&newOptions.visibility){var view=map.getView();var center=ol.proj.transform(view.getCenter(),"EPSG:3857","EPSG:4326");gmaps[mapId].setCenter(new google.maps.LatLng(center[1],center[0]));gmaps[mapId].setZoom(view.getZoom())}}};
24
+
25
+ export default {
26
+ create: function create(options, map) {
27
+ var google = window.google;
28
+ var mapId = map.get('id');
29
+ if (mapId !== 'map') {
30
+ // ignore if not main map, e.g. overview
31
+ return null;
32
+ }
33
+ if (!layersMap) {
34
+ layersMap = {
35
+ HYBRID: google.maps.MapTypeId.HYBRID,
36
+ SATELLITE: google.maps.MapTypeId.SATELLITE,
37
+ ROADMAP: google.maps.MapTypeId.ROADMAP,
38
+ TERRAIN: google.maps.MapTypeId.TERRAIN
39
+ };
40
+ }
41
+ if (!gmaps[mapId]) {
42
+ gmaps[mapId] = new google.maps.Map(document.getElementById(mapId + 'gmaps'), {
43
+ disableDefaultUI: true,
44
+ keyboardShortcuts: false,
45
+ draggable: false,
46
+ disableDoubleClickZoom: true,
47
+ scrollwheel: false,
48
+ streetViewControl: false,
49
+ tilt: 0
50
+ });
51
+ }
52
+ gmaps[mapId].setMapTypeId(layersMap[options.name]);
53
+ var mapContainer = document.getElementById(mapId + 'gmaps');
54
+ var setCenter = function setCenter() {
55
+ if (mapContainer.style.visibility !== 'hidden') {
56
+ var center = ol.proj.transform(map.getView().getCenter(), 'EPSG:3857', 'EPSG:4326');
57
+ gmaps[mapId].setCenter(new google.maps.LatLng(center[1], center[0]));
58
+ }
59
+ };
60
+ var setZoom = function setZoom() {
61
+ if (mapContainer.style.visibility !== 'hidden') {
62
+ gmaps[mapId].setZoom(Math.round(map.getView().getZoom()));
63
+ }
64
+ };
65
+
66
+ /**
67
+ * @param point {array}: [x, y]
68
+ * @param alpha {number}: rotation in degrees
69
+ */
70
+ var rotatePoint = function rotatePoint(point, alpha) {
71
+ var radAlpha = alpha * Math.PI / 180;
72
+ var x = point[0];
73
+ var y = point[1];
74
+ var rx = x * Math.cos(radAlpha) - y * Math.sin(radAlpha);
75
+ var ry = x * Math.sin(radAlpha) + y * Math.cos(radAlpha);
76
+ return [rx, ry];
77
+ };
78
+
79
+ /**
80
+ * @param rotation {number}: rotation in degrees
81
+ * @param size {array}: map size [w, h]
82
+ */
83
+ var calculateRotatedSize = function calculateRotatedSize(rotation, size) {
84
+ var w = size[0];
85
+ var h = size[1];
86
+ var vertices = [
87
+ // [ x , y ]
88
+ [w / 2, h / 2], [-w / 2, h / 2], [-w / 2, -h / 2], [w / 2, -h / 2]];
89
+ var rVertices = vertices.map(function (p) {
90
+ return rotatePoint(p, rotation);
91
+ });
92
+ var Xs = rVertices.map(function (p) {
93
+ return p[0];
94
+ });
95
+ var Ys = rVertices.map(function (p) {
96
+ return p[1];
97
+ });
98
+ var maxX = Math.max.apply(null, Xs);
99
+ var minX = Math.min.apply(null, Xs);
100
+ var maxY = Math.max.apply(null, Ys);
101
+ var minY = Math.min.apply(null, Ys);
102
+ var H = Math.abs(maxY) + Math.abs(minY);
103
+ var W = Math.abs(maxX) + Math.abs(minX);
104
+ return {
105
+ width: W,
106
+ height: H
107
+ };
108
+ };
109
+ var setRotation = function setRotation() {
110
+ if (mapContainer.style.visibility !== 'hidden') {
111
+ var rotation = map.getView().getRotation() * 180 / Math.PI;
112
+ mapContainer.style.transform = "rotate(" + rotation + "deg)";
113
+ google.maps.event.trigger(gmaps[mapId], "resize");
114
+ }
115
+ };
116
+ var setViewEventListeners = function setViewEventListeners() {
117
+ var view = map.getView();
118
+ view.on('change:center', setCenter);
119
+ view.on('change:resolution', setZoom);
120
+ view.on('change:rotation', setRotation);
121
+ };
122
+ map.on('change:view', setViewEventListeners);
123
+ setViewEventListeners();
124
+ setCenter();
125
+ setZoom();
126
+ var viewport = map.getViewport();
127
+ var oldTrans = document.getElementById(mapId + 'gmaps').style.transform;
128
+ var mousedown = false;
129
+ var mousemove = false;
130
+ var resizeGoogleLayerIfRotated = function resizeGoogleLayerIfRotated() {
131
+ var degrees = /[+-]?\d+\.?\d*/i;
132
+ var newTrans = document.getElementById(mapId + 'gmaps').style.transform;
133
+ if (newTrans !== oldTrans && newTrans.indexOf('rotate') !== -1) {
134
+ var rotation = parseFloat(newTrans.match(degrees)[0]);
135
+ var size = calculateRotatedSize(-rotation, map.getSize());
136
+ mapContainer.style.width = size.width + 'px';
137
+ mapContainer.style.height = size.height + 'px';
138
+ mapContainer.style.left = Math.round((map.getSize()[0] - size.width) / 2.0) + 'px';
139
+ mapContainer.style.top = Math.round((map.getSize()[1] - size.height) / 2.0) + 'px';
140
+ google.maps.event.trigger(gmaps[mapId], "resize");
141
+ setCenter();
142
+ }
143
+ };
144
+ viewport.addEventListener(startEvent, function () {
145
+ mousedown = true;
146
+ });
147
+ viewport.addEventListener(endEvent, function () {
148
+ if (mousemove && mousedown) {
149
+ resizeGoogleLayerIfRotated();
150
+ }
151
+ oldTrans = document.getElementById(mapId + 'gmaps').style.transform;
152
+ mousedown = false;
153
+ });
154
+ viewport.addEventListener(moveEvent, function () {
155
+ mousemove = mousedown;
156
+ });
157
+ return null;
158
+ },
159
+ render: function render(options, map) {
160
+ var mapId = map.get('id');
161
+ if (mapId !== 'map') {
162
+ // ignore if not main map, e.g. overview
163
+ return null;
164
+ }
165
+
166
+ // the first item that call render will take control
167
+ if (!rendererItem) {
168
+ rendererItem = options.name;
169
+ }
170
+ var wrapperStyle = {
171
+ zIndex: -1,
172
+ position: 'fixed',
173
+ left: 0,
174
+ right: 0,
175
+ top: 0,
176
+ bottom: 0
177
+ };
178
+ var gmapsStyle = {
179
+ height: '100%'
180
+ };
181
+ var visibilityChanged = layerVisibilities[options.id] !== options.visibility;
182
+ layerVisibilities[options.id] = options.visibility;
183
+ if (options.visibility === true) {
184
+ var div = document.getElementById(mapId + "gmaps");
185
+ if (div) {
186
+ // override div visibility
187
+ div.style.visibility = 'visible';
188
+ }
189
+ if (gmaps[mapId] && layersMap) {
190
+ gmaps[mapId].setMapTypeId(layersMap[options.name]);
191
+ gmaps[mapId].setTilt(0);
192
+ if (visibilityChanged) {
193
+ // update map extent when turning visibility on
194
+ var center = ol.proj.transform(map.getView().getCenter(), 'EPSG:3857', 'EPSG:4326');
195
+ gmaps[mapId].setCenter(new window.google.maps.LatLng(center[1], center[0]));
196
+ gmaps[mapId].setZoom(map.getView().getZoom());
197
+ }
198
+ }
199
+ } else {
200
+ gmapsStyle.visibility = 'hidden'; // used only for the renered div
201
+ }
202
+ // To hide the map when visibility is set to false for every
203
+ // instance of google layer
204
+ if (rendererItem === options.name) {
205
+ // assume the first render the div for gmaps
206
+ var _div = document.getElementById(mapId + "gmaps");
207
+ if (_div) {
208
+ _div.style.visibility = options.visibility ? 'visible' : 'hidden';
209
+ }
210
+ return /*#__PURE__*/React.createElement("div", {
211
+ style: wrapperStyle
212
+ }, /*#__PURE__*/React.createElement("div", {
213
+ className: "fill",
214
+ id: mapId + "gmaps",
215
+ style: gmapsStyle
216
+ }));
217
+ }
218
+ return null;
219
+ },
220
+ update: function update(layer, newOptions, oldOptions, map) {
221
+ var mapId = map.get('id');
222
+ var google = window.google;
223
+ if (!oldOptions.visibility && newOptions.visibility) {
224
+ var view = map.getView();
225
+ var center = ol.proj.transform(view.getCenter(), 'EPSG:3857', 'EPSG:4326');
226
+ gmaps[mapId].setCenter(new google.maps.LatLng(center[1], center[0]));
227
+ gmaps[mapId].setZoom(view.getZoom());
228
+ }
229
+ }
230
+ };
@@ -5,4 +5,24 @@
5
5
  *
6
6
  * This source code is licensed under the BSD-style license found in the
7
7
  * LICENSE file in the root directory of this source tree.
8
- */import ol from"openlayers";export default{create:function create(options,map){var graticule=new ol.Graticule({strokeStyle:options.style||new ol.style.Stroke({color:"rgba(255,120,0,0.9)",width:2,lineDash:[0.5,4]})});graticule.setMap(map);return{detached:true,remove:function remove(){graticule.setMap(null)}}}};
8
+ */
9
+
10
+ import ol from 'openlayers';
11
+ export default {
12
+ create: function create(options, map) {
13
+ var graticule = new ol.Graticule({
14
+ strokeStyle: options.style || new ol.style.Stroke({
15
+ color: 'rgba(255,120,0,0.9)',
16
+ width: 2,
17
+ lineDash: [0.5, 4]
18
+ })
19
+ });
20
+ graticule.setMap(map);
21
+ return {
22
+ detached: true,
23
+ remove: function remove() {
24
+ graticule.setMap(null);
25
+ }
26
+ };
27
+ }
28
+ };
@@ -5,4 +5,18 @@
5
5
  *
6
6
  * This source code is licensed under the BSD-style license found in the
7
7
  * LICENSE file in the root directory of this source tree.
8
- */import ol from"openlayers";export default{create:function create(options){return new ol.layer.Image({source:new ol.source.ImageStatic({url:options.url,projection:options.projection,imageExtent:options.imageExtent})})},update:function update(){}};
8
+ */
9
+
10
+ import ol from 'openlayers';
11
+ export default {
12
+ create: function create(options) {
13
+ return new ol.layer.Image({
14
+ source: new ol.source.ImageStatic({
15
+ url: options.url,
16
+ projection: options.projection,
17
+ imageExtent: options.imageExtent
18
+ })
19
+ });
20
+ },
21
+ update: function update() {}
22
+ };
@@ -1,7 +1,57 @@
1
- function _typeof(o){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o},_typeof(o)}function ownKeys(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);r&&(o=o.filter(function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable})),t.push.apply(t,o)}return t}function _objectSpread(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?ownKeys(Object(t),!0).forEach(function(r){_defineProperty(e,r,t[r])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):ownKeys(Object(t)).forEach(function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r))})}return e}function _defineProperty(e,r,t){return(r=_toPropertyKey(r))in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function _toPropertyKey(t){var i=_toPrimitive(t,"string");return"symbol"==_typeof(i)?i:i+""}function _toPrimitive(t,r){if("object"!=_typeof(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var i=e.call(t,r||"default");if("object"!=_typeof(i))return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===r?String:Number)(t)}/**
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
5
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
6
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
7
+ /**
2
8
  * Copyright 2022 Oslandia SAS <infos+qwc2@oslandia.com>
3
9
  * All rights reserved.
4
10
  *
5
11
  * This source code is licensed under the BSD-style license found in the
6
12
  * LICENSE file in the root directory of this source tree.
7
- */import axios from"axios";import{applyStyle}from"ol-mapbox-style";import ol from"openlayers";export default{create:function create(options){var createLayer=function createLayer(){return new ol.layer.VectorTile(_objectSpread({minResolution:options.minResolution,maxResolution:options.maxResolution,declutter:options.declutter,source:new ol.source.VectorTile(_objectSpread({projection:options.projection,format:new ol.format.MVT({}),url:options.url,tileGrid:options.tileGridConfig?new ol.tilegrid.TileGrid(_objectSpread({},options.tileGridConfig)):undefined},options.sourceConfig||{}))},options.layerConfig||{}))};var group=new ol.layer.Group;if(options.style){axios.get(options.style).then(function(response){var _glStyle$sprite,_glStyle$glyphs;var glStyle=response.data;((_glStyle$sprite=glStyle.sprite)===null||_glStyle$sprite===void 0?void 0:_glStyle$sprite.startsWith("."))&&(glStyle.sprite=new URL(glStyle.sprite,options.style).href);((_glStyle$glyphs=glStyle.glyphs)===null||_glStyle$glyphs===void 0?void 0:_glStyle$glyphs.startsWith("."))&&(glStyle.glyphs=new URL(glStyle.glyphs,options.style).href);Object.keys(glStyle.sources).forEach(function(styleSource){var _glStyle$sources$styl;((_glStyle$sources$styl=glStyle.sources[styleSource].url)===null||_glStyle$sources$styl===void 0?void 0:_glStyle$sources$styl.startsWith("."))&&(glStyle.sources[styleSource].url=new URL(glStyle.sources[styleSource].url,options.style).href);var layer=createLayer();applyStyle(layer,glStyle,styleSource,options.styleOptions).then(function(){group.getLayers().push(layer)})})})["catch"](function(e){/* eslint-disable-next-line */console.warn("Unable to load style "+options.style+": "+String(e))})}else{group.getLayers().push(createLayer())}return group}};
13
+ */
14
+
15
+ import axios from 'axios';
16
+ import { applyStyle } from 'ol-mapbox-style';
17
+ import ol from 'openlayers';
18
+ export default {
19
+ create: function create(options) {
20
+ var createLayer = function createLayer() {
21
+ return new ol.layer.VectorTile(_objectSpread({
22
+ minResolution: options.minResolution,
23
+ maxResolution: options.maxResolution,
24
+ declutter: options.declutter,
25
+ source: new ol.source.VectorTile(_objectSpread({
26
+ projection: options.projection,
27
+ format: new ol.format.MVT({}),
28
+ url: options.url,
29
+ tileGrid: options.tileGridConfig ? new ol.tilegrid.TileGrid(_objectSpread({}, options.tileGridConfig)) : undefined
30
+ }, options.sourceConfig || {}))
31
+ }, options.layerConfig || {}));
32
+ };
33
+ var group = new ol.layer.Group();
34
+ if (options.style) {
35
+ axios.get(options.style).then(function (response) {
36
+ var _glStyle$sprite, _glStyle$glyphs;
37
+ var glStyle = response.data;
38
+ ((_glStyle$sprite = glStyle.sprite) === null || _glStyle$sprite === void 0 ? void 0 : _glStyle$sprite.startsWith(".")) && (glStyle.sprite = new URL(glStyle.sprite, options.style).href);
39
+ ((_glStyle$glyphs = glStyle.glyphs) === null || _glStyle$glyphs === void 0 ? void 0 : _glStyle$glyphs.startsWith(".")) && (glStyle.glyphs = new URL(glStyle.glyphs, options.style).href);
40
+ Object.keys(glStyle.sources).forEach(function (styleSource) {
41
+ var _glStyle$sources$styl;
42
+ ((_glStyle$sources$styl = glStyle.sources[styleSource].url) === null || _glStyle$sources$styl === void 0 ? void 0 : _glStyle$sources$styl.startsWith(".")) && (glStyle.sources[styleSource].url = new URL(glStyle.sources[styleSource].url, options.style).href);
43
+ var layer = createLayer();
44
+ applyStyle(layer, glStyle, styleSource, options.styleOptions).then(function () {
45
+ group.getLayers().push(layer);
46
+ });
47
+ });
48
+ })["catch"](function (e) {
49
+ /* eslint-disable-next-line */
50
+ console.warn("Unable to load style " + options.style + ": " + String(e));
51
+ });
52
+ } else {
53
+ group.getLayers().push(createLayer());
54
+ }
55
+ return group;
56
+ }
57
+ };
@@ -1,8 +1,30 @@
1
- function _typeof(o){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o},_typeof(o)}function ownKeys(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);r&&(o=o.filter(function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable})),t.push.apply(t,o)}return t}function _objectSpread(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?ownKeys(Object(t),!0).forEach(function(r){_defineProperty(e,r,t[r])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):ownKeys(Object(t)).forEach(function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r))})}return e}function _defineProperty(e,r,t){return(r=_toPropertyKey(r))in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function _toPropertyKey(t){var i=_toPrimitive(t,"string");return"symbol"==_typeof(i)?i:i+""}function _toPrimitive(t,r){if("object"!=_typeof(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var i=e.call(t,r||"default");if("object"!=_typeof(i))return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===r?String:Number)(t)}/**
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
5
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
6
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
7
+ /**
2
8
  * Copyright 2015 GeoSolutions Sas
3
9
  * Copyright 2016-2024 Sourcepole AG
4
10
  * All rights reserved.
5
11
  *
6
12
  * This source code is licensed under the BSD-style license found in the
7
13
  * LICENSE file in the root directory of this source tree.
8
- */import ol from"openlayers";import ConfigUtils from"../../../utils/ConfigUtils";export default{create:function create(options){return new ol.layer.Tile(_objectSpread({minResolution:options.minResolution,maxResolution:options.maxResolution,preload:ConfigUtils.getConfigProp("tilePreloadLevels",null,0),source:new ol.source.OSM(_objectSpread({url:options.url,projection:options.projection},options.sourceConfig||{}))},options.layerConfig||{}))}};
14
+ */
15
+
16
+ import ol from 'openlayers';
17
+ import ConfigUtils from '../../../utils/ConfigUtils';
18
+ export default {
19
+ create: function create(options) {
20
+ return new ol.layer.Tile(_objectSpread({
21
+ minResolution: options.minResolution,
22
+ maxResolution: options.maxResolution,
23
+ preload: ConfigUtils.getConfigProp("tilePreloadLevels", null, 0),
24
+ source: new ol.source.OSM(_objectSpread({
25
+ url: options.url,
26
+ projection: options.projection
27
+ }, options.sourceConfig || {}))
28
+ }, options.layerConfig || {}));
29
+ }
30
+ };
@@ -5,6 +5,58 @@
5
5
  *
6
6
  * This source code is licensed under the BSD-style license found in the
7
7
  * LICENSE file in the root directory of this source tree.
8
- */import ol from"openlayers";var _removeIds=function removeIds(items){if(items.length!==0){for(var i=0;i<items.length;i++){var item=items.item(i);item.removeAttribute("data-reactid");_removeIds(item.children||[])}}};var cloneOriginalOverlay=function cloneOriginalOverlay(original,options){var cloned=original.cloneNode(true);cloned.id=options.id+"-overlay";cloned.className=(options.className||original.className)+"-overlay";cloned.removeAttribute("data-reactid");// remove reactjs generated ids from cloned object
9
- _removeIds(cloned.children||[]);// handle optional close button on overlay
10
- var closeClassName=options.closeClass||"close";if(options.onClose&&cloned.getElementsByClassName(closeClassName).length===1){var close=cloned.getElementsByClassName(closeClassName)[0];var onClose=function onClose(e){options.onClose(e.target.getAttribute("data-overlayid"))};close.addEventListener("click",onClose)}return cloned};export default{create:function create(options,map){var original=document.getElementById(options.id);var cloned=cloneOriginalOverlay(original,options);document.body.appendChild(cloned);var overlay=new ol.Overlay({id:options.id,element:cloned,autoPan:options.autoPan||false,positioning:options.positioning||"top-left",offset:options.offset||[0,0],autoPanAnimation:{duration:options.autoPanAnimation||250},position:[options.position.x,options.position.y]});map.addOverlay(overlay);return{detached:true,remove:function remove(){map.removeOverlay(overlay)}}}};
8
+ */
9
+
10
+ import ol from 'openlayers';
11
+ var _removeIds = function removeIds(items) {
12
+ if (items.length !== 0) {
13
+ for (var i = 0; i < items.length; i++) {
14
+ var item = items.item(i);
15
+ item.removeAttribute('data-reactid');
16
+ _removeIds(item.children || []);
17
+ }
18
+ }
19
+ };
20
+ var cloneOriginalOverlay = function cloneOriginalOverlay(original, options) {
21
+ var cloned = original.cloneNode(true);
22
+ cloned.id = options.id + '-overlay';
23
+ cloned.className = (options.className || original.className) + "-overlay";
24
+ cloned.removeAttribute('data-reactid');
25
+ // remove reactjs generated ids from cloned object
26
+ _removeIds(cloned.children || []);
27
+ // handle optional close button on overlay
28
+ var closeClassName = options.closeClass || 'close';
29
+ if (options.onClose && cloned.getElementsByClassName(closeClassName).length === 1) {
30
+ var close = cloned.getElementsByClassName(closeClassName)[0];
31
+ var onClose = function onClose(e) {
32
+ options.onClose(e.target.getAttribute('data-overlayid'));
33
+ };
34
+ close.addEventListener("click", onClose);
35
+ }
36
+ return cloned;
37
+ };
38
+ export default {
39
+ create: function create(options, map) {
40
+ var original = document.getElementById(options.id);
41
+ var cloned = cloneOriginalOverlay(original, options);
42
+ document.body.appendChild(cloned);
43
+ var overlay = new ol.Overlay({
44
+ id: options.id,
45
+ element: cloned,
46
+ autoPan: options.autoPan || false,
47
+ positioning: options.positioning || 'top-left',
48
+ offset: options.offset || [0, 0],
49
+ autoPanAnimation: {
50
+ duration: options.autoPanAnimation || 250
51
+ },
52
+ position: [options.position.x, options.position.y]
53
+ });
54
+ map.addOverlay(overlay);
55
+ return {
56
+ detached: true,
57
+ remove: function remove() {
58
+ map.removeOverlay(overlay);
59
+ }
60
+ };
61
+ }
62
+ };