adds frontend build tool

This commit is contained in:
Lars Berning 2021-03-26 23:15:12 +00:00
parent f358d06247
commit c3d7d64a51
10 changed files with 879 additions and 478 deletions

1
.gitignore vendored
View File

@ -76,3 +76,4 @@ node_modules
.DS_Store .DS_Store
._* ._*
tmp/ tmp/
build/

View File

@ -3,7 +3,7 @@
<!-- markdownlint-disable-next-line no-inline-html --> <!-- markdownlint-disable-next-line no-inline-html -->
<img width="200" height="200" align="left" src="doc/img/openrowingmonitor_icon.png"> <img width="200" height="200" align="left" src="doc/img/openrowingmonitor_icon.png">
An open source rowing monitor for rowing exercise machines. An open source rowing monitor for rowing exercise machines. It upgrades a rowing machine into a real smart trainer that can be used with training applications and games.
Open Rowing Monitor is a Node.js application that runs on a Raspberry Pi and measures the rotation of the rower's flywheel to calculate rowing specific metrics, such as power, split time, speed, stroke rate, distance and calories. Open Rowing Monitor is a Node.js application that runs on a Raspberry Pi and measures the rotation of the rower's flywheel to calculate rowing specific metrics, such as power, split time, speed, stroke rate, distance and calories.
@ -42,7 +42,7 @@ Fitness Machine Service (FTMS) is a standardized GATT protocol for different typ
**FTMS Indoor Bike** is widely adopted by training applications for bike training. The simulated Indoor Bike offers metrics such as power and distance to the biking application. So why not use your rowing machine to row up a mountain in Zwift, Bkool, Sufferfest or similar :-) **FTMS Indoor Bike** is widely adopted by training applications for bike training. The simulated Indoor Bike offers metrics such as power and distance to the biking application. So why not use your rowing machine to row up a mountain in Zwift, Bkool, Sufferfest or similar :-)
**Concept2 PM** Open Rowing Monitor also implements part of the Concept2 PM Bluetooth Smart Communication Interface Definition. This is still work in progress and may not work with all applications that support C2 rowing machines. **Concept2 PM** Open Rowing Monitor also implements part of the Concept2 PM Bluetooth Smart Communication Interface Definition. This is still work in progress and only implements the most common parts of the spec, so it will not work with all applications that support the C2 rowing machines.
## How it all started ## How it all started

View File

@ -15,7 +15,7 @@ import EventEmitter from 'events'
function createWebServer () { function createWebServer () {
const emitter = new EventEmitter() const emitter = new EventEmitter()
const port = process.env.PORT || 80 const port = process.env.PORT || 80
const serve = serveStatic('./app/client', { index: ['index.html'] }) const serve = serveStatic('./build', { index: ['index.html'] })
const server = http.createServer((req, res) => { const server = http.createServer((req, res) => {
serve(req, res, finalhandler(req, res)) serve(req, res, finalhandler(req, res))

File diff suppressed because one or more lines are too long

View File

@ -2,10 +2,10 @@
/* /*
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
This is currently a very simple Web UI that displays the training metrics. Does not use any bundling This is currently a very simple Web UI that displays the training metrics.
or transpiling yet.
*/ */
// eslint-disable-next-line no-unused-vars import NoSleep from 'nosleep.js'
export function createApp () { export function createApp () {
const fields = ['strokesTotal', 'distanceTotal', 'caloriesTotal', 'power', 'splitFormatted', 'strokesPerMinute', 'durationTotalFormatted', 'peripheralMode'] const fields = ['strokesTotal', 'distanceTotal', 'caloriesTotal', 'power', 'splitFormatted', 'strokesPerMinute', 'durationTotalFormatted', 'peripheralMode']
const fieldFormatter = { const fieldFormatter = {
@ -37,7 +37,7 @@ export function createApp () {
function initWebsocket () { function initWebsocket () {
// use the native websocket implementation of browser to communicate with backend // use the native websocket implementation of browser to communicate with backend
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
socket = new WebSocket(`ws://${location.host}`) socket = new WebSocket(`ws://${location.host}/websocket`)
socket.addEventListener('open', (event) => { socket.addEventListener('open', (event) => {
console.log('websocket openend') console.log('websocket openend')

View File

@ -15,11 +15,7 @@
<title>Open Rowing Monitor</title> <title>Open Rowing Monitor</title>
</head> </head>
<body> <body>
<script src="NoSleep.min.js"></script> <script type="module" src="/index.js"></script>
<script type="module">
import { createApp } from './app.js'
window.app = createApp()
</script>
<div id="dashboard" class="grid"> <div id="dashboard" class="grid">
<div class="col"> <div class="col">
<div class="label">Distance</div> <div class="label">Distance</div>

9
app/client/index.js Normal file
View File

@ -0,0 +1,9 @@
'use strict'
/*
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
Init file for the web frontend
*/
import { createApp } from './app.js'
window.app = createApp()

1291
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,9 @@
"prepare": "husky install", "prepare": "husky install",
"lint": "eslint ./app && markdownlint '**/*.md' --ignore node_modules", "lint": "eslint ./app && markdownlint '**/*.md' --ignore node_modules",
"start": "node app/server.js", "start": "node app/server.js",
"dev": "npm-run-all --parallel start build:watch",
"build": "snowpack build",
"build:watch": "snowpack build --watch",
"test": "ava" "test": "ava"
}, },
"ava": { "ava": {
@ -27,6 +30,7 @@
"finalhandler": "^1.1.2", "finalhandler": "^1.1.2",
"http": "0.0.1-security", "http": "0.0.1-security",
"loglevel": "^1.7.1", "loglevel": "^1.7.1",
"nosleep.js": "^0.12.0",
"onoff": "^6.0.1", "onoff": "^6.0.1",
"serve-static": "^1.14.1", "serve-static": "^1.14.1",
"ws": "^7.4.4" "ws": "^7.4.4"
@ -38,7 +42,10 @@
"eslint-plugin-import": "^2.22.1", "eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0", "eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.3.1", "eslint-plugin-promise": "^4.3.1",
"http-proxy": "^1.18.1",
"husky": "^5.1.3", "husky": "^5.1.3",
"markdownlint-cli": "^0.27.1" "markdownlint-cli": "^0.27.1",
"npm-run-all": "^4.1.5",
"snowpack": "^3.1.2"
} }
} }

25
snowpack.config.js Normal file
View File

@ -0,0 +1,25 @@
// Snowpack Configuration File
// See all supported options: https://www.snowpack.dev/reference/configuration
// todo: might add a proxy for websockets here so we can use snowpack dev server with HMR
export default {
mount: {
// the web frontend is located in this directory
'./app/client': { url: '/' }
// mount "public" to the root URL path ("/*") and serve files with zero transformations:
// './public': { url: '/', static: true, resolve: false }
},
plugins: [
/* ... */
],
packageOptions: {
/* ... */
},
devOptions: {
open: 'none',
output: 'stream'
},
buildOptions: {
out: 'build'
}
}