Skip to content

Commit e014979

Browse files
authored
Merge pull request #165 from OutSystems/ROU-4708
ROU-4708: adding new APIs for adding/removing marker and marker events
2 parents 2e48230 + 1a76aa8 commit e014979

9 files changed

Lines changed: 210 additions & 37 deletions

File tree

src/OSFramework/Maps/Enum/ErrorCodes.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ namespace OSFramework.Maps.Enum {
5656
API_FailedRemoveMarkerFromCluster = 'MAPS-API-09001',
5757
API_FailedContainsLocation = 'MAPS-API-05005',
5858
API_FailedGettingCenterCoordinates = 'MAPS-API-01001',
59+
API_FailedCreateMarker = 'MAPS-API-09002',
60+
API_FailedRemoveMarker = 'MAPS-API-09003',
61+
API_FailedRemoveMarkers = 'MAPS-API-09004',
62+
API_FailedSubscribeMarkerEvent = 'MAPS-API-09005',
63+
API_FailedUnsubscribeMarkerEvent = 'MAPS-API-09006',
5964

6065
// Error Codes - GENeral error - General or internal Errors of the component. In the situation of simple components without different features/sections inside it, the GEN acronym should be used.
6166
GEN_InvalidChangePropertyMap = 'MAPS-GEN-01001',

src/OSFramework/Maps/Event/Marker/MarkerEventsManager.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,27 +72,23 @@ namespace OSFramework.Maps.Event.Marker {
7272
// The following events are being deprecated. They should get removed soon.
7373
switch (eventType) {
7474
case MarkerEventType.Initialized:
75+
case MarkerEventType.OnMouseout:
76+
case MarkerEventType.OnMouseover:
7577
handlerEvent.trigger(
7678
this._marker.map.widgetId, // Id of Map block that was initialized
7779
this._marker.widgetId || this._marker.uniqueId, // Id of Marker block that was initialized
80+
eventType,
7881
this._marker.index // Index of Marker block that was initialized
7982
);
8083
break;
8184
case MarkerEventType.OnClick:
8285
handlerEvent.trigger(
8386
this._marker.map.widgetId, // Id of Map block that was clicked
8487
this._marker.widgetId || this._marker.uniqueId, // Id of Marker block that was clicked
88+
eventType,
8589
...args // Coordinates retrieved from the marker event that got triggered
8690
);
8791
break;
88-
case MarkerEventType.OnMouseout:
89-
case MarkerEventType.OnMouseover:
90-
handlerEvent.trigger(
91-
this._marker.map.widgetId, // Id of Map block that was clicked
92-
this._marker.widgetId || this._marker.uniqueId, // Id of Marker block that was clicked
93-
this._marker.index // Index of Marker block that was clicked
94-
);
95-
break;
9692
case MarkerEventType.OnEventTriggered:
9793
handlerEvent.trigger(
9894
this._marker.map.widgetId, // Id of Map block that triggered the event

src/OSFramework/Maps/OSMap/AbstractMap.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace OSFramework.Maps.OSMap {
1010
private _heatmapLayersSet: Set<HeatmapLayer.IHeatmapLayer>;
1111
private _isReady: boolean;
1212
private _mapEvents: Event.OSMap.MapEventsManager;
13+
private _mapRefreshRequest: number;
1314
private _mapType: Enum.MapType;
1415
private _markers: Map<string, Marker.IMarker>;
1516
private _markersSet: Set<Marker.IMarker>;
@@ -38,6 +39,7 @@ namespace OSFramework.Maps.OSMap {
3839
this._isReady = false;
3940
this._mapEvents = new Event.OSMap.MapEventsManager(this);
4041
this._mapType = mapType;
42+
this._mapRefreshRequest = 0;
4143
this._providerType = providerType;
4244
this._zoomChanged = false;
4345
this._mapZoomChangeCallback = this._mapZoomChangeHandler.bind(this);
@@ -156,6 +158,13 @@ namespace OSFramework.Maps.OSMap {
156158
this._widgetId = Helper.GetElementByUniqueId(this.uniqueId).closest(this.mapTag).id;
157159
}
158160

161+
public cancelScheduledResfresh(): void {
162+
if (this._mapRefreshRequest !== 0) {
163+
clearTimeout(this._mapRefreshRequest);
164+
this._mapRefreshRequest = 0;
165+
}
166+
}
167+
159168
public changeProperty(propertyName: string, propertyValue: unknown): void {
160169
//Update Map's config when the property is available
161170
if (this.config.hasOwnProperty(propertyName)) {
@@ -404,6 +413,14 @@ namespace OSFramework.Maps.OSMap {
404413
}
405414
}
406415

416+
public scheduleRefresh(): void {
417+
this.cancelScheduledResfresh();
418+
419+
this._mapRefreshRequest = setTimeout(() => {
420+
this.refresh();
421+
}, 0);
422+
}
423+
407424
public updateHeight(): void {
408425
// Because only some specific map providers like Leaflet Provider need to update or refresh the map after changing its height,
409426
// this function doesn't need any logic

src/OSFramework/Maps/OSMap/IMap.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ namespace OSFramework.Maps.OSMap {
6565
* @returns Shape that has been created
6666
*/
6767
addShape(shape: OSFramework.Maps.Shape.IShape): OSFramework.Maps.Shape.IShape;
68+
/**
69+
* Stops the current refresh from being refreshed.
70+
*
71+
* @memberof IMap
72+
*/
73+
cancelScheduledResfresh(): void;
6874
/**
6975
* Change property of a drawingTools from the DrawingTools by specifying the property name and the new value
7076
* @param drawingToolsId id of the DrawingTools
@@ -194,12 +200,17 @@ namespace OSFramework.Maps.OSMap {
194200
* @param shapeId id of the shape
195201
*/
196202
removeShape(shapeId: string): void;
203+
/**
204+
* Schedules the map to be refreshed so, that the bulk operations are made fast.
205+
* @memberof IMap
206+
*/
207+
scheduleRefresh(): void;
197208
/**
198209
* Adds a custom render to the Clusters. Applicable to some providers only.
199210
* @param {OSFramework.Maps.Feature.IMarkerClusterer} renderer
200211
* @memberof IMap
201212
*/
202-
setClusterRenderer?(renderer: OSFramework.Maps.Feature.IMarkerClustererRender);
213+
setClusterRenderer?(renderer: OSFramework.Maps.Feature.IMarkerClustererRender): void;
203214
/**
204215
* Updates the Height of the Map by refreshing/updating the provider
205216
*/

src/OutSystems/Maps/MapAPI/MapManager.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,23 @@ namespace OutSystems.Maps.MapAPI.MapManager {
7979
export function GetMapById(mapId: string, raiseError = true): OSFramework.Maps.OSMap.IMap {
8080
let map: OSFramework.Maps.OSMap.IMap;
8181

82-
//mapId is the UniqueId
8382
if (maps.has(mapId)) {
83+
// mapId = uniqueId
8484
map = maps.get(mapId);
8585
} else {
86-
//Search for WidgetId
87-
for (const p of maps.values()) {
88-
if (p.equalsToID(mapId)) {
89-
map = p;
90-
break;
91-
}
86+
// map = widgetId
87+
// Search for (all) the map(s) that have this WidgetId
88+
const mapFiltered = Array.from(maps.values()).filter((p) => p.equalsToID(mapId));
89+
90+
// There can be situations, for example when changing from a page
91+
// to another page that also has a "Map", in which, we'll end up
92+
// having 2 maps, with different uniqueIds, but same Widget id.
93+
if (mapFiltered.length > 0) {
94+
// So we'll always pick the last map of that was found and it
95+
// will correspond to the last map that was created in the app
96+
// (in these cases, the new map). The other map, is the one
97+
// that will be destroyed afterwards.
98+
map = mapFiltered[mapFiltered.length - 1];
9299
}
93100
}
94101

@@ -148,6 +155,9 @@ namespace OutSystems.Maps.MapAPI.MapManager {
148155
}
149156

150157
map.dispose();
158+
159+
//Let's remove the empty markers references from the Markers API.
160+
MarkerManager.RemoveAllMarkers(mapId, false);
151161
}
152162

153163
/**

src/OutSystems/Maps/MapAPI/MarkerManager.Events.ts

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,30 @@ namespace OutSystems.Maps.MapAPI.MarkerManager.Events {
6060
* @export
6161
* @param {string} markerId Marker where the events will get attached
6262
* @param {OSFramework.Maps.Event.Marker.MarkerEventType} eventName name of the event to get attached
63-
* @param {OSFramework.Maps.Callbacks.Marker.ClickEvent} callback to be invoked when the event occurs
63+
* @param {OSFramework.Maps.Callbacks.Marker.Event} callback to be invoked when the event occurs
6464
*/
6565
export function Subscribe(
6666
markerId: string,
6767
eventName: OSFramework.Maps.Event.Marker.MarkerEventType,
68-
// eslint-disable-next-line
6968
callback: OSFramework.Maps.Callbacks.Marker.Event
70-
): void {
71-
const marker = GetMarkerById(markerId);
72-
marker.markerEvents.addHandler(eventName, callback, markerId);
69+
): string {
70+
const responseObj = {
71+
isSuccess: true,
72+
message: 'Success',
73+
code: '200',
74+
};
75+
try {
76+
const marker = GetMarkerById(markerId);
77+
marker.markerEvents.addHandler(eventName, callback, markerId);
78+
// Let's make sure the events get refreshed on the Marker provider
79+
marker.refreshProviderEvents();
80+
} catch (error) {
81+
responseObj.isSuccess = false;
82+
responseObj.message = error.message;
83+
responseObj.code = OSFramework.Maps.Enum.ErrorCodes.API_FailedSubscribeMarkerEvent;
84+
}
85+
86+
return JSON.stringify(responseObj);
7387
}
7488

7589
/**
@@ -78,7 +92,7 @@ namespace OutSystems.Maps.MapAPI.MarkerManager.Events {
7892
* @export
7993
* @param {string} eventUniqueId Id of the Event to be attached
8094
* @param {OSFramework.Maps.Event.Map.MapEventType} eventName name fo the event to be attached
81-
* @param {MapAPI.Callbacks.OSMap.Event} callback callback to be invoked when the event occurs
95+
* @param {OSFramework.Maps.Callbacks.Marker.Event} callback callback to be invoked when the event occurs
8296
*/
8397
export function SubscribeByUniqueId(
8498
eventUniqueId: string,
@@ -135,12 +149,11 @@ namespace OutSystems.Maps.MapAPI.MarkerManager.Events {
135149
* @export
136150
* @param {string} eventUniqueId Map where the event will be removed
137151
* @param {OSFramework.Maps.Event.Map.MapEventType} eventName name of the event to be removed
138-
* @param {MapAPI.Callbacks.OSMap.Event} callback callback that will be removed
152+
* @param {OSFramework.Maps.Callbacks.Marker.Event} callback callback that will be removed
139153
*/
140154
export function Unsubscribe(
141155
eventUniqueId: string,
142156
eventName: OSFramework.Maps.Event.Marker.MarkerEventType,
143-
// eslint-disable-next-line
144157
callback: OSFramework.Maps.Callbacks.Marker.Event
145158
): void {
146159
const markerId = GetMarkerIdByEventUniqueId(eventUniqueId);
@@ -160,6 +173,32 @@ namespace OutSystems.Maps.MapAPI.MarkerManager.Events {
160173
}
161174
}
162175
}
176+
177+
export function UnsubscribeByMarkerId(
178+
markerId: string,
179+
eventName: OSFramework.Maps.Event.Marker.MarkerEventType,
180+
callback: OSFramework.Maps.Callbacks.Marker.Event
181+
): string {
182+
const responseObj = {
183+
isSuccess: true,
184+
message: 'Success',
185+
code: '200',
186+
};
187+
try {
188+
const marker = GetMarkerById(markerId);
189+
if (marker !== undefined) {
190+
marker.markerEvents.removeHandler(eventName, callback);
191+
// Let's make sure the events get refreshed on the Marker provider
192+
marker.refreshProviderEvents();
193+
}
194+
} catch (error) {
195+
responseObj.isSuccess = false;
196+
responseObj.message = error.message;
197+
responseObj.code = OSFramework.Maps.Enum.ErrorCodes.API_FailedUnsubscribeMarkerEvent;
198+
}
199+
200+
return JSON.stringify(responseObj);
201+
}
163202
}
164203

165204
/// Overrides for the old namespace - calls the new one, lets users know this is no longer in use

src/OutSystems/Maps/MapAPI/MarkerManager.ts

Lines changed: 102 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,44 @@ namespace OutSystems.Maps.MapAPI.MarkerManager {
33
const markerMap = new Map<string, string>(); //marker.uniqueId -> map.uniqueId
44
const markerArr = new Array<OSFramework.Maps.Marker.IMarker>();
55

6+
/**
7+
* Creates and adds a marker to a map.
8+
*
9+
* @export
10+
* @param {string} mapId Id of the map to which the marker should be added
11+
* @param {string} configs Configurations for the marker
12+
* @return {*} {string}
13+
*/
14+
export function AddMarker(mapId: string, configs: string): string {
15+
const responseObj = {
16+
isSuccess: true,
17+
message: 'Success',
18+
code: '200',
19+
};
20+
21+
try {
22+
const map = MapManager.GetMapById(mapId, true);
23+
const markerId = OSFramework.Maps.Helper.GenerateUniqueId();
24+
const marker = OSFramework.Maps.Marker.MarkerFactory.MakeMarker(
25+
map,
26+
markerId,
27+
OSFramework.Maps.Enum.MarkerType.Marker,
28+
JSON.parse(configs)
29+
);
30+
markerArr.push(marker);
31+
markerMap.set(markerId, map.uniqueId);
32+
map.addMarker(marker);
33+
34+
responseObj.message = markerId;
35+
} catch (error) {
36+
responseObj.isSuccess = false;
37+
responseObj.message = error.message;
38+
responseObj.code = OSFramework.Maps.Enum.ErrorCodes.API_FailedCreateMarker;
39+
}
40+
41+
return JSON.stringify(responseObj);
42+
}
43+
644
/**
745
* Changes the property value of a given Marker.
846
*
@@ -226,18 +264,71 @@ namespace OutSystems.Maps.MapAPI.MarkerManager {
226264
* @export
227265
* @param {string} markerID id of the Marker that is about to be removed
228266
*/
229-
export function RemoveMarker(markerId: string): void {
230-
const marker = GetMarkerById(markerId);
231-
const map = marker.map;
267+
export function RemoveMarker(markerId: string): string {
268+
const responseObj = {
269+
isSuccess: true,
270+
message: 'Success',
271+
code: '200',
272+
};
273+
try {
274+
const marker = GetMarkerById(markerId);
275+
const map = marker.map;
276+
map && map.removeMarker(markerId);
277+
278+
markerMap.delete(markerId);
279+
markerArr.splice(
280+
markerArr.findIndex((p) => {
281+
return p && p.equalsToID(markerId);
282+
}),
283+
1
284+
);
285+
} catch (error) {
286+
responseObj.isSuccess = false;
287+
responseObj.message = error.message;
288+
responseObj.code = OSFramework.Maps.Enum.ErrorCodes.API_FailedRemoveMarker;
289+
}
232290

233-
map && map.removeMarker(markerId);
234-
markerMap.delete(markerId);
235-
markerArr.splice(
236-
markerArr.findIndex((p) => {
237-
return p && p.equalsToID(markerId);
238-
}),
239-
1
240-
);
291+
return JSON.stringify(responseObj);
292+
}
293+
294+
/**
295+
* Removes all the markers of a given map.
296+
*
297+
* @export
298+
* @param {string} mapId
299+
* @return {*} {string}
300+
*/
301+
export function RemoveAllMarkers(mapId: string, removeFromMap = true): string {
302+
const responseObj = {
303+
isSuccess: true,
304+
message: 'Success',
305+
code: '200',
306+
};
307+
try {
308+
if (removeFromMap) {
309+
// First we try to remove the markers from the map.
310+
MapManager.RemoveMarkers(mapId);
311+
}
312+
313+
// Second remove the markers to destroy from local variables.
314+
markerMap.forEach((storedMapId, storedMarkerId) => {
315+
if (mapId === storedMapId) {
316+
markerMap.delete(storedMarkerId);
317+
markerArr.splice(
318+
markerArr.findIndex((p) => {
319+
return p && p.equalsToID(storedMarkerId);
320+
}),
321+
1
322+
);
323+
}
324+
});
325+
} catch (error) {
326+
responseObj.isSuccess = false;
327+
responseObj.message = error.message;
328+
responseObj.code = OSFramework.Maps.Enum.ErrorCodes.API_FailedRemoveMarkers;
329+
}
330+
331+
return JSON.stringify(responseObj);
241332
}
242333
}
243334

0 commit comments

Comments
 (0)