Security News
Fluent Assertions Faces Backlash After Abandoning Open Source Licensing
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
@wework/floormap-sdk
Advanced tools
master
branch (https://github.com/WeConnect/floormap-monorepo/tree/master/packages/react-floormap)mapAppearance
options to disable default theme - UsageNPM
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@v2
# Yarn
yarn add @wework/floormap-sdk@v2
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
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 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 */
})
mwAccessToken
for futher usageauthenticate
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.
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 mapoptions.deskLayout
- Show desk layoutoptions.deskInteractable
- Allow desk/chair to be interactableAfter 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>
To render a floor, we can simply pass floorId
to render
function. Floormap will automatically fetch a floor data and building data (the floor belongs to)
floorMap.render({
floorId: '{FLOOR_ID}',
})
Or you can pass just a buildingId
which will let to floorMap
render the lowerest floor of the building
floorMap.render({
floorId: 'b308b94c-bca6-4318-b906-1c148f7ca183',
})
the render
will return promise with building
and floor
data inside
const { building, floors, spaces, objects } = await floorMap.render({
floorId: 'b308b94c-bca6-4318-b906-1c148f7ca183',
})
To render a single room by passing spaceId
// Render room with return only spaces (with single space inside) and objects inside the space
const { spaces, objects } = floorMap.render({
spaceId: '{PHYSICAL_SPACE_UUID_FROM_SRS}',
})
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 typepayload
- An informations of the interactiondata
- Space data, If an interaction is on space/objectExample 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 */
}
}
mapAppearance
options to disable default themeA floormap comes with default color theme and icon. Provide mapAppearance
options when create a floorMap allow you to control the initial appearance of the map.
You can disable default color of each room, remove default map icons, and hide room number. Disable all default appearance will allow you to configure and style the map by from scatch.
manager.createFloorMap({
// other options
mapAppearance: {
mapIcons: false, // disable defatch map icons
mapColor: false, // disable default map color
roomNumbers: false, // disable room numbers
},
})
property | type | default | note |
---|---|---|---|
wallColor , color | `string | number` | |
wallHeight , height | number | height will take precedence | |
wallTexture , texture | TextureOptions | texture will take precedence, see Types | |
wallOffset | number | ||
wallCornerRadius | number | ||
wallOutline | `string | number` | |
wallOpacity | number | ||
wallSide | FRONT ,BACK ,DOUBLE | ||
wallVisible | boolean | ||
wallElevation | number | ||
baseColor | `string | number` | |
baseHeight | number | ||
baseTexture | TextureOptions | ||
baseOffset | number | ||
baseCornerRadius | number | ||
baseOutline | `string | number` | |
baseOpacity | number | ||
baseSide | FRONT ,BACK ,DOUBLE | ||
baseVisible | boolean | ||
baseElevation | number | ||
title | TitleNodeOptions | ||
titleDisplayMode | `'fitSpace' | 'hideOnOverflow' | 'default'` |
interactable | boolean | ||
visible | boolean |
Property | Type | Note |
---|---|---|
color | `string | number` |
outline | `string | number` |
height | number | |
elevation | number | |
title | TitleNodeOptions | see Types |
interactable | boolean | |
visible | boolean | |
scale | `number | Point3D` |
rotation | ObjectRotationOptions | see Types |
position | Point2D | |
gltf | GLTFOptions | see Types |
objectOffset | Point3D | see 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
// Position + positionOffset is title node position and use as the anchor point when rotating (billboard)
position?: Point2D
positionOffset?: Point2D
elevation?: number
// Content Offset is the badge position relative to the title node position
contentOffset?: Point3D
}
type ObjectRotationOptions = {
x: number
y: number
z: number
metric: RotationMetric
}
type GLTFOptions = {
src?: any
scale?: number
rotation?: Point3D
}
type TextureOptions = {
img?: string
repeat?: number
}
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 will be an anchor point for rotation
position?: Point2D
elevation?: number // z-position
// offset internal content position
objectOffset?: Point3D
}
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
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:
.applyStyle()
.revertStyle()
.resetStyle()
.invalidate()
.updateSpace()
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.
invalidate
to highlight selecting spacelet 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 = ''
}
})
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.
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
// }
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
)
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' },
])
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
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 all applied styles from a given space uuid
resetStyle(
stylesWithId: { id: string } | { id: string }[],
animated?: boolean,
duration?: number,
completion?: function
)
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 })
// - 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 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 objectfloor
A floor objectoptions
Passing options from .render
and .load
errors
If any errors occurredonLoad 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.
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
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.
const unsubscribe = floorMap.didLoad(
({ building, floor, spaces, objects, options, errors }) => {
// Change room type
floorMap.updateData(spaceeUUID, { roomType: 'Private Large Office' })
}
)
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.
const unsubscribe = floorMap.onRender(
({ building, floor, spaces, objects, options, errors }) => {
floorMap.applyStyle({
id: spaceUUID,
style: { color: 'aqua' },
key: 'occupancy-style',
})
}
)
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)
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)
}
)
Get a call when an error occurred during loading or rending
const unsubscribe = floorMap.onError(({ options, errors }) => {
// Change room type
floorMap.updateData(spaceeUUID, { roomType: 'Private Large Office' })
})
Call returned function to remove a listener.
// Subscribe to onLoad
const unsubscribe = floorMap.onLoad(() => {})
// Unsubscribe
unsubscribe()
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 UUIDfloorId
- Physical / System Floor UUIDautoLoadFloor
- Auto load lowerest floor in building if floorId
is omittedskipCache
- Skip local building/floor cache in the SDKResult:
building
- Building objectfloor
- Floor objectspaces
- Space objects inside floorobjects
- Objects (Chair, Table) inside floorLoad and render floormap into the screen
floorMap.render(options: Object): Promise<Result>
Options:
buildingId
- Physical / System Building UUIDfloorId
- Physical / System Floor UUIDautoLoadFloor
- Auto load lowerest floor in building if floorId
is omittedskipCache
- Skip local building/floor cache in the SDKResult:
building
- Building objectfloor
- Floor objectspaces
- Space objects inside floorobjects
- Objects (Chair, Table) inside floorReload and re-render current floor
floorMap.reload(options: Object): Promise
Options:
skipCache
: Skip local building/floor cache in the SDKReturns all spaces and objects in current floor (if floorId is omitted)
floorMap.getSpaces(floorId: string?): Space|SpaceObject[]
Update Space/SpaceObject data by its uuid. This will trigger on('datachange')
event.
floorMap.updateData(uuid: string, data: object?)
Returns current building
floorMap.getCurrentBuilding(): Building
Returns current floor
floorMap.getCurrentBuilding(): Floor
Returns current status of the floor map
floorMap.getCurrentState(): string
State values:
IDLE
- Floor map is ready to renderLOADING
- Loading dataRENDERING
- Rendering mapRENDERED
- Floor map is displayed on the screenTERMINATED
- Floor map is terminated from teardown callERROR
- Have an error during loading/renderingFit camera to the map content
floorMap.fitContent({ padding: number })
floorMap.fitContent({ padding: 20 })
Set the zoom level
floorMap.setZoomLevel(zoomLevel: number)
Get current zoom level of the map.
floorMap.getZoomLevel(): number
Set minimum zoom level of the map.
floorMap.getMinZoomLevel(min: number)
Set maximum zoom level of the map.
floorMap.getMaxZoomLevel(max: number)
Set the camera rotation view angle
floorMap.setCenter(options: {
x: number
y: number
z?: number
animated?: boolean
duration?: number
onComplete?: () => {}
}
floorMap.setCenter({ x: 2, y: 0, z: 5 })
Rotate the map
floorMap.setRotation(azimuthAngleDegree: number, horizontalDegree: number)
azimuthAngleDegree
Vetical (y-axis) rotation degreepolarAngleDegree
Horizontal (x-axis) rotation degreefloorMap.setRotation(rotationDegree, polarAngle)
Set min polar angle (x-axis) that the camera can be rotated by user
Value is in degree
setMinPolarAngle(min: number)
Set max polar angle (x-axis) that the camera can be rotated by user
Value is in degree
setMaxPolarAngle(max: number)
Set min azimuthAngle (y-axis) that the camera can be rotated by user
Value is in degree
setMinAzimuthAngle(min: number)
Set max azimuthAngle (y-axis) that the camera can be rotated by user
Value is in degree
setMaxAzimuthAngle(max: number)
Set minimum zoom level of the map.
floorMap.getMinZoomLevel(min: number)
Set maximum zoom level of the map.
floorMap.getMaxZoomLevel(max: number)
Enable/Disable zoom interaction
floorMap.setEnabledZoom(enabled: boolean)
Enable/Disable pan interaction
floorMap.setEnabledPan(enabled: boolean)
Enable/Disable rotation interaction
floorMap.setEnabledRotate(enabled: boolean)
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
floorMap.addObject(overlay)
// You can add multiple objects as once by passing array of objects
floorMap.addObject([overlay, overlay2])
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])
Returns an access token of the current session
const mwAccessTokenObj = manager.session.getAccessToken()
Set new access token to the current session
manager.session.setAccessToken(mwAccessTokenObj)
Set new spaceman JWT token and re-authenticate
const mwAccessTokenObj = await manager.session.setSpacemanToken(jwt)
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 extensiongetDescription()
- Description of the extensiononRegister()
- This function will get called when register the extension to a maponRemove()
- This function will get called when unregister the extension from a mapgetDataById(spaceUUID: string)
- Provide additional data for to space/object based on UUID - Deprecated Use getDataBySpace insteadgetDataBySpace(space: Space)
- Provide additional data for to space/objectInside 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 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)
}
})
// extensionId is the value returned from getId()
floorMap.extensions[extensionId]
floorMap.getExtension(extensionId)
// Example
floormap.extensions.cityweather
floormap.getExtension('cityweather')
Remove extension from floormap
floorMap.removeExtension(weatherExtension)
floorMap.removeExtension('cityweather')
Please see: https://github.com/WeConnect/floormap-extensions
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.
# 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
# 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
[![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
The npm package @wework/floormap-sdk receives a total of 53 weekly downloads. As such, @wework/floormap-sdk popularity was classified as not popular.
We found that @wework/floormap-sdk demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 30 open source maintainers collaborating on the project.
Did you know?
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.
Security News
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
Research
Security News
Socket researchers uncover the risks of a malicious Python package targeting Discord developers.
Security News
The UK is proposing a bold ban on ransomware payments by public entities to disrupt cybercrime, protect critical services, and lead global cybersecurity efforts.