Skip to content

Commit c5c3dfa

Browse files
add demo app
Co-authored-by: tc-imba <[email protected]> Co-authored-by: Reapor-Yurnero <[email protected]>
1 parent 21fd6cf commit c5c3dfa

File tree

7 files changed

+996
-0
lines changed

7 files changed

+996
-0
lines changed

apps/demo/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.zip
2+
/node_modules

apps/demo/Dockerfile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
FROM node:18-alpine
2+
3+
ENV HOME="/root"
4+
WORKDIR /root
5+
6+
COPY ./package.json ./yarn.lock /root/
7+
RUN --mount=type=cache,target=/usr/local/share/.config/yarn/global yarn
8+
COPY . /root
9+
10+
CMD node backend/index.js

apps/demo/backend/index.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
const express = require('express')
2+
const request = require('request');
3+
const cors = require('cors')
4+
5+
const app = express()
6+
const port = 5000
7+
8+
app.use(cors())
9+
10+
let apiToken = process.env.BRICK_SERVER_API_TOKEN;
11+
if (!apiToken) {
12+
apiToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJsaXV5aDk3MDYxNUBnbWFpbC5jb20iLCJhdWQiOlsiYnJpY2siXSwiZG9tYWluIjoiQ2VudGVyX0hhbGwiLCJhcHAiOiJnZW5pZSIsImRvbWFpbl91c2VyX2FwcCI6IjY2YzRlYzk5NTMxNzI4MWZiNDg3Y2NkMyIsImV4cCI6MTc0NzU5NTQ4NX0.Xa15aa5vBS1M9oQrdYvlFWYH07yftloyFSflFGAxFpg";
13+
// process.exit(-1);
14+
}
15+
const parseJwt = (token) => {
16+
return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
17+
}
18+
const jwt = parseJwt(apiToken);
19+
const domain = jwt.domain;
20+
console.log(jwt)
21+
22+
const baseURL = "https://brickserver.ucsd.edu/brickapi/v1"
23+
const listEntitiesURL = `${baseURL}/users/domains/${domain}/permissions`;
24+
const readURL = `${baseURL}/actuation/domains/${domain}/read`;
25+
const writeURL = `${baseURL}/actuation/domains/${domain}`;
26+
const headers = {
27+
'Content-Type': 'application/json',
28+
'Authorization': `Bearer ${apiToken}`,
29+
}
30+
31+
32+
app.get('/', (req, res) => {
33+
res.send('Hello World!')
34+
})
35+
36+
app.get('/list', (req, res) => {
37+
request.get(listEntitiesURL, {headers: headers}, (err, _res, body) => {
38+
res.send(body);
39+
});
40+
})
41+
42+
app.get('/read', (req, res) => {
43+
const data = {
44+
[req.query.entity_id]: [""]
45+
}
46+
request.post(readURL, {headers: headers, json: data}, (err, _res, body) => {
47+
res.send(body);
48+
});
49+
})
50+
51+
app.get('/write', (req, res) => {
52+
const data = {
53+
[req.query.entity_id]: [`${req.query.value}`]
54+
}
55+
request.post(writeURL, {headers: headers, json: data}, (err, _res, body) => {
56+
res.send(body);
57+
});
58+
})
59+
60+
61+
app.listen(port, () => {
62+
console.log(`Example app listening on port ${port}`)
63+
})

apps/demo/build.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
3+
rm backend.zip frontend.zip
4+
5+
# build backend
6+
zip -r backend.zip backend Dockerfile package.json yarn.lock
7+
8+
# build frontend
9+
cd frontend && zip -r ../frontend.zip .

apps/demo/frontend/index.html

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Entity Reader/Writer</title>
6+
<style>
7+
body { font-family: sans-serif; padding: 20px; }
8+
.controls { display: flex; align-items: center; gap: 20px; margin: 20px; }
9+
</style>
10+
</head>
11+
<body>
12+
<div class="controls">
13+
<select id="select_read">
14+
<option value="" disabled selected>Loading…</option>
15+
</select>
16+
<input id="input_read" type="text" disabled/>
17+
<button id="button_read">Read</button>
18+
</div>
19+
<div class="controls">
20+
<select id="select_write">
21+
<option value="" disabled selected>Loading…</option>
22+
</select>
23+
<input id="input_write" type="text"/>
24+
<button id="button_write">Write</button>
25+
</div>
26+
27+
<script>
28+
// Populate dropdown on page load
29+
const baseURL = "https://brickserver.ucsd.edu/brickapi/v1/apps/api";
30+
const params = new URL(document.location).searchParams;
31+
const token = params.get("token");
32+
const headers = {
33+
"Authorization": `Bearer ${token}`
34+
};
35+
36+
function initSelect(id, entities) {
37+
const sel = document.getElementById(id);
38+
sel.innerHTML = ''; // clear "Loading…" placeholder
39+
entities.forEach(e => {
40+
const opt = document.createElement('option');
41+
opt.value = e;
42+
opt.textContent = e;
43+
sel.appendChild(opt);
44+
});
45+
}
46+
47+
async function loadEntities() {
48+
try {
49+
const resp = await fetch(`${baseURL}/list`, {headers: headers});
50+
if (!resp.ok) throw new Error('Network response was not ok');
51+
const result = await resp.json(); // expect ["ent1", "ent2", ...]
52+
initSelect("select_read", result.data.read[""].concat(result.data.write[""]));
53+
initSelect("select_write", result.data.write[""]);
54+
55+
} catch (err) {
56+
console.error(err);
57+
alert('Failed to load entities.');
58+
}
59+
}
60+
61+
// Call read or write API with the selected entity
62+
async function callApi(action) {
63+
const entity = document.getElementById(`select_${action}`).value;
64+
if (!entity) {
65+
alert('Select an entity first.');
66+
return;
67+
}
68+
try {
69+
let url = `${baseURL}/${action}?entity_id=${entity}`;
70+
if (action === "write") {
71+
const value = document.getElementById("input_write").value;
72+
url += `&value=${value}`;
73+
}
74+
const resp = await fetch(url, {headers: headers});
75+
if (!resp.ok) throw new Error(`${action} failed`);
76+
const result = await resp.json();
77+
console.log(result);
78+
if (action === "read") {
79+
document.getElementById("input_read").value = result.data.results[0].detail;
80+
}
81+
alert(`${action} succeeded: ${JSON.stringify(result)}`);
82+
} catch (err) {
83+
console.error(err);
84+
alert(`${action} error: ${err.message}`);
85+
}
86+
}
87+
88+
document.getElementById('button_read').addEventListener('click', () => callApi('read'));
89+
document.getElementById('button_write').addEventListener('click', () => callApi('write'));
90+
window.addEventListener('DOMContentLoaded', loadEntities);
91+
</script>
92+
</body>
93+
</html>

apps/demo/package.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "demo",
3+
"version": "1.0.0",
4+
"description": "A demo app",
5+
"main": "backend/index.js",
6+
"license": "MIT",
7+
"dependencies": {
8+
"cors": "^2.8.5",
9+
"express": "^5.1.0",
10+
"request": "^2.88.2"
11+
}
12+
}

0 commit comments

Comments
 (0)