Skip to content

Commit

Permalink
OAuth & viewer update
Browse files Browse the repository at this point in the history
* Implemented OAuth 2 authentication
* Updated optimaze-viewer to v0.3.0
* Removed I prefix from interfaces
* Updated webpack build
* Refactoring
  • Loading branch information
joakimgunst authored Oct 17, 2017
1 parent 7847a9b commit c97a3a2
Show file tree
Hide file tree
Showing 11 changed files with 492 additions and 183 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# optimaze-viewer-example

This is an example application for the [`optimaze-viewer`](https://github.com/rapal/optimaze-viewer) library.
It is written in TypeScript and uses Webpack for bundling.
This is an example application for the [`optimaze-viewer`](https://github.com/rapal/optimaze-viewer) library. It is written in TypeScript and uses Webpack for bundling. It implements the OAuth 2 authorization code flow for authenticating API requests.

Note: The API which this application uses is not yet published but will be published later in 2017.

## Usage

1. Run `yarn` to install dependencies
2. Run `yarn build`
2. Run `yarn start` to run webpack in watch mode
* Or run `yarn build` to create a production build
3. Open `index.html`
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@

<head>
<title>optimaze-viewer-example</title>
<script src="build/bundle.js"></script>
<link rel="stylesheet" href="build/bundle.css" />
</head>

<body>
<div id="viewer"></div>
<script src="build/bundle.js"></script>
</body>

</html>
12 changes: 9 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"url": "https://github.com/rapal/optimaze-viewer-example"
},
"scripts": {
"build": "yarn run lint && rimraf build && webpack",
"start": "webpack-dev-server",
"start": "yarn run lint && rimraf build && webpack -w",
"build": "yarn run lint && rimraf build && webpack -p --env production",
"lint": "tslint --config tslint.json --project tsconfig.json"
},
"devDependencies": {
Expand All @@ -25,9 +25,15 @@
"webpack": "^3.6.0"
},
"dependencies": {
"@rapal/optimaze-viewer": "^0.2.0",
"@rapal/optimaze-viewer": "^0.3.0",
"@types/date-fns": "^2.6.0",
"@types/es6-promise": "^0.0.33",
"@types/jwt-decode": "^2.2.1",
"@types/leaflet": "^1.2.0",
"@types/q": "^1.0.5",
"date-fns": "^1.29.0",
"es6-promise": "^4.1.1",
"jwt-decode": "^2.2.0",
"leaflet": "^1.2.0",
"q": "^1.5.0"
}
Expand Down
25 changes: 25 additions & 0 deletions src/app.css
Original file line number Diff line number Diff line change
@@ -1,9 +1,34 @@
body {
margin: 0;
font-family: sans-serif;
}

#viewer {
height: 100vh;
}

.leaflet-container {
background: transparent;
}

.login-button {
position: absolute;
top: 50%;
left: 50%;
font-size: 24px;
width: 100px;
margin-left: -50px;
}

.user-info {
position: absolute;
top: 10px;
right: 10px;
background: #eee;
border-radius: 3px;
padding: 10px;
}

.logout-button {
margin-left: 10px;
}
152 changes: 15 additions & 137 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -1,145 +1,23 @@
import * as L from "leaflet";
import * as Q from "q";
import {
Viewer,
Space,
Element,
GraphicsLayer,
IDimensions,
IBoundary,
ICoordinate
} from "@rapal/optimaze-viewer";
import loadViewer from "./viewer";
import { getAccessToken, showLoginButton, showUserInfo } from "./authentication";

import "leaflet/dist/leaflet.css";
import "./app.css";

// Specify company id
// Floor plan parameters
const companyId = 1361;
const floorId = "m2033670";

// Get floor id from URL params or use default
const params = new URLSearchParams(document.location.search.substring(1));
const floorId = params.get("floorId") || "m2033625";

// TODO: Replace with production URL once API is published
// TODO: Add support for authentication
const baseUrl = "http://localhost/space/api/public/v1/";

const graphicsUrl = `${baseUrl}/${companyId}/floors/${floorId}/graphics`;
const seatsUrl = `${baseUrl}/${companyId}/seats?floorId=${floorId}`;

function getTileUrlTemplate(layer: GraphicsLayer) {
return `${baseUrl}/${companyId}/floors/${floorId}/tiles?layer=${layer}&x={x}&y={y}&z={z}`;
// Get authorization code from URL
const params = new URLSearchParams(document.location.search);
const authorizationCode = params.get("code");
if (authorizationCode) {
window.history.replaceState(null, "", window.location.pathname);
}

function getJson<TData>(url: string) {
return fetch(url, { credentials: "include" }).then<TData>(r => r.json());
}

Q.all([
getJson<IFloorGraphics>(graphicsUrl),
getJson<IList<ISeat>>(seatsUrl)
]).then(values => {
const floor = values[0];
const seats = values[1].items;

const viewer = new Viewer("viewer", floor.dimensions);

// Add all available tile layers
// floor.graphicsLayers.forEach(l =>
// viewer.addTileLayer(getTileUrlTemplate(l))
// );

// Or add specific tile layer
viewer.addTileLayer(getTileUrlTemplate(GraphicsLayer.Architect));

// Creating custom panes is not neccessary, but makes sure
// that elements of the same type are shown at the same z-index
viewer.createPane("spaces").style.zIndex = "405";
viewer.createPane("seats").style.zIndex = "410";

// Create selectable space layers
const spaceLayers = floor.spaceGraphics.map(s => {
return new Space(
s.id,
s.boundaries,
{ pane: "spaces" },
{ selectable: true }
);
});

spaceLayers.forEach(space => {
// Add to map
viewer.addLayer(space);

// Deselect other spaces and log space id when selected
space.on("select", e => {
const id = e.target.id;
spaceLayers.filter(s => s.id !== id).forEach(s => (s.selected = false));
console.log("select space " + id);
});

// Log space id when deselected
space.on("deselect", e => {
const id = e.target.id;
console.log("deselect space " + id);
});
});

// Create selectable seat layer
// Seats are shown as circles with 500mm radius
// Seat styles are specified using the style function
const seatLayers = seats.map(s => {
const circle = L.circle(L.latLng(s.y, s.x), { radius: 500, pane: "seats" });
return new Element(s.id.toString(), [circle], {
selectable: true,
styleFunction: e => ({
color: e.selected ? "#f00" : "#666",
weight: e.selected ? 2 : 1,
opacity: 1,
fillColor: e.selected ? "#faa" : "#ccc",
fillOpacity: 1,
pane: "seats"
})
});
});

seatLayers.forEach(seat => {
// Add to map
viewer.addLayer(seat);

// Deselect other seats and log seat id when selected
seat.on("select", e => {
const id = e.target.id;
seatLayers.filter(s => s.id !== id).forEach(s => (s.selected = false));
console.log("select seat " + id);
});

// Log seat id when deselected
seat.on("deselect", e => {
const id = e.target.id;
console.log("deselect seat " + id);
});
});
});

interface IFloorGraphics {
dimensions: IDimensions;
graphicsLayers: GraphicsLayer[];
spaceGraphics: ISpaceGraphics[];
scale: number;
}

interface ISpaceGraphics {
id: string;
boundaries: IBoundary[];
}

interface IList<TItem> {
items: TItem[];
}

interface ISeat {
id: number;
x: number;
y: number;
}
getAccessToken(authorizationCode)
.then(accessToken => {
loadViewer(companyId, floorId, accessToken);
showUserInfo(accessToken);
})
.catch(() => showLoginButton());
Loading

0 comments on commit c97a3a2

Please sign in to comment.