7. Import and Create New POIs

Points of interest (POIs) can be imported from UNL Studio into the JS web application using our SDK. You can also create a new POI which will get saved in UNL Studio.

Import POI#

Create a new method in unlApi.js which uses the SDK's function to retrieve a record.

export const getPoi = (projectId, poiId) => {
return unlApi.recordsApi.getById(projectId, poiId);
};

Add a new file (we called it loadMapImages.js) with a function that imports images which will represent POI markers on the map.

import MarkerIcon from "../icons/marker_icon_satellite.png";
const MAP_IMAGES = [
{
name: "marker_icon_satellite",
icon: MarkerIcon,
},
];
export const loadMapImages = (map) => {
MAP_IMAGES.forEach((img) => {
map.loadImage(img.icon, (error, res) => {
if (error) {
return;
}
map.addImage(img.name, res);
});
});
};

Call this method in index.js.

loadMapImages(map);

Next, add a function which transforms a geohash into an array of coordinates (latitude and longitude) using the unl-core's decode method.

export const geohashToCoordinates = (geohash) => {
const geohashPoint = UnlCore.decode(geohash);
return [geohashPoint.lon, geohashPoint.lat];
};

Then, add a method to display a marker on the map, which will mark the location of a POI.

const addPoiMarker = (map, poiGeohash, poiName, poiId) => {
if (map.getSource(`poi_${poiId}`)) {
return;
}
map.addSource(`poi_${poiId}`, {
type: "geojson",
data: {
type: "Feature",
geometry: {
type: "Point",
coordinates: geohashToCoordinates(poiGeohash),
},
properties: {
name: poiName,
},
},
});
map.addLayer({
id: `poi_${poiId}`,
type: "symbol",
source: `poi_${poiId}`,
layout: {
"icon-image": "marker_icon_satellite",
"icon-size": 0.5,
"icon-offset": [0, -40],
"text-font": ["Fira GO Regular"],
"text-field": poiName,
"text-size": 14,
"text-anchor": "bottom",
"text-offset": [0, -3.5],
"icon-allow-overlap": true,
"text-allow-overlap": true,
},
});
};

Create another method to render the POI, which adds the POI marker on the map, highlights its UNL cell and interpolates to its location on the map.

export const renderPoi = (map, poi) => {
const poiId = poi.recordId;
const poiCoordinates = poi.geojson.geometry.coordinates;
const poiName = poi.geojson.properties.name;
const poiGeohash = poi.geohash;
addPoiMarker(map, poiGeohash, poiName, poiId);
updateCell(map, { lat: poiCoordinates[1], lng: poiCoordinates[0] });
map.flyTo({ center: poiCoordinates, zoom: 18 });
};

Add two new entries in the .config file: PROJECT_ID and IMPORTED_POI_ID. These values will be passed to the method we call from the SDK. The PROJECT_ID will identify the project you have created in the UNL Studio app from which you want import or contribute with data. The IMPORTED_POI_ID will find the POI you want to import from UNL Studio into the JS application.

export default {
MAPBOX_TOKEN: "YOUR-MAPBOX-TOKEN",
HERE_MAPS_API_KEY = "YOUR-HERE-MAPS-API-KEY",
UNL_API_KEY: "YOUR-UNL-API-KEY",
PROJECT_ID = "YOUR-PROJECT-ID",
IMPORTED_POI_ID = "YOUR-IMPORTED-POI-ID"
}

Replace YOUR-PROJECT-ID and YOUR-IMPORTED-POI-ID in the .config file with valid values from your project in UNL Studio.

You can obtain the project id by going to the project's settings page.

To get the id of the POI you want to import, open the the project from the projects page by clicking on it, then select the POI you want to import directly on the map or from the library. When the Properties tab appears, copy the ID.

Then, add the method that initiates the request to import the POI and renders it on the map.

export const importPoiFromStudio = async (map) => {
const projectId = config.PROJECT_ID;
const poiId = config.IMPORTED_POI_ID;
const poi = await getPoi(projectId, poiId);
renderPoi(map, poi);
};

The next stept is to add a new button in the menu action sheet component (ActionSheet.js) inside the <div> element.

<button id="import-poi-button" class="action-sheet-button">
Import POI from Studio
</button>

Add a style for the button in styles.css.

.action-sheet-button {
padding: 12px;
margin-bottom: 12px;
}

Finally, call the method to import the POI in index.js when the Import POI from Studio button added previously is clicked.

document.getElementById("import-poi-button").addEventListener("click", () => {
importPoiFromStudio(map);
});

Now, when the Import POI from Studio button is clicked, the point of interest should be imported from UNL Studio and visible on the map.

Create a new POI#

Add another button in the menu action sheet component (ActionSheet.js) inside the <div> element for creating a new poi. Add an input field as well, to be able to insert a name for the POI.

<button id="create-poi-button" class="action-sheet-button">Create new POI</button>
<form>
<input id="poi-name-input" class="input" value="POI name" placeholder="POI name"></input>
<input id="submit" type="submit" class="input" value="Create POI">
</form>

Add a new style for the input elements in the styles.css file.

.input {
display: none;
padding: 12px;
margin-bottom: 12px;
}

Create a new method in unlApi.js which uses the SDK's function to create a new POI.

export const createPoi = (projectId, poiGeojson) => {
return unlApi.recordsApi.create(projectId, poiGeojson);
};

Next, add a method that at first checks whether a cell is selected on the map. If a cell is selected, it uses UNL core library methods to calculate the coordinates of the cell, builds the POI geojson object using those coordinates and the name provided for the POI in the input field. Lastly, it calls the previous method to create the POI and then renders it on the map.

Note Make sure YOUR-PROJECT-ID from .config is replaced with a valid project id from UNL Studio.

export const createNewPoi = async (map) => {
const projectId = config.PROJECT_ID;
const cellCoordinates = map.getSource("unlCell")._data.geometry.coordinates;
if (!cellCoordinates.length) {
alert("Select the POI location on the map!");
} else {
const cellCorner =
map.getSource("unlCell")._data.geometry.coordinates[0][1];
const poiGeohash = UnlCore.encode(
cellCorner[1],
cellCorner[0],
9 //geohash precision
);
const poiCoordinates = geohashToCoordinates(poiGeohash);
const poiGeojson = {
type: "Feature",
geometry: { type: "Point", coordinates: poiCoordinates },
properties: {
name: document.getElementById("poi-name-input").value,
feature_type: "PointOfInterest",
},
};
const poi = await createPoi(projectId, poiGeojson);
renderPoi(map, poi);
}
};

Toggle the input field and the submit button in index.js when the create POI button is clicked and call the previous method when the submit button is clicked.

document.getElementById("create-poi-button").addEventListener("click", () => {
toggleInputField();
toggleSubmitButton();
});
document.getElementById("submit").addEventListener("click", (event) => {
event.preventDefault();
createNewPoi(map);
});

Now, when the Create POI from Studio button is clicked and a POI name is provided, the point of interest should be created and visible both on the map and in UNL Studio.