Appearance
Code examples
Draw a floor plan GeoJSON using MapLibre
In this demo we use MapLibre GL JS to draw a detailed floor plan in GeoJSON format on the map that were loaded from the REST API.
TIP
If the floor plan is not geo-referenced it will appear at LatLng = [0, 0]
You can geo-reference your floor plan in the Editor
Load the GeoJSON geometry
Use the GeoJSON get request to load the geometries of the floor. Make sure to set the includeAllElements
param to include all elements of the layout.
ts
const publishableAccessToken = '<your-token>'
const floorId = '<your-floor-id>'
const endpoint = 'https://api.archilogic.com/v2'
const url = `${endpoint}/floor/${floorId}/geo-json?includeAllElements=true&pubtoken=${publishableAccessToken}`
fetch(url)
.then(res => res.json())
.then(drawMap)
.catch(console.error)
Create the map
Create your maplibre gl instance, with or without a map layer.
ts
import 'maplibre-gl/dist/maplibre-gl.css'
import maplibregl from 'maplibre-gl'
const container = document.getElementById('map')
const map = new maplibregl.Map({
// optionally add a map layer
container,
center: [0, 0],
zoom: 19,
maxZoom: 25,
maplibreLogo: false
})
Draw the GeoJSON on the map
To draw the GeoJSON features on the map, add it as a GeoJSON source and use separate layers to draw shapes and lines. The mapLibre style spec offers lots of options to either map to the default styles or adjust styling, depending on feature parameters.
ts
function drawMap(geoJson) {
const floor = geoJson.features.find(feature => feature.properties.resourceType === 'Floor')
map.setCenter(floor.properties.origin)
map.addSource('floorPlan', { type: 'geojson', data: geoJson })
// Add fills and lines, using the included 'simplestyle' styles from the geojson features
map.addLayer({
id: 'fills',
type: 'fill',
source: 'floorPlan',
filter: ['==', ['geometry-type'], 'Polygon'],
paint: {
'fill-color': [
// Apply a custom fill to spaces with certain property values
'match',
['get', 'program'],
'work',
'#54c072',
'meet',
'#ffab00',
// Default use the give fill color
['get', 'fill']
]
}
})
map.addLayer({
id: 'lines',
type: 'line',
source: 'floorPlan',
paint: { 'line-color': ['get', 'stroke'] }
})
}
Open code sample on StackBlitz
Update a layout via the operations API
With the following examples we explore the usage of the layout operations endpoint which allows updating or creating nodes in a layout. Each call will create a new layout revision based on the latest published revision.
It requires floor:update
scope.
WARNING
This endpoint is in beta stage. Breaking changes need to be expected.
SpaceUpdate
Update the attributes of a space node
Type
ts
type SpaceUpdateOperationJson = {
type: 'operation:spaceUpdate'
nodeId: string
value: {
name?: string
customId?: string
}
}
Example
Update the custom id of a space
ts
const operations = [
{
type: 'operation:spaceUpdate',
nodeId: '<space-id>',
value: {
customId: 'ABC-123'
}
}
]
const authorization = `AL-Secret-Token ${secretToken}`
await fetch(`https://api.archilogic.com/v2/layout/:layoutId/operations`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
authorization
},
body: JSON.stringify({ operations })
})
ElementUpdate
Type
ts
type ElementUpdateOperationJson = {
type: 'operation:elementUpdate'
nodeId: string
value: {
name?: string
customId?: string
position?: [number, number, number] // [x, y, z] right handed coordinate system, y is up
rotation?: number // rotation in degrees around the y axis
product?: string
}
}
Example
Change the product definition for one asset, the position and custom attribute value for another
ts
const operations = [
{
type: 'operation:elementUpdate'
nodeId: '<asset-id-1>'
value: {
product: '<new-product-id>'
}
},
{
type: 'operation:elementUpdate'
nodeId: '<asset-id-2>'
value: {
position: [2.5, 0, 0],
customAttributes: {
'<attribute-id>': 'attribute-value'
}
}
}
]
const authorization = `AL-Secret-Token ${secretToken}`
await fetch(`https://api.archilogic.com/v2/layout/:layoutId/operations`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
authorization
},
body: JSON.stringify({ operations })
})
ElementCreate
Place a new asset element at a given position
Type
ts
type ElementCreateOperationJson = {
type: 'operation:elementCreate'
value: {
type: 'element:asset'
id: string
name?: string
customId?: string
position: [number, number, number] // [x, y, z] right handed coordinate system, y is up
rotation?: number // rotation in degrees around the y axis
product: string
}
}
Example
Create a desk and a chair. Product geometries are facing z+. Make sure each new element gets a newly created uuid v4.
ts
const operations = [
{
type: 'operation:elementCreate'
value: {
type: 'element:asset',
id: '<new-uuid>',
position: [0, 0, 0],
product: '<desk-product-id>'
}
},
{
type: 'operation:elementCreate'
value: {
type: 'element:asset',
id: '<new-uuid>',
position: [0, 0, 0.6], // move the desk in front of the desk
rotation: 180, // make the chair face the desk
product: '<chair-product-id>'
}
}
]
const authorization = `AL-Secret-Token ${secretToken}`
await fetch(`https://api.archilogic.com/v2/layout/:layoutId/operations`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
authorization
},
body: JSON.stringify({ operations })
})
Access private resources from front end
The following example demonstrates how to access a private floor from the front end using temporary access tokens and the floor plan engine.
Get the temporary access token
Create an API on your back-end to retrieve temporary access tokens
js
app.post('/api/get-access-token', async (req, res) => {
// https://developers.archilogic.com/space-api/v2/introduction.html#temporary-access-token
const apiUrl = 'https://api.archilogic.com/v2/temporary-access-token/create'
const { body } = await got.post(apiUrl, {
headers: {
Authorization: `AL-Secret-Token ${process.env.SECRET_TOKEN}`
},
json: {
scopes: [{ resource: 'floor', action: 'readPrivate' }],
durationSeconds: 3600
},
responseType: 'json'
})
res.send(body)
})
Use the temporary access token
Make your front end call that API and use the token then via the loadScene method
js
function getTemporaryAccessToken() {
return fetch(`/api/get-access-token`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
scopes: [{ resource: 'floor', action: 'readPrivate' }]
})
}).then(response => response.json())
}
// authorization contains the temporary access token
// expiresAt can be used to check on when you need to request an new token
const { authorization, expiresAt } = await getTemporaryAccessToken()
const floorId = 'bc78475e-0236-4b8d-9d7e-b4f46cd3f6fa'
const container = document.getElementById('hello-plan')
const floorPlan = new FloorPlanEngine({ container })
await floorPlan
.loadFloorById(floorId, { temporaryAccessToken: { authorization, expiresAt } })
.catch()
Setup webhooks
Webhooks are available from the following API endpoints: https://api.archilogic.com/v2/webhook
Before using webhooks, a destination endpoint must be set up which supports POST requests from the Archilogic domain.
Currently webhooks are supported for 2 resources: floor
with available actions
ts
type FloorAction = 'created' | 'updated' | 'deleted' | 'archived' | 'unarchived'
and order
with available actions
ts
type OrderAction = 'created' | 'rejected' | 'completed'
Webhook payload example:
ts
{
"type": "event",
"url": "https://webhook.site/179b5241-ab4f-42df-bdb4-7f3154c9177a",
"resource": "floor",
"action": "created",
"createdAt": "2023-11-22T13:44:10.255Z",
"data": {
"id": "abaaea05-5070-4c77-bd6c-4f26c5b71340"
}
}
Create webhooks
Webhook objects must include the following required fields:
ts
{
active: boolean // webhook state
action: WebhookActions // FloorAction | OrderAction
resource: WebhookResources // 'floor' | 'order'
url: string // format like 'https://{your_destination_url}'
}
Example:
ts
const authorization = `AL-Secret-Token ${secretToken}`
await fetch(`https://api.archilogic.com/v2/webhook`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
authorization
},
body: JSON.stringify({
active: true,
action: 'updated', // FloorAction | OrderAction
resource: 'floor', // 'floor' | 'order'
url: 'https://example.com'
})
})
Get all webhooks
Example:
ts
const authorization = `AL-Secret-Token ${secretToken}`
const webhooks = await fetch(`https://api.archilogic.com/v2/webhook`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
authorization
}
})
Get webhook by ID
Url path parameter :webhookId
can be taken from the GET request.
ts
const webhook = await fetch(`https://api.archilogic.com/v2/webhook/:webhookId`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
authorization
}
})
Update webhooks
Any of the webhook object's parameters could be passed to the request body.
Url path parameter :webhookId
can be taken from the GET request.
Example:
ts
const authorization = `AL-Secret-Token ${secretToken}`
// Deactivate webhook
await fetch(`https://api.archilogic.com/v2/webhook/:webhookId`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
authorization
},
body: JSON.stringify({
active: false
})
})
// Change webhook destination url
await fetch(`https://api.archilogic.com/v2/webhook/:webhookId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
authorization
},
body: JSON.stringify({
url: 'https://example1.com'
})
})
Delete webhooks
Url path parameter :webhookId
can be taken from the GET request.
Example:
ts
const authorization = `AL-Secret-Token ${secretToken}`
await fetch(`https://api.archilogic.com/v2/webhook/:webhookId`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
authorization
}
})