refactors part of the frontend build pipeline, introduces ts
|
|
@ -1,18 +1,18 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": false,
|
||||
"node": true,
|
||||
"es2021": true
|
||||
},
|
||||
"extends": [
|
||||
"standard"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 13,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"ignorePatterns": ["**/*.min.js"],
|
||||
"rules": {
|
||||
"camelcase": 0
|
||||
}
|
||||
"env": {
|
||||
"browser": false,
|
||||
"node": true,
|
||||
"es2021": true
|
||||
},
|
||||
"extends": [
|
||||
"standard"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 13,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"ignorePatterns": ["**/*.min.js"],
|
||||
"rules": {
|
||||
"camelcase": 0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": false,
|
||||
"es2021": true
|
||||
},
|
||||
"extends": [
|
||||
"standard",
|
||||
"plugin:wc/recommended",
|
||||
"plugin:lit/recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 13,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"ignorePatterns": ["**/*.min.js"],
|
||||
"rules": {
|
||||
"camelcase": 0
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 636 B After Width: | Height: | Size: 636 B |
|
Before Width: | Height: | Size: 984 B After Width: | Height: | Size: 984 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 346 B After Width: | Height: | Size: 346 B |
|
Before Width: | Height: | Size: 386 B After Width: | Height: | Size: 386 B |
|
|
@ -1,4 +1,3 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
|
||||
|
|
@ -7,11 +6,12 @@
|
|||
|
||||
import { customElement, property } from 'lit/decorators.js'
|
||||
import { buttonStyles } from '../lib/styles.js'
|
||||
import { createRef, ref } from 'lit/directives/ref.js'
|
||||
import { AppElement, css, html } from './AppElement.js'
|
||||
import { createRef, ref, Ref } from 'lit/directives/ref.js'
|
||||
import { AppElement, css, html } from './AppElement'
|
||||
|
||||
@customElement('app-dialog')
|
||||
export class AppDialog extends AppElement {
|
||||
dialog: Ref<Element>
|
||||
constructor () {
|
||||
super()
|
||||
this.dialog = createRef()
|
||||
|
|
@ -58,7 +58,7 @@ export class AppDialog extends AppElement {
|
|||
}
|
||||
|
||||
@property({ type: Boolean, reflect: true })
|
||||
dialogOpen
|
||||
dialogOpen: boolean = false
|
||||
|
||||
render () {
|
||||
return html`
|
||||
|
|
@ -76,7 +76,7 @@ export class AppDialog extends AppElement {
|
|||
`
|
||||
}
|
||||
|
||||
close (event) {
|
||||
close (event: any) {
|
||||
if (event.target.returnValue !== 'confirm') {
|
||||
this.dispatchEvent(new CustomEvent('close', { detail: 'cancel' }))
|
||||
} else {
|
||||
|
|
@ -89,7 +89,7 @@ export class AppDialog extends AppElement {
|
|||
this.dialog.value.showModal()
|
||||
}
|
||||
|
||||
updated (changedProperties) {
|
||||
updated (changedProperties: Map<string, object>) {
|
||||
if (changedProperties.has('dialogOpen')) {
|
||||
if (this.dialogOpen) {
|
||||
// @ts-ignore
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
|
||||
|
|
@ -7,14 +6,14 @@
|
|||
|
||||
import { LitElement } from 'lit'
|
||||
import { property } from 'lit/decorators.js'
|
||||
import { APP_STATE } from '../store/appState.js'
|
||||
import { AppState, APP_STATE } from '../store/appState.js'
|
||||
export * from 'lit'
|
||||
|
||||
export class AppElement extends LitElement {
|
||||
// this is how we implement a global state: a global state object is passed via properties
|
||||
// to child components
|
||||
@property({ type: Object })
|
||||
appState = APP_STATE
|
||||
appState: AppState = APP_STATE
|
||||
|
||||
// ..and state changes are send back to the root component of the app by dispatching
|
||||
// a CustomEvent
|
||||
|
|
@ -23,7 +22,7 @@ export class AppElement extends LitElement {
|
|||
}
|
||||
|
||||
// a helper to dispatch events to the parent components
|
||||
sendEvent (eventType, eventData) {
|
||||
sendEvent (eventType: string, eventData: object) {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent(eventType, {
|
||||
detail: eventData,
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
|
||||
|
|
@ -6,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { customElement, property } from 'lit/decorators.js'
|
||||
import { AppElement, css, svg } from './AppElement.js'
|
||||
import { AppElement, css, svg } from './AppElement'
|
||||
|
||||
@customElement('battery-icon')
|
||||
export class DashboardMetric extends AppElement {
|
||||
|
|
@ -22,15 +21,15 @@ export class DashboardMetric extends AppElement {
|
|||
`
|
||||
}
|
||||
|
||||
@property({ type: String })
|
||||
batteryLevel = ''
|
||||
@property({ type: Number })
|
||||
batteryLevel = 0
|
||||
|
||||
render () {
|
||||
// 416 is the max width value of the battery bar in the SVG graphic
|
||||
const batteryWidth = parseInt(this.batteryLevel) * 416 / 100
|
||||
const batteryWidth = this.batteryLevel * 416 / 100
|
||||
|
||||
// if battery level is low, highlight the battery icon
|
||||
const iconClass = parseInt(this.batteryLevel) > 25 ? 'icon' : 'icon low-battery'
|
||||
const iconClass = this.batteryLevel > 25 ? 'icon' : 'icon low-battery'
|
||||
|
||||
return svg`
|
||||
<svg aria-hidden="true" focusable="false" class="${iconClass}" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512">
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
|
||||
|
|
@ -8,8 +7,8 @@
|
|||
import { customElement, state } from 'lit/decorators.js'
|
||||
import { icon_bluetooth, icon_compress, icon_expand, icon_gamepad, icon_poweroff, icon_undo, icon_upload } from '../lib/icons.js'
|
||||
import { buttonStyles } from '../lib/styles.js'
|
||||
import './AppDialog.js'
|
||||
import { AppElement, css, html } from './AppElement.js'
|
||||
import './AppDialog'
|
||||
import { AppElement, css, html, TemplateResult } from './AppElement'
|
||||
@customElement('dashboard-actions')
|
||||
export class DashboardActions extends AppElement {
|
||||
static get styles () {
|
||||
|
|
@ -41,7 +40,7 @@ export class DashboardActions extends AppElement {
|
|||
}
|
||||
|
||||
@state()
|
||||
dialog
|
||||
dialog: TemplateResult<1> | undefined = undefined
|
||||
|
||||
render () {
|
||||
return html`
|
||||
|
|
@ -121,34 +120,34 @@ export class DashboardActions extends AppElement {
|
|||
}
|
||||
|
||||
uploadTraining () {
|
||||
const dialogClosed = (event: any) => {
|
||||
this.dialog = undefined
|
||||
if (event.detail === 'confirm') {
|
||||
this.sendEvent('triggerAction', { command: 'uploadTraining' })
|
||||
}
|
||||
}
|
||||
|
||||
this.dialog = html`
|
||||
<app-dialog @close=${dialogClosed}>
|
||||
<legend>${icon_upload}<br/>Upload to Strava?</legend>
|
||||
<p>Do you want to finish your workout and upload it to Strava?</p>
|
||||
</app-dialog>
|
||||
`
|
||||
function dialogClosed (event) {
|
||||
this.dialog = undefined
|
||||
if (event.detail === 'confirm') {
|
||||
// @ts-ignore
|
||||
this.sendEvent('triggerAction', { command: 'uploadTraining' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shutdown () {
|
||||
const dialogClosed = (event: any) => {
|
||||
this.dialog = undefined
|
||||
if (event.detail === 'confirm') {
|
||||
this.sendEvent('triggerAction', { command: 'shutdown' })
|
||||
}
|
||||
}
|
||||
|
||||
this.dialog = html`
|
||||
<app-dialog @close=${dialogClosed}>
|
||||
<legend>${icon_poweroff}<br/>Shutdown Open Rowing Monitor?</legend>
|
||||
<p>Do you want to shutdown the device?</p>
|
||||
</app-dialog>
|
||||
`
|
||||
function dialogClosed (event) {
|
||||
this.dialog = undefined
|
||||
if (event.detail === 'confirm') {
|
||||
// @ts-ignore
|
||||
this.sendEvent('triggerAction', { command: 'shutdown' })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
|
||||
|
|
@ -6,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { customElement, property } from 'lit/decorators.js'
|
||||
import { AppElement, css, html } from './AppElement.js'
|
||||
import { AppElement, css, html, svg } from './AppElement'
|
||||
|
||||
@customElement('dashboard-metric')
|
||||
export class DashboardMetric extends AppElement {
|
||||
|
|
@ -37,7 +36,7 @@ export class DashboardMetric extends AppElement {
|
|||
}
|
||||
|
||||
@property({ type: Object })
|
||||
icon
|
||||
icon = svg``
|
||||
|
||||
@property({ type: String })
|
||||
unit = ''
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
|
||||
|
|
@ -11,8 +10,10 @@ import { icon_bolt, icon_exit, icon_heartbeat, icon_paddle, icon_route, icon_sto
|
|||
import { metricValue, metricUnit } from '../lib/helper.js'
|
||||
import { buttonStyles } from '../lib/styles.js'
|
||||
import { AppElement, css, html } from './AppElement.js'
|
||||
import { AppState } from '../store/appState.js'
|
||||
@customElement('game-component')
|
||||
export class GameComponent extends AppElement {
|
||||
rowingGames: any
|
||||
static get styles () {
|
||||
return [
|
||||
buttonStyles,
|
||||
|
|
@ -134,10 +135,10 @@ export class GameComponent extends AppElement {
|
|||
// This problem only occurs, when the update events are created from a web request (i.e. by receiving
|
||||
// new rowing metrics via web socket).
|
||||
// By delivering the app state updates directly here from index.js, this problem does not occur.
|
||||
this.sendEvent('setGameStateUpdater', (appState) => { this.gameAppState(appState) })
|
||||
this.sendEvent('setGameStateUpdater', (appState: AppState) => { this.gameAppState(appState) })
|
||||
}
|
||||
|
||||
gameAppState (appState) {
|
||||
gameAppState (appState: AppState) {
|
||||
if (this.rowingGames) this.rowingGames.appState(appState)
|
||||
}
|
||||
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
|
||||
|
|
@ -9,10 +8,10 @@ import { customElement, property } from 'lit/decorators.js'
|
|||
import { metricUnit, metricValue } from '../lib/helper.js'
|
||||
import { icon_bolt, icon_clock, icon_fire, icon_heartbeat, icon_paddle, icon_route, icon_stopwatch } from '../lib/icons.js'
|
||||
import { APP_STATE } from '../store/appState.js'
|
||||
import { AppElement, css, html } from './AppElement.js'
|
||||
import './BatteryIcon.js'
|
||||
import './DashboardActions.js'
|
||||
import './DashboardMetric.js'
|
||||
import { AppElement, css, html } from './AppElement'
|
||||
import './BatteryIcon'
|
||||
import './DashboardActions'
|
||||
import './DashboardMetric'
|
||||
|
||||
@customElement('performance-dashboard')
|
||||
export class PerformanceDashboard extends AppElement {
|
||||
|
|
@ -48,9 +47,6 @@ export class PerformanceDashboard extends AppElement {
|
|||
`
|
||||
}
|
||||
|
||||
@property({ type: Object })
|
||||
appState = APP_STATE
|
||||
|
||||
render () {
|
||||
const metrics = this.appState.metrics
|
||||
return html`
|
||||
|
|
@ -58,12 +54,12 @@ export class PerformanceDashboard extends AppElement {
|
|||
<dashboard-metric .icon=${icon_stopwatch} unit="/500m" .value=${metricValue(metrics, 'splitFormatted')}></dashboard-metric>
|
||||
<dashboard-metric .icon=${icon_bolt} unit="watt" .value=${metricValue(metrics, 'power')}></dashboard-metric>
|
||||
<dashboard-metric .icon=${icon_paddle} unit="/min" .value=${metricValue(metrics, 'strokesPerMinute')}></dashboard-metric>
|
||||
${metrics?.heartrate?.value
|
||||
${metrics?.heartrate
|
||||
? html`
|
||||
<dashboard-metric .icon=${icon_heartbeat} unit="bpm" .value=${metricValue(metrics, 'heartrate')}>
|
||||
${metrics?.heartrateBatteryLevel?.value
|
||||
${metrics?.heartrateBatteryLevel
|
||||
? html`
|
||||
<battery-icon .batteryLevel=${metrics?.heartrateBatteryLevel?.value}></battery-icon>
|
||||
<battery-icon .batteryLevel=${metrics?.heartrateBatteryLevel}></battery-icon>
|
||||
`
|
||||
: ''
|
||||
}
|
||||
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
|
|
@ -1,4 +1,3 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
|
||||
|
|
@ -10,12 +9,17 @@ import { customElement, state } from 'lit/decorators.js'
|
|||
import './components/GameComponent.js'
|
||||
import './components/PerformanceDashboard.js'
|
||||
import { createApp } from './lib/app.js'
|
||||
import { APP_STATE } from './store/appState.js'
|
||||
import { AppState, APP_STATE } from './store/appState.js'
|
||||
|
||||
@customElement('web-app')
|
||||
export class App extends LitElement {
|
||||
@state()
|
||||
appState = APP_STATE
|
||||
appState: AppState = APP_STATE
|
||||
|
||||
private app: {
|
||||
handleAction: (action: object) => void
|
||||
}
|
||||
private gameStateUpdater?: (state: AppState) => void
|
||||
|
||||
constructor () {
|
||||
super()
|
||||
|
|
@ -51,9 +55,9 @@ export class App extends LitElement {
|
|||
* the global state is updated by replacing the appState with a copy of the new state
|
||||
* todo: maybe it is more convenient to just pass the state elements that should be changed?
|
||||
* i.e. do something like this.appState = { ..this.appState, ...newState }
|
||||
* @param {Object} newState the new state of the application
|
||||
* @param {AppState} newState the new state of the application
|
||||
*/
|
||||
updateState = (newState) => {
|
||||
updateState = (newState: AppState) => {
|
||||
this.appState = { ...newState }
|
||||
// notify games about new app state
|
||||
if (this.gameStateUpdater) this.gameStateUpdater(this.appState)
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
|
||||
Defines the global state of the app
|
||||
*/
|
||||
|
||||
export interface Metrics {
|
||||
sessionState: string
|
||||
durationTotal: number
|
||||
durationTotalFormatted: string
|
||||
strokesTotal: number
|
||||
distanceTotal: number
|
||||
caloriesTotal: number
|
||||
caloriesPerMinute: number
|
||||
caloriesPerHour: number
|
||||
strokeTime: number
|
||||
distance: number
|
||||
power: number
|
||||
powerRaw: number
|
||||
split: number
|
||||
splitFormatted: string
|
||||
powerRatio: number
|
||||
instantaneousTorque: number
|
||||
strokesPerMinute: number
|
||||
speed: number
|
||||
strokeState: string
|
||||
heartrate: number
|
||||
heartrateBatteryLevel: number
|
||||
}
|
||||
|
||||
export interface AppState {
|
||||
// currently can be STANDALONE (Mobile Home Screen App), KIOSK (Raspberry Pi deployment) or '' (default)
|
||||
appMode: string
|
||||
// currently can be DASHBOARD or 'ROWINGGAMES'
|
||||
activeRoute: string
|
||||
// contains all the rowing metrics that are delivered from the backend
|
||||
metrics: Metrics,
|
||||
config: {
|
||||
// currently can be FTMS, FTMSBIKE or PM5
|
||||
peripheralMode: string
|
||||
// true if upload to strava is enabled
|
||||
stravaUploadEnabled: boolean
|
||||
// true if remote device shutdown is enabled
|
||||
shutdownEnabled: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export const APP_STATE: AppState = {
|
||||
// currently can be STANDALONE (Mobile Home Screen App), KIOSK (Raspberry Pi deployment) or '' (default)
|
||||
appMode: '',
|
||||
// currently can be DASHBOARD or 'ROWINGGAMES'
|
||||
activeRoute: 'DASHBOARD',
|
||||
// contains all the rowing metrics that are delivered from the backend
|
||||
metrics: {
|
||||
sessionState: 'waitingForStart',
|
||||
durationTotal: 0,
|
||||
durationTotalFormatted: '--',
|
||||
strokesTotal: 0,
|
||||
distanceTotal: 0,
|
||||
caloriesTotal: 0,
|
||||
caloriesPerMinute: 0,
|
||||
caloriesPerHour: 0,
|
||||
strokeTime: 0,
|
||||
distance: 0,
|
||||
power: 0,
|
||||
powerRaw: 0,
|
||||
split: Infinity,
|
||||
splitFormatted: '--',
|
||||
powerRatio: 0,
|
||||
instantaneousTorque: 0,
|
||||
strokesPerMinute: 0,
|
||||
speed: 0,
|
||||
strokeState: 'RECOVERY',
|
||||
heartrate: 0,
|
||||
heartrateBatteryLevel: 0,
|
||||
},
|
||||
config: {
|
||||
// currently can be FTMS, FTMSBIKE or PM5
|
||||
peripheralMode: '',
|
||||
// true if upload to strava is enabled
|
||||
stravaUploadEnabled: false,
|
||||
// true if remote device shutdown is enabled
|
||||
shutdownEnabled: false
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": false,
|
||||
"esModuleInterop": false,
|
||||
"experimentalDecorators": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "ES2020",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": true
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": false,
|
||||
"es2021": true
|
||||
},
|
||||
"extends": [
|
||||
"standard",
|
||||
"plugin:wc/recommended",
|
||||
"plugin:lit/recommended"
|
||||
],
|
||||
"parser": "@babel/eslint-parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 13,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"ignorePatterns": ["**/*.min.js"],
|
||||
"rules": {
|
||||
"camelcase": 0
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
|
||||
Defines the global state of the app
|
||||
*/
|
||||
|
||||
export const APP_STATE = {
|
||||
// currently can be STANDALONE (Mobile Home Screen App), KIOSK (Raspberry Pi deployment) or '' (default)
|
||||
appMode: '',
|
||||
// currently can be DASHBOARD or 'ROWINGGAMES'
|
||||
activeRoute: 'DASHBOARD',
|
||||
// contains all the rowing metrics that are delivered from the backend
|
||||
metrics: {},
|
||||
config: {
|
||||
// currently can be FTMS, FTMSBIKE or PM5
|
||||
peripheralMode: '',
|
||||
// true if upload to strava is enabled
|
||||
stravaUploadEnabled: false,
|
||||
// true if remote device shutdown is enabled
|
||||
shutdownEnabled: false
|
||||
}
|
||||
}
|
||||
|
|
@ -186,10 +186,8 @@ function getConfig () {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
replayRowingSession(handleRotationImpulse, {
|
||||
filename: 'recordings/WRX700_2magnets.csv',
|
||||
filename: 'data/recordings/2022-02-18_12-51-00_raw.csv',
|
||||
realtime: true,
|
||||
loop: true
|
||||
})
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"targets": {
|
||||
"esmodules": true
|
||||
},
|
||||
"shippedProposals": true,
|
||||
"bugfixes": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": [
|
||||
["@babel/plugin-proposal-decorators", { "decoratorsBeforeExport": true }]
|
||||
]
|
||||
}
|
||||
27
package.json
|
|
@ -18,13 +18,12 @@
|
|||
"!/**/*.test.js"
|
||||
],
|
||||
"scripts": {
|
||||
"lint": "eslint ./app ./config && markdownlint-cli2 '**/*.md' '#node_modules'",
|
||||
"lint": "eslint ./app ./config ./app-webclient && markdownlint-cli2 '**/*.md' '#node_modules'",
|
||||
"start": "node app/server.js",
|
||||
"dev": "npm-run-all --parallel dev:backend dev:frontend",
|
||||
"dev:backend": "nodemon --ignore 'app/client/**/*' app/server.js",
|
||||
"dev:backend": "nodemon app/server.js",
|
||||
"dev:frontend": "snowpack dev",
|
||||
"build": "rollup -c",
|
||||
"build:watch": "rollup -cw",
|
||||
"build": "snowpack build",
|
||||
"test": "uvu"
|
||||
},
|
||||
"simple-git-hooks": {
|
||||
|
|
@ -37,7 +36,7 @@
|
|||
"finalhandler": "1.1.2",
|
||||
"form-data": "4.0.0",
|
||||
"kaboom": "2001.0.0-alpha.21",
|
||||
"lit": "2.1.3",
|
||||
"lit": "2.2.0",
|
||||
"loglevel": "1.8.0",
|
||||
"nosleep.js": "0.12.0",
|
||||
"onoff": "6.0.3",
|
||||
|
|
@ -56,17 +55,9 @@
|
|||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "7.17.0",
|
||||
"@babel/plugin-proposal-decorators": "7.17.2",
|
||||
"@babel/preset-env": "7.16.11",
|
||||
"@rollup/plugin-babel": "5.3.0",
|
||||
"@rollup/plugin-commonjs": "21.0.1",
|
||||
"@rollup/plugin-node-resolve": "13.1.3",
|
||||
"@snowpack/plugin-babel": "2.1.7",
|
||||
"@web/rollup-plugin-html": "1.10.1",
|
||||
"axios": "0.25.0",
|
||||
"eslint": "8.9.0",
|
||||
"eslint-config-standard": "17.0.0-0",
|
||||
"axios": "0.26.0",
|
||||
"eslint": "8.10.0",
|
||||
"eslint-config-standard": "17.0.0-1",
|
||||
"eslint-plugin-import": "2.25.4",
|
||||
"eslint-plugin-lit": "1.6.1",
|
||||
"eslint-plugin-n": "14.0.0",
|
||||
|
|
@ -76,10 +67,6 @@
|
|||
"markdownlint-cli2": "0.4.0",
|
||||
"nodemon": "2.0.15",
|
||||
"npm-run-all": "4.1.5",
|
||||
"rollup": "2.67.2",
|
||||
"rollup-plugin-copy": "3.4.0",
|
||||
"rollup-plugin-summary": "1.3.0",
|
||||
"rollup-plugin-terser": "7.0.2",
|
||||
"simple-git-hooks": "2.7.0",
|
||||
"snowpack": "3.8.8",
|
||||
"tar": "6.1.11",
|
||||
|
|
|
|||
|
|
@ -1,15 +1,27 @@
|
|||
// Rollup bundling is currently not used any more since the experimental esbuild included in
|
||||
// snowpack does seem to work just fine with Open Rowing Monitor and produces bundles of similar size
|
||||
// If you want to use rollup bundling, make sure that you install the following dev dependencies
|
||||
// @rollup/plugin-commonjs
|
||||
// @rollup/plugin-node-resolve
|
||||
// @rollup/plugin-typescript
|
||||
// @web/rollup-plugin-html
|
||||
// rollup
|
||||
// rollup-plugin-copy
|
||||
// rollup-plugin-summary
|
||||
// rollup-plugin-terser
|
||||
|
||||
// Import rollup plugins
|
||||
import { babel } from '@rollup/plugin-babel'
|
||||
import commonjs from '@rollup/plugin-commonjs'
|
||||
import resolve from '@rollup/plugin-node-resolve'
|
||||
import html from '@web/rollup-plugin-html'
|
||||
import copy from 'rollup-plugin-copy'
|
||||
import summary from 'rollup-plugin-summary'
|
||||
import { terser } from 'rollup-plugin-terser'
|
||||
import typescript from '@rollup/plugin-typescript'
|
||||
|
||||
// Configure an instance of @web/rollup-plugin-html
|
||||
const htmlPlugin = html({
|
||||
rootDir: 'app/client',
|
||||
rootDir: 'app-webclient',
|
||||
flattenOutput: false
|
||||
})
|
||||
|
||||
|
|
@ -20,14 +32,15 @@ export default {
|
|||
plugins: [
|
||||
copy({
|
||||
targets: [
|
||||
{ src: 'app/client/assets/*', dest: 'build/assets' }
|
||||
{ src: 'app-webclient/assets/*', dest: 'build/assets' }
|
||||
]
|
||||
}),
|
||||
htmlPlugin,
|
||||
// transpile decorators so we can use the upcoming ES decorator syntax
|
||||
babel({
|
||||
babelrc: true,
|
||||
babelHelpers: 'bundled'
|
||||
typescript({
|
||||
tsconfig: './app-webclient/tsconfig.json',
|
||||
compilerOptions: {
|
||||
outDir: 'build/ts'
|
||||
}
|
||||
}),
|
||||
// convert modules with commonJS syntax to ESM
|
||||
commonjs(),
|
||||
|
|
|
|||
|
|
@ -1,24 +1,22 @@
|
|||
// Snowpack Configuration File
|
||||
// See all supported options: https://www.snowpack.dev/reference/configuration
|
||||
import proxy from 'http2-proxy'
|
||||
import { nodeResolve } from '@rollup/plugin-node-resolve'
|
||||
// import { nodeResolve } from '@rollup/plugin-node-resolve'
|
||||
|
||||
export default {
|
||||
mount: {
|
||||
// the web frontend is located in this directory
|
||||
'./app/client': { url: '/' }
|
||||
'./app-webclient': { url: '/' }
|
||||
},
|
||||
plugins: ['@snowpack/plugin-babel'],
|
||||
mode: 'development',
|
||||
packageOptions: {
|
||||
rollup: {
|
||||
plugins: [
|
||||
// todo: related to the lit documentation this should enable development mode
|
||||
// unfortunately this currently does not seem to work
|
||||
nodeResolve({
|
||||
exportConditions: ['development'],
|
||||
dedupe: true
|
||||
})
|
||||
// nodeResolve({
|
||||
// exportConditions: ['development']
|
||||
// })
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
@ -29,14 +27,16 @@ export default {
|
|||
buildOptions: {
|
||||
out: 'build'
|
||||
},
|
||||
// the esbuild based bundler in snowpack is still quite young, but does seem to work
|
||||
// nicely with this project
|
||||
optimize: {
|
||||
bundle: true,
|
||||
treeshake: true,
|
||||
minify: false,
|
||||
minify: true,
|
||||
target: 'es2020',
|
||||
sourcemap: false
|
||||
sourcemap: true
|
||||
},
|
||||
// add a proxy for websocket requests for the dev setting
|
||||
// add a proxy for web socket requests for the dev setting
|
||||
routes: [
|
||||
{
|
||||
src: '/websocket',
|
||||
|
|
|
|||