From 611346c7fad877c009258d1527809c3e9ff64b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Louren=C3=A7o?= Date: Tue, 10 Feb 2026 11:18:36 +0000 Subject: [PATCH 1/7] Performance improvements for Markers and MarkerCluster --- src/OutSystems/Maps/MapAPI/MarkerManager.ts | 33 ++++++++----------- .../Google/Features/GoogleMarkerClusterer.ts | 4 +-- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/src/OutSystems/Maps/MapAPI/MarkerManager.ts b/src/OutSystems/Maps/MapAPI/MarkerManager.ts index 811fa123..a5b77f72 100644 --- a/src/OutSystems/Maps/MapAPI/MarkerManager.ts +++ b/src/OutSystems/Maps/MapAPI/MarkerManager.ts @@ -1,7 +1,7 @@ // eslint-disable-next-line @typescript-eslint/no-unused-vars namespace OutSystems.Maps.MapAPI.MarkerManager { - const markerMap = new Map(); //marker.uniqueId -> map.uniqueId - const markerArr = new Array(); + //const markerArr = new Array(); + const markerMap = new Map(); /** * Gets the Map to which the Marker belongs to @@ -13,8 +13,8 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { let map: OSFramework.Maps.OSMap.IMap; //markerId is the UniqueId - if (markerMap.has(markerId)) { - map = MapManager.GetMapById(markerMap.get(markerId), false); + if (markerMap.has(markerId) && markerMap.get(markerId).map !== undefined) { + map = MapManager.GetMapById(markerMap.get(markerId).map.uniqueId, false); } //UniqueID not found else { @@ -38,11 +38,7 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { * @param {string} markerId Id of the Marker to be removed */ function CleanMarkerArrays(markerId: string): void { - markerMap.has(markerId) && markerMap.delete(markerId); - const idx = markerArr.findIndex((marker) => marker?.equalsToID(markerId)); - if (idx !== -1) { - markerArr.splice(idx, 1); - } + markerMap.delete(markerId); } /** @@ -69,8 +65,7 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { OSFramework.Maps.Enum.MarkerType.Marker, JSON.parse(configs) ); - markerArr.push(marker); - markerMap.set(markerId, map.uniqueId); + markerMap.set(markerId, marker); map.addMarker(marker); responseObj.message = markerId; @@ -189,8 +184,7 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { OSFramework.Maps.Enum.MarkerType.Marker, JSON.parse(configs) ); - markerArr.push(_marker); - markerMap.set(markerId, map.uniqueId); + markerMap.set(markerId, _marker); map.addMarker(_marker); return _marker; @@ -223,8 +217,7 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { markerType, JSON.parse(configs) ); - markerArr.push(_marker); - markerMap.set(markerId, map.uniqueId); + markerMap.set(markerId, _marker); map.addMarker(_marker); Events.CheckPendingEvents(_marker); @@ -239,7 +232,7 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { * @param markerId Id of the Marker */ export function GetMarkerById(markerId: string, raiseError = true): OSFramework.Maps.Marker.IMarker { - let marker: OSFramework.Maps.Marker.IMarker = markerArr.find((p) => p && p.equalsToID(markerId)); + let marker: OSFramework.Maps.Marker.IMarker = markerMap.get(markerId); // if didn't found marker, check if it was draw by the DrawingTools if (marker === undefined) { @@ -318,8 +311,8 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { MapManager.RemoveMarkers(mapId); } - for (const [storedMarkerId, storedMapId] of markerMap) { - if (storedMapId === mapId) { + for (const [storedMarkerId, marker] of markerMap) { + if (marker.map !== undefined && marker.map.uniqueId === mapId) { const marker = GetMarkerById(storedMarkerId, false); if (marker && marker.widgetId === undefined) { // If the marker does not have a widgetId, it means it was created by @@ -356,8 +349,8 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { } // Second remove the markers to destroy from local variables. - markerMap.forEach((storedMapId, storedMarkerId) => { - if (mapId === storedMapId) { + markerMap.forEach((marker, storedMarkerId) => { + if (marker.map !== undefined && mapId === marker.map.uniqueId) { CleanMarkerArrays(storedMarkerId); } }); diff --git a/src/Providers/Maps/Google/Features/GoogleMarkerClusterer.ts b/src/Providers/Maps/Google/Features/GoogleMarkerClusterer.ts index 09e10dbd..07a42615 100644 --- a/src/Providers/Maps/Google/Features/GoogleMarkerClusterer.ts +++ b/src/Providers/Maps/Google/Features/GoogleMarkerClusterer.ts @@ -95,7 +95,7 @@ namespace Provider.Maps.Google.Feature { public addMarker(marker: OSFramework.Maps.Marker.IMarker): void { if (this.isEnabled && marker.isReady) { // We need to make sure that a redraw is triggered whenever a new marker is added to the clusters - this._markerClusterer.addMarker(marker.provider as GoogleMapsMarker, false); + this._markerClusterer.addMarker(marker.provider as GoogleMapsMarker, true); } } @@ -152,7 +152,7 @@ namespace Provider.Maps.Google.Feature { public removeMarker(marker: OSFramework.Maps.Marker.IMarker): void { if (this.isEnabled && marker.isReady) { // We need to make sure that a redraw is triggered whenever a new marker is removed from the clusters - this._markerClusterer?.removeMarker(marker.provider as GoogleMapsMarker, false); + this._markerClusterer?.removeMarker(marker.provider as GoogleMapsMarker, true); } } From 0606d1bb1ef4d2ce3590ab814996c7b638ccce79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Louren=C3=A7o?= Date: Tue, 10 Feb 2026 15:19:55 +0000 Subject: [PATCH 2/7] Corrected some code comments --- src/OutSystems/Maps/MapAPI/MarkerManager.ts | 1 - src/Providers/Maps/Google/Features/GoogleMarkerClusterer.ts | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/OutSystems/Maps/MapAPI/MarkerManager.ts b/src/OutSystems/Maps/MapAPI/MarkerManager.ts index a5b77f72..914dfcf4 100644 --- a/src/OutSystems/Maps/MapAPI/MarkerManager.ts +++ b/src/OutSystems/Maps/MapAPI/MarkerManager.ts @@ -1,6 +1,5 @@ // eslint-disable-next-line @typescript-eslint/no-unused-vars namespace OutSystems.Maps.MapAPI.MarkerManager { - //const markerArr = new Array(); const markerMap = new Map(); /** diff --git a/src/Providers/Maps/Google/Features/GoogleMarkerClusterer.ts b/src/Providers/Maps/Google/Features/GoogleMarkerClusterer.ts index 07a42615..d8f01b02 100644 --- a/src/Providers/Maps/Google/Features/GoogleMarkerClusterer.ts +++ b/src/Providers/Maps/Google/Features/GoogleMarkerClusterer.ts @@ -94,7 +94,8 @@ namespace Provider.Maps.Google.Feature { public addMarker(marker: OSFramework.Maps.Marker.IMarker): void { if (this.isEnabled && marker.isReady) { - // We need to make sure that a redraw is triggered whenever a new marker is added to the clusters + // The noDraw was set to true to avoid a redraw of the map everytime when a new marker is added to the clusters + // This will not impact the draw of the marker since we are calling the repaint function after the addMarker function this._markerClusterer.addMarker(marker.provider as GoogleMapsMarker, true); } } @@ -151,7 +152,8 @@ namespace Provider.Maps.Google.Feature { public removeMarker(marker: OSFramework.Maps.Marker.IMarker): void { if (this.isEnabled && marker.isReady) { - // We need to make sure that a redraw is triggered whenever a new marker is removed from the clusters + // The noDraw was set to true to avoid a redraw of the map everytime when a new marker is added to the clusters + // This will not impact the draw of the marker since we are calling the repaint function after the addMarker function this._markerClusterer?.removeMarker(marker.provider as GoogleMapsMarker, true); } } From 05c22964578a1e3563ca692492c92141267f2f69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Louren=C3=A7o?= Date: Tue, 10 Feb 2026 20:08:15 +0000 Subject: [PATCH 3/7] Added ADR files for maps --- .gitignore | 1 - docs/adr/ADR-0000-Title-of-ADR copy.md | 46 +++++++++++++++++++ docs/adr/ADR-0001-Google-markers-draw.md | 57 ++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 docs/adr/ADR-0000-Title-of-ADR copy.md create mode 100644 docs/adr/ADR-0001-Google-markers-draw.md diff --git a/.gitignore b/.gitignore index 36f2b739..3ed5199b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,5 @@ code/*.bat code/package-lock.json package-lock.json -docs/* !docs/Licenses !docs/README.md diff --git a/docs/adr/ADR-0000-Title-of-ADR copy.md b/docs/adr/ADR-0000-Title-of-ADR copy.md new file mode 100644 index 00000000..a253dfc8 --- /dev/null +++ b/docs/adr/ADR-0000-Title-of-ADR copy.md @@ -0,0 +1,46 @@ + + +# ADR-0000: Title of ADR + +## Status + +Proposed/Accepted/Rejected/Superseded by ADR-XXXX + +## Context + +What is the issue that we're seeing that is motivating this decision or change? +What is the current architectural state relevant to this decision? +What are the constraints (technical, business, etc.)? + +## Decision Drivers + +- Driver 1 +- Driver 2 +- ... + +## Considered Options + +- Option 1 + - Pros: + - Cons: +- Option 2 + - Pros: + - Cons: +- ... + +## Decision Outcome + +Chosen option: "Option X", because [justification. e.g., only option that meets k.o. criteria decision driver | satisfies critical requirement | ... | comes out best (see below)]. +Positive consequences: + +- ... + Negative consequences: +- ... + +## Links + +- Link to related issues, discussions, or documents. + +## Date + +YYYY-MM-DD \ No newline at end of file diff --git a/docs/adr/ADR-0001-Google-markers-draw.md b/docs/adr/ADR-0001-Google-markers-draw.md new file mode 100644 index 00000000..df7159cc --- /dev/null +++ b/docs/adr/ADR-0001-Google-markers-draw.md @@ -0,0 +1,57 @@ + + +# ADR-0001: Google Markers and Marker Cluster draw phase + +## Status + +Accepted + +## Context + +When a developer places a large number of Markers on a map with clustering enabled, the rendering process becomes overwhelming. This causes the browser to freeze, resulting in significant delays before the Markers and Marker Clusters appear to the user. + +After investigation, it was perceived that adding Markers to the cluster was the root cause of this behavior. Specifically, every time a new Marker is added to a cluster, a redraw is triggered using the existing visual tree. The operation to add a new Marker to the visual tree is computationally expensive and causes the browser to crash or hang. + +Furthermore, in a method called after the addition of the Marker to the cluster, a repaint of the Marker Cluster is triggered. This action is less expensive than the "redraw after add" because it creates a new visual tree rather than modifying the existing one. + +Constraints: + +- Avoid breaking changes for the developer and the runtime experience. +- Keep fixes minimal and localized so they are easier for developers to adopt. + +## Decision Drivers + +- Keep changes minimal and reversible. +- Maintain existing behavior. +- Improve the performance of the overall interaction. + +## Considered Options + +- Option 1: Create new client actions for bulk additions + - Pros: This would optimize the overall draw flow, making it as efficient as possible. It avoids multiple redraws by calling for a repaint only after all new Markers are added. + + - Cons: This would require a higher effort from developers to implement the changes. Additionally, it would necessitate further documentation and significant changes to the codebase to achieve the desired behavior. +- Option 2: Disable draw on addition moment but keep the repaint after addition + - Pros: The difference in performance is significant. It would require no changes for developers to adopt and no need for new documentation. + - Cons: Some discarded repaints will occur, meaning the performance will not be theoretically optimal, though still improved. + +## Decision Outcome + +Chosen option: "Option 1", because it is the only option that allows for performance benefits to reach the majority of users and developers quickly. It is also the best option to ensure that minimal changes are implemented with minimal impact on already developed applications. + +Positive consequences: + +- Increased overall performance of Markers, especially when using Marker Clusters. + +Negative consequences: + +- No negative consequence found. + +## Links + +- [ROU-12504](https://outsystemsrd.atlassian.net/jira/software/c/projects/ROU/boards/544?quickFilter=11980&selectedIssue=ROU-12504) + + +## Date + +2026-02-10 \ No newline at end of file From eda99227d7193d9a44de3f78a0acf07fd52da3b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Louren=C3=A7o?= Date: Wed, 11 Feb 2026 10:36:18 +0000 Subject: [PATCH 4/7] Reverted incorrect changes and fixed documentation files --- ...f-ADR copy.md => ADR-0000-Title-of-ADR.md} | 0 ...R-0001-Google-Markers-Draw-Performance.md} | 2 +- src/OutSystems/Maps/MapAPI/MarkerManager.ts | 32 ++++++++++++------- 3 files changed, 21 insertions(+), 13 deletions(-) rename docs/adr/{ADR-0000-Title-of-ADR copy.md => ADR-0000-Title-of-ADR.md} (100%) rename docs/adr/{ADR-0001-Google-markers-draw.md => ADR-0001-Google-Markers-Draw-Performance.md} (95%) diff --git a/docs/adr/ADR-0000-Title-of-ADR copy.md b/docs/adr/ADR-0000-Title-of-ADR.md similarity index 100% rename from docs/adr/ADR-0000-Title-of-ADR copy.md rename to docs/adr/ADR-0000-Title-of-ADR.md diff --git a/docs/adr/ADR-0001-Google-markers-draw.md b/docs/adr/ADR-0001-Google-Markers-Draw-Performance.md similarity index 95% rename from docs/adr/ADR-0001-Google-markers-draw.md rename to docs/adr/ADR-0001-Google-Markers-Draw-Performance.md index df7159cc..f6a9eead 100644 --- a/docs/adr/ADR-0001-Google-markers-draw.md +++ b/docs/adr/ADR-0001-Google-Markers-Draw-Performance.md @@ -49,7 +49,7 @@ Negative consequences: ## Links -- [ROU-12504](https://outsystemsrd.atlassian.net/jira/software/c/projects/ROU/boards/544?quickFilter=11980&selectedIssue=ROU-12504) +- [ROU-12504](https://outsystemsrd.atlassian.net/browse/ROU-12504) ## Date diff --git a/src/OutSystems/Maps/MapAPI/MarkerManager.ts b/src/OutSystems/Maps/MapAPI/MarkerManager.ts index 914dfcf4..811fa123 100644 --- a/src/OutSystems/Maps/MapAPI/MarkerManager.ts +++ b/src/OutSystems/Maps/MapAPI/MarkerManager.ts @@ -1,6 +1,7 @@ // eslint-disable-next-line @typescript-eslint/no-unused-vars namespace OutSystems.Maps.MapAPI.MarkerManager { - const markerMap = new Map(); + const markerMap = new Map(); //marker.uniqueId -> map.uniqueId + const markerArr = new Array(); /** * Gets the Map to which the Marker belongs to @@ -12,8 +13,8 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { let map: OSFramework.Maps.OSMap.IMap; //markerId is the UniqueId - if (markerMap.has(markerId) && markerMap.get(markerId).map !== undefined) { - map = MapManager.GetMapById(markerMap.get(markerId).map.uniqueId, false); + if (markerMap.has(markerId)) { + map = MapManager.GetMapById(markerMap.get(markerId), false); } //UniqueID not found else { @@ -37,7 +38,11 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { * @param {string} markerId Id of the Marker to be removed */ function CleanMarkerArrays(markerId: string): void { - markerMap.delete(markerId); + markerMap.has(markerId) && markerMap.delete(markerId); + const idx = markerArr.findIndex((marker) => marker?.equalsToID(markerId)); + if (idx !== -1) { + markerArr.splice(idx, 1); + } } /** @@ -64,7 +69,8 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { OSFramework.Maps.Enum.MarkerType.Marker, JSON.parse(configs) ); - markerMap.set(markerId, marker); + markerArr.push(marker); + markerMap.set(markerId, map.uniqueId); map.addMarker(marker); responseObj.message = markerId; @@ -183,7 +189,8 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { OSFramework.Maps.Enum.MarkerType.Marker, JSON.parse(configs) ); - markerMap.set(markerId, _marker); + markerArr.push(_marker); + markerMap.set(markerId, map.uniqueId); map.addMarker(_marker); return _marker; @@ -216,7 +223,8 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { markerType, JSON.parse(configs) ); - markerMap.set(markerId, _marker); + markerArr.push(_marker); + markerMap.set(markerId, map.uniqueId); map.addMarker(_marker); Events.CheckPendingEvents(_marker); @@ -231,7 +239,7 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { * @param markerId Id of the Marker */ export function GetMarkerById(markerId: string, raiseError = true): OSFramework.Maps.Marker.IMarker { - let marker: OSFramework.Maps.Marker.IMarker = markerMap.get(markerId); + let marker: OSFramework.Maps.Marker.IMarker = markerArr.find((p) => p && p.equalsToID(markerId)); // if didn't found marker, check if it was draw by the DrawingTools if (marker === undefined) { @@ -310,8 +318,8 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { MapManager.RemoveMarkers(mapId); } - for (const [storedMarkerId, marker] of markerMap) { - if (marker.map !== undefined && marker.map.uniqueId === mapId) { + for (const [storedMarkerId, storedMapId] of markerMap) { + if (storedMapId === mapId) { const marker = GetMarkerById(storedMarkerId, false); if (marker && marker.widgetId === undefined) { // If the marker does not have a widgetId, it means it was created by @@ -348,8 +356,8 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { } // Second remove the markers to destroy from local variables. - markerMap.forEach((marker, storedMarkerId) => { - if (marker.map !== undefined && mapId === marker.map.uniqueId) { + markerMap.forEach((storedMapId, storedMarkerId) => { + if (mapId === storedMapId) { CleanMarkerArrays(storedMarkerId); } }); From 9ec6740d4c1015b963350129d24d745c0b297660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Louren=C3=A7o?= Date: Wed, 11 Feb 2026 11:41:44 +0000 Subject: [PATCH 5/7] Corrections on the MarkerManager to ensure compatibility with blocks and API creation --- src/OutSystems/Maps/MapAPI/MarkerManager.ts | 72 ++++++++++----------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/src/OutSystems/Maps/MapAPI/MarkerManager.ts b/src/OutSystems/Maps/MapAPI/MarkerManager.ts index 811fa123..ec26531a 100644 --- a/src/OutSystems/Maps/MapAPI/MarkerManager.ts +++ b/src/OutSystems/Maps/MapAPI/MarkerManager.ts @@ -1,7 +1,6 @@ // eslint-disable-next-line @typescript-eslint/no-unused-vars namespace OutSystems.Maps.MapAPI.MarkerManager { - const markerMap = new Map(); //marker.uniqueId -> map.uniqueId - const markerArr = new Array(); + const markerMap = new Map(); /** * Gets the Map to which the Marker belongs to @@ -13,8 +12,8 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { let map: OSFramework.Maps.OSMap.IMap; //markerId is the UniqueId - if (markerMap.has(markerId)) { - map = MapManager.GetMapById(markerMap.get(markerId), false); + if (markerMap.has(markerId) && markerMap.get(markerId).map !== undefined) { + map = MapManager.GetMapById(markerMap.get(markerId).map.uniqueId, false); } //UniqueID not found else { @@ -38,11 +37,7 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { * @param {string} markerId Id of the Marker to be removed */ function CleanMarkerArrays(markerId: string): void { - markerMap.has(markerId) && markerMap.delete(markerId); - const idx = markerArr.findIndex((marker) => marker?.equalsToID(markerId)); - if (idx !== -1) { - markerArr.splice(idx, 1); - } + markerMap.delete(markerId); } /** @@ -69,8 +64,7 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { OSFramework.Maps.Enum.MarkerType.Marker, JSON.parse(configs) ); - markerArr.push(marker); - markerMap.set(markerId, map.uniqueId); + markerMap.set(markerId, marker); map.addMarker(marker); responseObj.message = markerId; @@ -189,8 +183,7 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { OSFramework.Maps.Enum.MarkerType.Marker, JSON.parse(configs) ); - markerArr.push(_marker); - markerMap.set(markerId, map.uniqueId); + markerMap.set(markerId, _marker); map.addMarker(_marker); return _marker; @@ -223,8 +216,7 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { markerType, JSON.parse(configs) ); - markerArr.push(_marker); - markerMap.set(markerId, map.uniqueId); + markerMap.set(markerId, _marker); map.addMarker(_marker); Events.CheckPendingEvents(_marker); @@ -239,29 +231,33 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { * @param markerId Id of the Marker */ export function GetMarkerById(markerId: string, raiseError = true): OSFramework.Maps.Marker.IMarker { - let marker: OSFramework.Maps.Marker.IMarker = markerArr.find((p) => p && p.equalsToID(markerId)); + let marker: OSFramework.Maps.Marker.IMarker = + markerMap.get(markerId) ?? Array.from(markerMap.values()).find((value) => value.equalsToID(markerId)); - // if didn't found marker, check if it was draw by the DrawingTools - if (marker === undefined) { - // Get all maps - const allMaps = [...MapManager.GetMapsFromPage().values()]; - - // On each map, look for all drawingTools and on each one look, - // on the createdElements array, for the markerId passed. - allMaps.find((map: OSFramework.Maps.OSMap.IMap) => { - if (map.drawingTools) { - marker = map.drawingTools.createdElements.find( - (marker: OSFramework.Maps.Marker.IMarker) => marker && marker.equalsToID(markerId) - ) as OSFramework.Maps.Marker.IMarker; - } - return marker; - }); + if (marker !== undefined) { + return marker; + } - // If still wasn't found, then it does not exist - throw error - if (marker === undefined && raiseError) { - throw new Error(`Marker id:${markerId} not found`); + // if didn't found marker, check if it was draw by the DrawingTools + // Get all maps + const allMaps = [...MapManager.GetMapsFromPage().values()]; + + // On each map, look for all drawingTools and on each one look, + // on the createdElements array, for the markerId passed. + allMaps.find((map: OSFramework.Maps.OSMap.IMap) => { + if (map.drawingTools) { + marker = map.drawingTools.createdElements.find( + (marker: OSFramework.Maps.Marker.IMarker) => marker && marker.equalsToID(markerId) + ) as OSFramework.Maps.Marker.IMarker; } + return marker; + }); + + // If still wasn't found, then it does not exist - throw error + if (marker === undefined && raiseError) { + throw new Error(`Marker id:${markerId} not found`); } + return marker; } @@ -318,8 +314,8 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { MapManager.RemoveMarkers(mapId); } - for (const [storedMarkerId, storedMapId] of markerMap) { - if (storedMapId === mapId) { + for (const [storedMarkerId, marker] of markerMap) { + if (marker.map !== undefined && marker.map.equalsToID(mapId)) { const marker = GetMarkerById(storedMarkerId, false); if (marker && marker.widgetId === undefined) { // If the marker does not have a widgetId, it means it was created by @@ -356,8 +352,8 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { } // Second remove the markers to destroy from local variables. - markerMap.forEach((storedMapId, storedMarkerId) => { - if (mapId === storedMapId) { + markerMap.forEach((marker, storedMarkerId) => { + if (marker.map !== undefined && marker.map.equalsToID(mapId)) { CleanMarkerArrays(storedMarkerId); } }); From 943b36f1c13cc8529793a53e444926eb2cf1033d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Louren=C3=A7o?= Date: Wed, 11 Feb 2026 15:01:12 +0000 Subject: [PATCH 6/7] Correction on the MarkerManager logic --- src/OutSystems/Maps/MapAPI/MarkerManager.ts | 46 +++++++++------------ 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/src/OutSystems/Maps/MapAPI/MarkerManager.ts b/src/OutSystems/Maps/MapAPI/MarkerManager.ts index ec26531a..2d629d9d 100644 --- a/src/OutSystems/Maps/MapAPI/MarkerManager.ts +++ b/src/OutSystems/Maps/MapAPI/MarkerManager.ts @@ -9,14 +9,10 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { * @returns {*} {MarkerMapper} this structure has the id of Map, and the reference to the instance of the Map */ function GetMapByMarkerId(markerId: string): OSFramework.Maps.OSMap.IMap { - let map: OSFramework.Maps.OSMap.IMap; + let map: OSFramework.Maps.OSMap.IMap = markerMap.get(markerId)?.map; - //markerId is the UniqueId - if (markerMap.has(markerId) && markerMap.get(markerId).map !== undefined) { - map = MapManager.GetMapById(markerMap.get(markerId).map.uniqueId, false); - } //UniqueID not found - else { + if (map === undefined) { // Try to find its reference on DOM const elem = OSFramework.Maps.Helper.GetElementByUniqueId(markerId, false); @@ -234,28 +230,26 @@ namespace OutSystems.Maps.MapAPI.MarkerManager { let marker: OSFramework.Maps.Marker.IMarker = markerMap.get(markerId) ?? Array.from(markerMap.values()).find((value) => value.equalsToID(markerId)); - if (marker !== undefined) { - return marker; - } - // if didn't found marker, check if it was draw by the DrawingTools - // Get all maps - const allMaps = [...MapManager.GetMapsFromPage().values()]; - - // On each map, look for all drawingTools and on each one look, - // on the createdElements array, for the markerId passed. - allMaps.find((map: OSFramework.Maps.OSMap.IMap) => { - if (map.drawingTools) { - marker = map.drawingTools.createdElements.find( - (marker: OSFramework.Maps.Marker.IMarker) => marker && marker.equalsToID(markerId) - ) as OSFramework.Maps.Marker.IMarker; - } - return marker; - }); + if (marker === undefined) { + // Get all maps + const allMaps = [...MapManager.GetMapsFromPage().values()]; + + // On each map, look for all drawingTools and on each one look, + // on the createdElements array, for the markerId passed. + allMaps.find((map: OSFramework.Maps.OSMap.IMap) => { + if (map.drawingTools) { + marker = map.drawingTools.createdElements.find( + (marker: OSFramework.Maps.Marker.IMarker) => marker && marker.equalsToID(markerId) + ) as OSFramework.Maps.Marker.IMarker; + } + return marker; + }); - // If still wasn't found, then it does not exist - throw error - if (marker === undefined && raiseError) { - throw new Error(`Marker id:${markerId} not found`); + // If still wasn't found, then it does not exist - throw error + if (marker === undefined && raiseError) { + throw new Error(`Marker id:${markerId} not found`); + } } return marker; From 8429a35496378f1a8b410460e5d1856577b6b0d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Louren=C3=A7o?= Date: Wed, 11 Feb 2026 18:39:32 +0000 Subject: [PATCH 7/7] Corrections to the documentation --- ...DR-0001-Google-Markers-Draw-Performance.md | 4 +-- docs/adr/Readme.md | 31 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 docs/adr/Readme.md diff --git a/docs/adr/ADR-0001-Google-Markers-Draw-Performance.md b/docs/adr/ADR-0001-Google-Markers-Draw-Performance.md index f6a9eead..77dc37b8 100644 --- a/docs/adr/ADR-0001-Google-Markers-Draw-Performance.md +++ b/docs/adr/ADR-0001-Google-Markers-Draw-Performance.md @@ -37,7 +37,7 @@ Constraints: ## Decision Outcome -Chosen option: "Option 1", because it is the only option that allows for performance benefits to reach the majority of users and developers quickly. It is also the best option to ensure that minimal changes are implemented with minimal impact on already developed applications. +Chosen option: "Option 2", because it is the only option that allows for performance benefits to reach the majority of users and developers quickly. It is also the best option to ensure that minimal changes are implemented with minimal impact on already developed applications. Positive consequences: @@ -49,7 +49,7 @@ Negative consequences: ## Links -- [ROU-12504](https://outsystemsrd.atlassian.net/browse/ROU-12504) +- ROU-12504 ## Date diff --git a/docs/adr/Readme.md b/docs/adr/Readme.md new file mode 100644 index 00000000..4b62fad4 --- /dev/null +++ b/docs/adr/Readme.md @@ -0,0 +1,31 @@ +# Architecture Decision Records (ADRs) + +This directory contains Architecture Decision Records (ADRs) for this project. +ADRs are short documents that capture important architectural decisions, along with their context and consequences. + +## Purpose + +- To document significant architectural decisions. +- To provide context for why decisions were made. +- To help onboard new team members. +- To facilitate future architectural discussions and evolution. +- To provide context to AI-powered development assistants. + +## Format + +Each ADR should follow the template in `ADR-0000-Title-of-ADR.md`. + +## Process + +1. **Propose:** Copy `ADR-0000-Title-of-ADR.md` to a new file named `NNNN-title-of-adr.md`, where `NNNN` is the next sequential number and the rest is a dash-separated, lowercase version of the title. +2. **Discuss:** Fill out the ADR and discuss it with the team. +3. **Decide:** Once a decision is reached, update the status in the ADR (e.g., "Accepted", "Rejected", "Superseded"). +4. **Commit:** Commit the ADR to the repository. + +## ADR Log + +| ADR Number | Title | Status | Date | +| :--------- | :---------------------------------------------------------------- | :------- | :---------------------------------- | +| ADR-0000 | Template for ADRs | Meta | 2026-02-04 | +| ADR-0001 | Use AI for Development Assistance | Accepted | 2026-02-04 | +| ADR-0002 | Highcharts TypeScript typings compatibility fixes v12 Assistance | Accepted | 2026-02-04 |