Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ROU-4708: adding new APIs for adding/removing marker and marker events #165

Merged
merged 13 commits into from
Mar 8, 2024
5 changes: 5 additions & 0 deletions src/OSFramework/Maps/Enum/ErrorCodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ namespace OSFramework.Maps.Enum {
API_FailedRemoveMarkerFromCluster = 'MAPS-API-09001',
API_FailedContainsLocation = 'MAPS-API-05005',
API_FailedGettingCenterCoordinates = 'MAPS-API-01001',
API_FailedCreateMarker = 'MAPS-API-09002',
API_FailedRemoveMarker = 'MAPS-API-09003',
API_FailedRemoveMarkers = 'MAPS-API-09004',
API_FailedSubscribeMarkerEvent = 'MAPS-API-09005',
API_FailedUnsubscribeMarkerEvent = 'MAPS-API-09006',

// 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.
GEN_InvalidChangePropertyMap = 'MAPS-GEN-01001',
Expand Down
12 changes: 4 additions & 8 deletions src/OSFramework/Maps/Event/Marker/MarkerEventsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,27 +72,23 @@ namespace OSFramework.Maps.Event.Marker {
// The following events are being deprecated. They should get removed soon.
switch (eventType) {
case MarkerEventType.Initialized:
case MarkerEventType.OnMouseout:
case MarkerEventType.OnMouseover:
handlerEvent.trigger(
this._marker.map.widgetId, // Id of Map block that was initialized
this._marker.widgetId || this._marker.uniqueId, // Id of Marker block that was initialized
eventType,
this._marker.index // Index of Marker block that was initialized
);
break;
case MarkerEventType.OnClick:
handlerEvent.trigger(
this._marker.map.widgetId, // Id of Map block that was clicked
this._marker.widgetId || this._marker.uniqueId, // Id of Marker block that was clicked
eventType,
...args // Coordinates retrieved from the marker event that got triggered
);
break;
case MarkerEventType.OnMouseout:
case MarkerEventType.OnMouseover:
handlerEvent.trigger(
this._marker.map.widgetId, // Id of Map block that was clicked
this._marker.widgetId || this._marker.uniqueId, // Id of Marker block that was clicked
this._marker.index // Index of Marker block that was clicked
);
break;
case MarkerEventType.OnEventTriggered:
handlerEvent.trigger(
this._marker.map.widgetId, // Id of Map block that triggered the event
Expand Down
17 changes: 17 additions & 0 deletions src/OSFramework/Maps/OSMap/AbstractMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace OSFramework.Maps.OSMap {
private _heatmapLayersSet: Set<HeatmapLayer.IHeatmapLayer>;
private _isReady: boolean;
private _mapEvents: Event.OSMap.MapEventsManager;
private _mapRefreshRequest: number;
private _mapType: Enum.MapType;
private _markers: Map<string, Marker.IMarker>;
private _markersSet: Set<Marker.IMarker>;
Expand Down Expand Up @@ -38,6 +39,7 @@ namespace OSFramework.Maps.OSMap {
this._isReady = false;
this._mapEvents = new Event.OSMap.MapEventsManager(this);
this._mapType = mapType;
this._mapRefreshRequest = 0;
this._providerType = providerType;
this._zoomChanged = false;
this._mapZoomChangeCallback = this._mapZoomChangeHandler.bind(this);
Expand Down Expand Up @@ -156,6 +158,13 @@ namespace OSFramework.Maps.OSMap {
this._widgetId = Helper.GetElementByUniqueId(this.uniqueId).closest(this.mapTag).id;
}

public cancelScheduledResfresh(): void {
if (this._mapRefreshRequest !== 0) {
clearTimeout(this._mapRefreshRequest);
this._mapRefreshRequest = 0;
}
}

public changeProperty(propertyName: string, propertyValue: unknown): void {
//Update Map's config when the property is available
if (this.config.hasOwnProperty(propertyName)) {
Expand Down Expand Up @@ -404,6 +413,14 @@ namespace OSFramework.Maps.OSMap {
}
}

public scheduleRefresh(): void {
this.cancelScheduledResfresh();

this._mapRefreshRequest = setTimeout(() => {
this.refresh();
}, 0);
}

public updateHeight(): void {
// Because only some specific map providers like Leaflet Provider need to update or refresh the map after changing its height,
// this function doesn't need any logic
Expand Down
13 changes: 12 additions & 1 deletion src/OSFramework/Maps/OSMap/IMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ namespace OSFramework.Maps.OSMap {
* @returns Shape that has been created
*/
addShape(shape: OSFramework.Maps.Shape.IShape): OSFramework.Maps.Shape.IShape;
/**
* Stops the current refresh from being refreshed.
*
* @memberof IMap
*/
cancelScheduledResfresh(): void;
/**
* Change property of a drawingTools from the DrawingTools by specifying the property name and the new value
* @param drawingToolsId id of the DrawingTools
Expand Down Expand Up @@ -194,12 +200,17 @@ namespace OSFramework.Maps.OSMap {
* @param shapeId id of the shape
*/
removeShape(shapeId: string): void;
/**
* Schedules the map to be refreshed so, that the bulk operations are made fast.
* @memberof IMap
*/
scheduleRefresh(): void;
/**
* Adds a custom render to the Clusters. Applicable to some providers only.
* @param {OSFramework.Maps.Feature.IMarkerClusterer} renderer
* @memberof IMap
*/
setClusterRenderer?(renderer: OSFramework.Maps.Feature.IMarkerClustererRender);
setClusterRenderer?(renderer: OSFramework.Maps.Feature.IMarkerClustererRender): void;
/**
* Updates the Height of the Map by refreshing/updating the provider
*/
Expand Down
24 changes: 17 additions & 7 deletions src/OutSystems/Maps/MapAPI/MapManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,23 @@ namespace OutSystems.Maps.MapAPI.MapManager {
export function GetMapById(mapId: string, raiseError = true): OSFramework.Maps.OSMap.IMap {
let map: OSFramework.Maps.OSMap.IMap;

//mapId is the UniqueId
if (maps.has(mapId)) {
// mapId = uniqueId
map = maps.get(mapId);
} else {
//Search for WidgetId
for (const p of maps.values()) {
if (p.equalsToID(mapId)) {
map = p;
break;
}
// map = widgetId
// Search for (all) the map(s) that have this WidgetId
const mapFiltered = Array.from(maps.values()).filter((p) => p.equalsToID(mapId));

// There can be situations, for example when changing from a page
// to another page that also has a "Map", in which, we'll end up
// having 2 maps, with different uniqueIds, but same Widget id.
if (mapFiltered.length > 0) {
// So we'll always pick the last map of that was found and it
// will correspond to the last map that was created in the app
// (in these cases, the new map). The other map, is the one
// that will be destroyed afterwards.
map = mapFiltered[mapFiltered.length - 1];
}
}

Expand Down Expand Up @@ -148,6 +155,9 @@ namespace OutSystems.Maps.MapAPI.MapManager {
}

map.dispose();

//Let's remove the empty markers references from the Markers API.
MarkerManager.RemoveAllMarkers(mapId, false);
joselrio marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down
55 changes: 47 additions & 8 deletions src/OutSystems/Maps/MapAPI/MarkerManager.Events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,30 @@ namespace OutSystems.Maps.MapAPI.MarkerManager.Events {
* @export
* @param {string} markerId Marker where the events will get attached
* @param {OSFramework.Maps.Event.Marker.MarkerEventType} eventName name of the event to get attached
* @param {OSFramework.Maps.Callbacks.Marker.ClickEvent} callback to be invoked when the event occurs
* @param {OSFramework.Maps.Callbacks.Marker.Event} callback to be invoked when the event occurs
*/
export function Subscribe(
markerId: string,
eventName: OSFramework.Maps.Event.Marker.MarkerEventType,
// eslint-disable-next-line
callback: OSFramework.Maps.Callbacks.Marker.Event
): void {
const marker = GetMarkerById(markerId);
marker.markerEvents.addHandler(eventName, callback, markerId);
): string {
const responseObj = {
isSuccess: true,
message: 'Success',
code: '200',
};
try {
const marker = GetMarkerById(markerId);
marker.markerEvents.addHandler(eventName, callback, markerId);
// Let's make sure the events get refreshed on the Marker provider
marker.refreshProviderEvents();
} catch (error) {
responseObj.isSuccess = false;
responseObj.message = error.message;
responseObj.code = OSFramework.Maps.Enum.ErrorCodes.API_FailedSubscribeMarkerEvent;
}

return JSON.stringify(responseObj);
}

/**
Expand All @@ -78,7 +92,7 @@ namespace OutSystems.Maps.MapAPI.MarkerManager.Events {
* @export
* @param {string} eventUniqueId Id of the Event to be attached
* @param {OSFramework.Maps.Event.Map.MapEventType} eventName name fo the event to be attached
* @param {MapAPI.Callbacks.OSMap.Event} callback callback to be invoked when the event occurs
* @param {OSFramework.Maps.Callbacks.Marker.Event} callback callback to be invoked when the event occurs
*/
export function SubscribeByUniqueId(
eventUniqueId: string,
Expand Down Expand Up @@ -135,12 +149,11 @@ namespace OutSystems.Maps.MapAPI.MarkerManager.Events {
* @export
* @param {string} eventUniqueId Map where the event will be removed
* @param {OSFramework.Maps.Event.Map.MapEventType} eventName name of the event to be removed
* @param {MapAPI.Callbacks.OSMap.Event} callback callback that will be removed
* @param {OSFramework.Maps.Callbacks.Marker.Event} callback callback that will be removed
*/
export function Unsubscribe(
eventUniqueId: string,
eventName: OSFramework.Maps.Event.Marker.MarkerEventType,
// eslint-disable-next-line
callback: OSFramework.Maps.Callbacks.Marker.Event
): void {
const markerId = GetMarkerIdByEventUniqueId(eventUniqueId);
Expand All @@ -160,6 +173,32 @@ namespace OutSystems.Maps.MapAPI.MarkerManager.Events {
}
}
}

export function UnsubscribeByMarkerId(
markerId: string,
eventName: OSFramework.Maps.Event.Marker.MarkerEventType,
callback: OSFramework.Maps.Callbacks.Marker.Event
): string {
const responseObj = {
isSuccess: true,
message: 'Success',
code: '200',
};
try {
const marker = GetMarkerById(markerId);
if (marker !== undefined) {
marker.markerEvents.removeHandler(eventName, callback);
// Let's make sure the events get refreshed on the Marker provider
marker.refreshProviderEvents();
}
} catch (error) {
responseObj.isSuccess = false;
responseObj.message = error.message;
responseObj.code = OSFramework.Maps.Enum.ErrorCodes.API_FailedUnsubscribeMarkerEvent;
}

return JSON.stringify(responseObj);
}
}

/// Overrides for the old namespace - calls the new one, lets users know this is no longer in use
Expand Down
113 changes: 102 additions & 11 deletions src/OutSystems/Maps/MapAPI/MarkerManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,44 @@ namespace OutSystems.Maps.MapAPI.MarkerManager {
const markerMap = new Map<string, string>(); //marker.uniqueId -> map.uniqueId
const markerArr = new Array<OSFramework.Maps.Marker.IMarker>();

/**
* Creates and adds a marker to a map.
*
* @export
* @param {string} mapId Id of the map to which the marker should be added
* @param {string} configs Configurations for the marker
* @return {*} {string}
*/
export function AddMarker(mapId: string, configs: string): string {
const responseObj = {
isSuccess: true,
message: 'Success',
code: '200',
};

try {
const map = MapManager.GetMapById(mapId, true);
const markerId = OSFramework.Maps.Helper.GenerateUniqueId();
const marker = OSFramework.Maps.Marker.MarkerFactory.MakeMarker(
map,
markerId,
OSFramework.Maps.Enum.MarkerType.Marker,
JSON.parse(configs)
);
markerArr.push(marker);
markerMap.set(markerId, map.uniqueId);
map.addMarker(marker);

responseObj.message = markerId;
} catch (error) {
responseObj.isSuccess = false;
responseObj.message = error.message;
responseObj.code = OSFramework.Maps.Enum.ErrorCodes.API_FailedCreateMarker;
}

return JSON.stringify(responseObj);
}

/**
* Changes the property value of a given Marker.
*
Expand Down Expand Up @@ -226,18 +264,71 @@ namespace OutSystems.Maps.MapAPI.MarkerManager {
* @export
* @param {string} markerID id of the Marker that is about to be removed
*/
export function RemoveMarker(markerId: string): void {
const marker = GetMarkerById(markerId);
const map = marker.map;
export function RemoveMarker(markerId: string): string {
const responseObj = {
isSuccess: true,
message: 'Success',
code: '200',
};
try {
const marker = GetMarkerById(markerId);
const map = marker.map;
map && map.removeMarker(markerId);

markerMap.delete(markerId);
markerArr.splice(
markerArr.findIndex((p) => {
return p && p.equalsToID(markerId);
}),
1
);
} catch (error) {
responseObj.isSuccess = false;
responseObj.message = error.message;
responseObj.code = OSFramework.Maps.Enum.ErrorCodes.API_FailedRemoveMarker;
}

map && map.removeMarker(markerId);
markerMap.delete(markerId);
markerArr.splice(
markerArr.findIndex((p) => {
return p && p.equalsToID(markerId);
}),
1
);
return JSON.stringify(responseObj);
}

/**
* Removes all the markers of a given map.
*
* @export
* @param {string} mapId
* @return {*} {string}
*/
export function RemoveAllMarkers(mapId: string, removeFromMap = true): string {
const responseObj = {
isSuccess: true,
message: 'Success',
code: '200',
};
try {
if (removeFromMap) {
// First we try to remove the markers from the map.
MapManager.RemoveMarkers(mapId);
}

// Second remove the markers to destroy from local variables.
markerMap.forEach((storedMapId, storedMarkerId) => {
if (mapId === storedMapId) {
markerMap.delete(storedMarkerId);
markerArr.splice(
markerArr.findIndex((p) => {
return p && p.equalsToID(storedMarkerId);
}),
1
);
}
});
} catch (error) {
responseObj.isSuccess = false;
responseObj.message = error.message;
responseObj.code = OSFramework.Maps.Enum.ErrorCodes.API_FailedRemoveMarkers;
}

return JSON.stringify(responseObj);
}
}

Expand Down
Loading
Loading