Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@wework/floormap-sdk

Package Overview
Dependencies
Maintainers
30
Versions
301
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@wework/floormap-sdk

[![CircleCI](https://circleci.com/gh/WeConnect/floormap-sdk/tree/master.svg?style=svg&circle-token=679c562fecb8e63401d492b82329d3d17a8c3430)](https://circleci.com/gh/WeConnect/floormap-sdk/tree/master) [![Coverage Status](https://coveralls.io/repos/github

  • 2.0.1-v2.455
  • npm
  • Socket score

Version published
Weekly downloads
36
increased by1100%
Maintainers
30
Weekly downloads
 
Created
Source

FloorMap SDK

CircleCI Coverage Status

Installation

NPM

You might need npm login

You will need to be logged in to install a dependency. Execute npm login and use the username, password, and e-mail found in 1Password under npmjs (dev-team).

npm install @wework/floormap-sdk

# Yarn
yarn add @wework/floormap-sdk

And import the SDK with:

import * as FloorMap from '@wework/floormap-sdk'

// you also can cherry-pick import a module from sdk by
// import { Manager } from '@wework/floormap-sdk'

UMD

By using the UMD format, You can access the SDK via FloorMap variable.

<script type="text/javascript" src="floormap-sdk.min.js"></script>

In JavaScript

const manager = new FloorMap.Manager({
  /* ... */
})
const floorMap = manager.createFloorMap(target, {
  /* ... */
})

Please see example/sample for UMD usage

Getting started

Authentication

Before create and render a floor map, you need to authenticate with MilkyWay service by creating Manager object and providing a credential.

To request for an appId/appSecret, kindly email tech-sg@wework.com with the subject Request for FloorMap SDK credentials and a brief explanation of its intended purpose.

const manager = new FloorMap.Manager({
  appId: /* App ID */,
  appSecret: /* App Secret */,
  baseUrl: 'https://occupancy-api.phoenix.dev.wwrk.co/v2',
})

Then, use .authenticate function to start authenticating

manager
  .authenticate()
  .then(mwAccessToken => {
    // Authenticated
  })
  .catch(e => {
    // Authenticating Error
  })

Spaceman JWT Token

Spaceman JWT Token is supported directly by the SDK. You can pass Spaceman JWT while constructing manager instance.

const manager = new FloorMap.Manager({
  appId: /* App ID */,
  appSecret: /* App Secret */,
  baseUrl: 'https://occupancy-api.phoenix.dev.wwrk.co/v2',
  spacemanToken: /* Spaceman JWT */
})

Store result mwAccessToken for futher usage

authenticate function resolves mwAccessToken object. You can store the access token object for further use and provide the token object next time you're creating a manager.

manager.authenticate().then(mwAccessToken => {
  // Authenticated
  localStorage.setItem('MW_TOKEN_STORAGE_KEY', JSON.stringify(mwAccessToken))
})

// Next time
const mwAccessToken = JSON.parse(localStorage.getItem('MW_TOKEN_STORAGE_KEY'))
const manager = new FloorMap.Manager({
  /* ... */
  mwAccessToken: mwAccessToken,
})

After this point, the manager instance is ready to create and render the floormap.

Create a floor map

First, create an empty HTML element for the map to render itself.

<body>
  <section id="container"></section>
</body>

Next, Use manager instance to create and render a floormap and provide target element.

const target = document.getElementById('container')
const floorMap = manager.createFloorMap(target, options)

FloorMap options

  • options.backgroundColor - Background color of the map
  • options.deskLayout - Show desk layout
  • options.deskInteractable - Allow desk/chair to be interactable

After creating a floor map, Call render function with buildingId and floorId to render a floor map into the screen (if floorId is omitted, the lowest floor of the building will be rendered)

// Render Map
floorMap
  .render({
    buildingId: 'b308b94c-bca6-4318-b906-1c148f7ca183',
    /* floorId: '' */
  })
  .then(result => {
    console.log(result)
    // { building, floor, spaces, objects, options}
  })
  .catch(e => {
    console.log(e.data)
    // { building, floor? }
    console.log(e.options)
  })

Final source code

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>FloorMap</title>

    <style>
      body {
        margin: 0;
        padding: 0;
      }
      #main {
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
      }
    </style>
  </head>
  <body>
    <div id="container"></div>

    <script src="../../dist/floormap-sdk.js"></script>
    <script>
      async function renderMap() {
        const target = document.getElementById('container')
        let currentId = null

        // Credential
        const manager = new FloorMap.Manager({
          appId: /* APP_ID */,
          appSecret: /* APP_SECRET */,
          baseUrl: 'https://occupancy-api.phoenix.dev.wwrk.co/v2',
        })

        // Authenticating
        await manager.authenticate()

        // Create Floor Map
        const floorMap = manager.createFloorMap(target, {
          backgroundColor: '#303030',
        })

        // Render Floor
        floorMap.render({
            buildingId: 'b308b94c-bca6-4318-b906-1c148f7ca183',
        })
      }

      renderMap()
    </script>
  </body>
</html>

Map Event

You can subscribe to user interaction and data event on the map by using addEventlistener and removeEventListener to remove a listener on the floor map instance.

// Mouse moveover a space
floorMap.addEventListener('mouseover', event => {})

// Mouse moveout a space
floorMap.addEventListener('mouseout', event => {})

// On click a space
floorMap.addEventListener('click', event => {})

// When user moving mouse cursor on the map
floorMap.addEventListener('mousemove', event => {})

// When physical data change
floorMap.addEventListener('datachange', event => {})

// Renderer event (mostly use for debugging purpose)
floorMap.addEventListener('onerror', event => {})
floorMap.addEventListener('onrender', event => {})

An event object will contain:

  • type - Event type
  • payload - An informations of the interaction
  • data - Space data, If an interaction is on space/object

Example payload

{
  "type": "click",
  "payload": {
    "id": "cdc9c84e-d092-11e7-9d13-0642b0acf810",
    "point": { "x": 14.237798863250575, "y": 74.47726859122804, "z": -3 },
    "mousePos": { "x": 530, "y": 203 }
  },
  "data": {
    /* Space Data */
  }
}

Styling

Room and Object

Room / Space
Supported properties
propertytypedefaultnote
wallColor, color`stringnumber`
wallHeight, heightnumberheight will take precedence
wallTexture, textureTextureOptionstexture will take precedence, see Types
wallOffsetnumber
wallCornerRadiusnumber
wallOutline`stringnumber`
wallOpacitynumber
wallSideFRONT,BACK,DOUBLE
wallVisibleboolean
wallElevationnumber
baseColor`stringnumber`
baseHeightnumber
baseTextureTextureOptions
baseOffsetnumber
baseCornerRadiusnumber
baseOutline`stringnumber`
baseOpacitynumber
baseSideFRONT,BACK,DOUBLE
baseVisibleboolean
baseElevationnumber
titleTitleNodeOptions
titleDisplayMode`'fitSpace''hideOnOverflow''default'`
interactableboolean
visibleboolean
Object - Chiar, Table, and Furniture
Support Property
PropertyTypeNote
heightnumber
elevationnumber
titleTitleNodeOptionssee Types
interactableboolean
visibleboolean
scale`numberPoint3D`
rotationObjectRotationOptionssee Types
positionPoint2D
gltfGLTFOptionssee Types
Types
type Point2D = {
  x: number
  y: number
}

type Point3D = {
  x: number
  y: number
  z: number
}

type TitleNodeOptions = {
  text?: string
  fontSize?: number
  font?: any
  textColor?: string
  textAlignment?: TextAlignment
  lineSpacing?: number

  icon?: any
  iconColor?: string
  iconScale?: number
  iconPosition?: IconPosition

  backgroundColor?: string | number | undefined
  borderWidth?: number
  borderColor?: string | number
  padding?: { x: number; y: number }
  cornerRadius?: number

  billboard?: boolean
  visible?: boolean
  offset?: Point2D
  position?: Point2D
  elevation?: number
}

type ObjectRotationOptions = {
  x: number
  y: number
  z: number
  metric: RotationMetric
}

type GLTFOptions = {
  src?: any
  scale?: number
  rotation?: Point3D
}

type NodeConfiguration = {
  // Common Properties (Both Room and Object)
  color?: string
  interactable?: boolean
  visible?: boolean
  title?: TitleNodeOptions

  // Room Properties
  wallColor?: string | number
  wallHeight?: number
  wallOffset?: number
  wallCornerRadius?: number
  wallOutline?: string | number
  wallOpacity?: number
  wallSide?: string //Side
  wallVisible?: boolean
  wallTexture?: TextureOptions
  wallElevation?: number

  baseColor?: string | number
  baseHeight?: number
  baseOffset?: number
  baseCornerRadius?: number
  baseOutline?: string | number
  baseOpacity?: number
  baseSide?: string // Side
  baseVisible?: boolean
  baseTexture?: TextureOptions
  baseElevation?: number
  // We don't support fitting title for object
  titleDisplayMode?: string | 'fitSpace' | 'hideOnOverflow' | 'default'

  //
  // Object Properties
  //
  gltf?: {
    src?: any
    scale?: number
    rotation?: Point3D
  }
  height?: number
  outline?: string | number
  offset?: number
  cornerRadius?: number
  opacity?: number
  scale?: number | Point3D
  rotation?: Partial<{
    x: number
    y: number
    z: number
    metric: RotationMetric
  }>
  position?: Point2D
  elevation?: number
}

Confiugre Space (Declarative)

Providie a function to the SDK to configure each space/object. The function will get call by each space/object to retrieve a configuration.

configureStyle(space: Space | SpaceObject, prevConfig: ): NodeConfiguration

example
floormap.configureStyle((spaceOrObjectPayload) => {
  if (space.subType === 'OFFICE') {
    return { color: 'red' }
  }

  return {}
})

configureStyle will automatically get called by the Floormap to retrieve a configurtion for a space, there are some events will trigger the function get called:

  • When a space get invalidated via .invalidate()
  • When a space data get updated through .updateSpace()
  • When a related space get updated (through .updateSpace()). For example, A space get updated, both the space and all objects inside will get called.
Reload Style

invalidate(spaceOrId?: { id: string }[] | id[])

Since configureStyle will get called automatically by the Floormap. In case you want to force the floormap to reload particular space or every spaces.

Passing undefined will cause the floormap reload every spaces.

example
  • Use invalidateSpace to highlight selecting space
let selectedUUID = ''
floormap.configureStyle(spaceOrObject => {
  if (space.uuid === selectedUUID) {
    return { color: 'red' }
  }

  return { color: 'blue' }
})

floormap.addEventListener('click', event => {
  if (event.data) {
    selectedUUID = event.data.uuid
    this.floormap.invalidate(selectedUUID)
  } else {
    this.floormap.invalidate(selectedUUID)
    selectedUUID = ''
  }
})
Multiple configurareSpace functions

You can register multiple configureStyle functions.

The return value of previous function will be passing to next function as second parameters and The return value from each function will get merged with the previous one.

example
floormap.configureStyle((space, prevConfig) => {
  // The default configuration
  console.log(prevConfig)

  return { color: 'red' }
})

floormap.configureStyle((space, prevConfig) => {
  // The previous function return { color: 'red' }
  // { ...defaultConfiguration, color: 'red' }
  console.log(prevConfig)

  return { visible: true }
})

// The final result for every spaces will be
// {
//  ...default,
//  color: 'red',
//  visible: true
// }

Style overriding

Apply style

Apply style to a given space uuid

You can use this function to override a style from configureStyle

applyStyle(
  {
    id: string,
    style: object,
    key: string,
  },
  animated?: boolean,
  duration?: number,
  completion?: function
)
example
floorMap.applyStyle({
  id: 'space-uuid-1',
  style: { color: 'red' },
  key: 'highlight',
})

// animated
floorMap.applyStyle(
  {
    id: 'space-uuid-1',
    style: { color: 'red' },
    key: 'highlight',
  },
  true,
  0.2,
  () => {
    console.log('animation finished')
  }
)

// Bulk apply
floorMap.applyStyle([
  { id: 'space-uuid-1', style: { color: 'red' }, key: 'highlight' },
  { id: 'space-uuid-2', style: { color: 'red' }, key: 'highlight' },
])

Revert style

revertStyle(
  { id: string, key: string } | { id: string, key: string }[],
  animated?: boolean,
  duration?: number,
  completion?: function
)

Revert style with matched key to a given space uuid.

Note. If the key is not given, the last applied style will get reverted

example
floorMap.revertStyle({ id: 'space-uuid-1', key: 'highlight' })

// Bulk revert
floorMap.revertStyle([
  { id: 'space-uuid-1', key: 'highlight' },
  { id: 'space-uuid-2', key: 'highlight' },
])

Reset style

Reset all applied styles from a given space uuid

resetStyle(
  stylesWithId: { id: string } | { id: string }[],
  animated?: boolean,
  duration?: number,
  completion?: function
)
example
flooMap.resetStyle({ id: 'space-uuid-1' })

// Bulk reset
flooMap.resetStyle([{ id: 'space-uuid-1' }, { id: 'space-uuid-2' }])

Style is Stack

Calling applyStyle will push style object into the stack. If we call applyStyle with a different key, the later style will be placed on top of the stack of overwrite property in previous items in the stack.

Also, we call applyStyle with a key that already exists in the stack, that style with the same key will be replaced with new style instead of merging and stay in the current position in the stack instead of bumping to the top

The style from configureStyle is a base style and won't affected by revertStyle and resetStyle

For example:

// Stack
//
// - Base: { color: 'yellow' } - from configureStyle
//
// result style: { color: 'yellow'}
floormap.configureStyle(() => ({ color: 'yello' })

// Stack
//
// - Base: { color: 'yellow' } - from configureStyle
// - somekey:{ color: 'red', opacity: 0.8 }
//
// result style: { color: 'red', opacity: 0.8  }
floorMap.applyStyle({ id: spaceUUID, style: { color: 'red', opacity: 0.8 }, key: 'somekey' })

// Apply style with new key `somekey`
//
// Stack
//
// - Base: { color: 'yellow' } - from configureStyle
// - otherkey: { opacity: 0.5 }
// - somekey: { color: 'red', opacity: 0.8 }
//
// result style: { color: 'red', opacity: 0.5 }
floorMap.applyStyle({ id: spaceUUID, style: { opacity: 0.5 }, key: 'otherkey' })

// Apply style to existing key `somekey`
//
// Stack
//
// - Base: { color: 'yellow' } - from configureStyle
// - otherkey: { opacity: 0.5 }
// - somekey: { color: 'red', opacity: 1.0 }
//
// result style: { color: 'red', opacity: 0.5 }
floorMap.applyStyle({ id: spaceUUID, style: { color: 'red', opacity: 1.0 }, key: 'somekey' })

// We revert 'somekey' style
// Stack
//
// - Base: { color: 'yellow' } - from configureStyle
// - otherkey: { opacity: 0.5 }
//
// result style: { opacity: 0.5 }
floorMap.revertStyle({ id: spaceUUID, key: 'somekey' })

// Remove all style in stack
//
// - Base: { color: 'yellow' } - from configureStyle
//
// result style: { color: 'yellow' }
floorMap.resetStyle({ id: spaceUUID })

Combine event and style to create a user interaction feedback

// - Event Handling
floorMap.addEventListener('onmouseover', event => {
  const { payload, data } = event

  // Highlight Space
  floorMap.applyStyle({
    id: payload.id,
    style: { color: 'aqua' },
    key: 'HOVER',
  })
})

floorMap.addEventListener('onmouseout', event => {
  const { payload, data } = event

  // unhighlight Space
  floorMap.applyStyle({ id: payload.id, style: {}, key: 'HOVER' })

  // You also can use revertStyle
  // floorMap.revertStyle({ id: payload.id, key: 'HOVER' })
  // or floorMap.resetStyle({ id: payload.id })
})

Map lifecycle hooks

Map lifecycle gives an opportunity to you to start loading data along with when the map starts loading data, modify physical data or apply a style to an object before the map start to render an object into the screen.

onLoad -> didLoad -> onRender -> didRender

Lifecycle function will get called with the following parameters:

  • building A building object
  • floor A floor object
  • options Passing options from .render and .load
  • errors If any errors occurred

onLoad

onLoad hook allows you to prepare your data while map starts loading their data. You can make the map to be waiting for your data to be loaded before starting rendering into the screen by returning promise from the function.

Example
const unsubscribe = floorMap.onLoad(
  ({ building, floor, spaces, objects, options, errors }) => {
    // Do something
  }
)

If a promise gets returned from the function, the map will wait until the promise gets resolved before start rendering.

const unsubscribe = floorMap.onLoad(
  ({ building, floor, spaces, objects, options, errors }) => {
    return fetch(/* ... */)
  }
)

didLoad

didLoad will get called when the map finished loading the data (including returned promises from onLoad function), and the Promise from onLoad(s) has been resolved. You can use this function to modify the physical data in the map.

Example
const unsubscribe = floorMap.didLoad(
  ({ building, floor, spaces, objects, options, errors }) => {
    // Change room type
    floorMap.updateData(spaceeUUID, { roomType: 'Private Large Office' })
  }
)

onRender

onRender will get called during the map is preparing to render object for rendering into the screen, but not yet rendered into the screen. This function gives you an opportunity to apply a style to spaces.

Example
const unsubscribe = floorMap.onRender(
  ({ building, floor, spaces, objects, options, errors }) => {
    floorMap.applyStyle({
      id: spaceUUID,
      style: { color: 'aqua' },
      key: 'occupancy-style',
    })
  }
)

didRender

didRender will get called when the map finished rendering objects into the screen. You can add custom overlay into the map on this lifecycle (We will talk about map overlay in next section)

Example
const unsubscribe = floorMap.didRender(
  ({ building, floor, spaces, objects, options, errors }) => {
    const imageOverlay = new ImageOverlay(noteIcon, {
      style: {
        width: 3,
        height: 3,
      },
    })

    imageOverlay.spaceUUID = spaceUUID
    floorMap.addObject(imageOverlay)
  }
)

onError

Get a call when an error occurred during loading or rending

Example
const unsubscribe = floorMap.onError(({ options, errors }) => {
  // Change room type
  floorMap.updateData(spaceeUUID, { roomType: 'Private Large Office' })
})

Unsubscribe

Call returned function to remove a listener.

// Subscribe to onLoad
const unsubscribe = floorMap.onLoad(() => {})

// Unsubscribe
unsubscribe()

Map Data

Preload Building / Floor Data

Pre-load and cache building/floor data in local. This function won't render floormap into the screen

floorMap.load(options: Object): Promise<Result>

Options:

  • buildingId - Physical / System Building UUID
  • floorId - Physical / System Floor UUID
  • autoLoadFloor - Auto load lowerest floor in building if floorId is omitted
  • skipCache - Skip local building/floor cache in the SDK

Result:

  • building - Building object
  • floor - Floor object
  • spaces - Space objects inside floor
  • objects - Objects (Chair, Table) inside floor

Render Floormap

Load and render floormap into the screen

floorMap.render(options: Object): Promise<Result>

Options:

  • buildingId - Physical / System Building UUID
  • floorId - Physical / System Floor UUID
  • autoLoadFloor - Auto load lowerest floor in building if floorId is omitted
  • skipCache - Skip local building/floor cache in the SDK

Result:

  • building - Building object
  • floor - Floor object
  • spaces - Space objects inside floor
  • objects - Objects (Chair, Table) inside floor

Reload Map

Reload and re-render current floor

floorMap.reload(options: Object): Promise

Options:

  • skipCache: Skip local building/floor cache in the SDK

Get Spaces

Returns all spaces and objects in current floor (if floorId is omitted)

floorMap.getSpaces(floorId: string?): Space|SpaceObject[]

Update Data

Update Space/SpaceObject data by its uuid. This will trigger on('datachange') event.

floorMap.updateData(uuid: string, data: object?)

Map State

Current Building

Returns current building

floorMap.getCurrentBuilding(): Building

Current Floor

Returns current floor

floorMap.getCurrentBuilding(): Floor

Current floor map state

Returns current status of the floor map

floorMap.getCurrentState(): string

State values:

  • IDLE - Floor map is ready to render
  • LOADING - Loading data
  • RENDERING - Rendering map
  • RENDERED - Floor map is displayed on the screen
  • TERMINATED - Floor map is terminated from teardown call
  • ERROR - Have an error during loading/rendering

Camera control

Fit Content

Fit camera to the map content

floorMap.fitContent({ padding: number })

Example
floorMap.fitContent({ padding: 20 })

setZoomLevel

Set the zoom level

floorMap.setZoomLevel(zoomLevel: number)

getZoomLevel

Get current zoom level of the map.

floorMap.getZoomLevel(): number

setMinZoomLevel

Set minimum zoom level of the map.

floorMap.getMinZoomLevel(min: number)

setMaxZoomLevel

Set maximum zoom level of the map.

floorMap.getMaxZoomLevel(max: number)

setCenter

Set the camera rotation view angle

floorMap.setCenter(options: {
    x: number
    y: number
    z?: number
    animated?: boolean
    duration?: number
    onComplete?: () => {}
  }
Example
floorMap.setCenter({ x: 2, y: 0, z: 5 })

setRotation

Rotate the map

floorMap.setRotation(azimuthAngleDegree: number, horizontalDegree: number)

  • azimuthAngleDegree Vetical (y-axis) rotation degree
  • polarAngleDegree Horizontal (x-axis) rotation degree
Example
floorMap.setRotation(rotationDegree, polarAngle)

setMinPolarAngle

Set min polar angle (x-axis) that the camera can be rotated by user

Value is in degree

setMinPolarAngle(min: number)

setMaxPolarAngle

Set max polar angle (x-axis) that the camera can be rotated by user

Value is in degree

setMaxPolarAngle(max: number)

setMinAzimuthAngle

Set min azimuthAngle (y-axis) that the camera can be rotated by user

Value is in degree

setMinAzimuthAngle(min: number)

setMaxAzimuthAngle

Set max azimuthAngle (y-axis) that the camera can be rotated by user

Value is in degree

setMaxAzimuthAngle(max: number)

setMinZoomLevel

Set minimum zoom level of the map.

floorMap.getMinZoomLevel(min: number)

setMaxZoomLevel

Set maximum zoom level of the map.

floorMap.getMaxZoomLevel(max: number)

Object Overlay

WeMaps Renderer's Render Node

FloorMap SDK is fully compatiable with WeMaps Renderer's Nodes. You can construct a WeMaps Renderer Node and use it directly with the SDK.

import { CircleNode } from '@wework/wemaps-renderer'

const circleNode = new CircleNode({
  extrude: 12, // If extrude Circle will be in 3D otherwise it will be a 2D Circle
  color: 'red',
  radius: 8,
  position: { x: 0, y: 0, z: 0 },
})

floorMap.addObject(circleNode)

The documentation on WeMaps Renderer's render nodes can be found on WeMaps Renderer repository

Add Object

floorMap.addObject(overlay)

// You can add multiple objects as once by passing array of objects
floorMap.addObject([overlay, overlay2])

Remove Object

FloorMap overlay/object can be removed by calling .removeObject with object or id

floorMap.removeObject(overlay)
floorMap.removeObject(id)

// Remove multiple objects as once
floorMap.removeObject([overlay1, overlay2])
floorMap.removeObject([id1, id2])

Session

getAccessToken

Returns an access token of the current session

Example
const mwAccessTokenObj = manager.session.getAccessToken()

setAccessToken

Set new access token to the current session

Example
manager.session.setAccessToken(mwAccessTokenObj)

setSpacemanToken

Set new spaceman JWT token and re-authenticate

Example
const mwAccessTokenObj = await manager.session.setSpacemanToken(jwt)

Separate of concern with extension

Create a extension

We can use lifecycle hooks like onLoad pre-loading our data and apply a style with applyStyle base on data we have. In some case, we want to separate to logic of data loading and styling from main application logic, make it reusable, plug-n-play, or even distribute our logic as a standalone package, and This is where the extension come to play.

To create an extension, create a class and extend the Extension base class. Then override required functions.

  • getId() - required - ID/Name of the extension, the name has to be unique across all extension
  • getDescription() - Description of the extension
  • onRegister() - This function will get called when register the extension to a map
  • onRemove() - This function will get called when unregister the extension from a map
  • getDataById(spaceUUID: string) - Provide additional data for to space/object based on UUID - Deprecated Use getDataBySpace instead
  • getDataBySpace(space: Space) - Provide additional data for to space/object

Inside extension class, you can access the map that extension has been registered to via getMap(). This allows you to listen and fetch database on the map lifecycle such as onLoad and onRender.

In the example, We're going to create CityWeatherExtension to fetch weather database on the current location of the building.

class CityWeatherExtension extends Extension {
  constructor() {
    super()
    this.data = undefined
    this.currentCity = ''
  }
  getId() {
    return 'cityweather'
  }
  getDescription() {
    return 'Awesome City Weather: Provide Weather information based on building location'
  }
  onRegister() {
    this.unsubscribeOnLoad = this.getMap().onLoad(async ({ building }) => {
      if (this.currentCity === building.city) {
        return
      }

      this.currentCity = building.city

      const res = await fetch(
        `https://api.openweathermap.org/data/2.5/weather?q=${this.currentCity}`
      )
      const data = await res.json()
      this.data = data
      return
    })
  }

  onRemove() {
    this.data = undefined
    this.unsubscribeOnLoad()
  }

  getDataBySpace(space) {
    // This function will get called when the map ask for data based on spaceUUID
    // such as onclick event

    // For this example
    // When click on space, the payload will contains field
    // {
    //  ...,
    //  cityweather: 'Room ...: ...F'
    // }
    return `Room ${space.number}: ${this.getTemperature()}F`
  }

  // Custom function provided by extension
  getTemperature() {
    // https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22
    return this.data.main.temp
  }
}

Register extension

Register extension by calling registerExtension on FloorMap instance

const weatherExtension = new CityWeatherExtension()

floorMap.registerExtension(weatherExtension)

Now when you switch a building, the extension will fetch the weather data for the user. Also when you click on any space, the event payload will include the data from the extension (which come from getDataById).

floorMap.addEventListener('onclick', event => {
  if (event.data) {
    console.log(event.data.cityweather)
  }
})

Access extension instance through floormap

// extensionId is the value returned from getId()
floorMap.extensions[extensionId]
floorMap.getExtension(extensionId)

// Example
floormap.extensions.cityweather
floormap.getExtension('cityweather')

Remove extension

Remove extension from floormap

floorMap.removeExtension(weatherExtension)
floorMap.removeExtension('cityweather')

Built-in extensions

Please see: https://github.com/WeConnect/floormap-extensions


API References

We provide API references documentation generated via jsdoc

# Clone
git clone git@github.com:WeConnect/floormap-sdk.git
cd floormap-sdk

yarn jsdoc

After that, the API doc will be in the docs folder.


Demo application

React application

# Clone
git clone git@github.com:WeConnect/floormap-sdk.git
cd floormap-sdk

# Install dependencies
yarn install

Open example/occupancy/index.js, then edit appId and appSecret

To request for an appId/appSecret, kindly email tech-sg@wework.com with the subject Request for FloorMap SDK credentials and a brief explanation of its intended purpose.

Then start the demo application

# Start demo and development
yarn start:demo

Open http//localhost:3000/

Plain Javascript application

# Clone
git clone git@github.com:WeConnect/floormap-sdk.git
cd floormap-sdk

# Install dependencies
yarn install

The plain demo version can be found in example/sample. Open index.html file.

FAQs

Package last updated on 28 Aug 2020

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc