odin on the web.
WODIN is a web application with a Node.js back end using Express, and a Vue.js front end. Both parts are written in Typescript.
The WODIN application can be deployed with custom configuration to create teaching courses that allow students to author and run model code using odin.
When the user runs a model in WODIN, odin will be invoked to provide executable JavaScript for odin model code. This odin code may be written by the user or provided in config.
WODIN configuration defines multiple 'apps', corresponding to teaching modules, which each provide functionality for one of three types of model usage:
- basic - to teach the basics of odin model definitions
- fit - to fit a model to data
- stochastic - to run a model stochastically
Each app will have one of these three app types, as well as any further configuration required e.g. default odin code.
WODIN fetches compiled odin code from odin.api, which should be run locally using
./scripts/run-dev-dependencies.sh
.
For development, you can install all dependencies and serve the app, with hot reloading, using two terminals. In one terminal, use ./scripts/serve-backend.sh
to run the server. In another terminal use ./scripts/serve-frontend.sh
.
The app will be available at http://localhost:3000.
You can also install dependencies, build and run the app locally in one step using ./scripts/build-and-run.sh
. The app will be available at http://localhost:3000
To build front end changes only run ./scripts/build-frontend.sh
.
WODIN is deployable via an npm package: https://www.npmjs.com/package/wodin
To run an instance of WODIN with custom configuration, install the package and use npx wodin /path/to/config
The path provided in the config
argument should be an absolute path to a root config folder containing the following:
Contains the following settings for the WODIN instance:
port
: the port number at which WODIN should be servedappsPath
: the url path under root at which each app should be available e.g/apps/day1
for appPath of "apps" and app name "day1"odinApi
: base url for the running instance of odin.api to use
A root index page index.html
should be provided which will be available at the root url /
and should provide a front
page for all apps, including any description and explanation along with links to apps and data files.
index.html
may also use files included in the /files
folder e.g. images or css.
Each config.json file defines config values for an app. The app will be available at /[appsPath]/[appName]
for a config
file named [appName].config.json
. [appsPath] is defined in wodin.config.json
. Note that the local config folder should
match appsPath
too.
Each app config file should contain the following settings:
appType
: "basic", "fit" or "stochastic"title
: the app title which will be visible to the userreadOnlyCode
: boolean indicating whether default code should not be editable by the userstateUploadIntervalMillis
(optional): number of milliseconds to wait after front end state changes before state will be saved to the server. Increase this value if too frequent requests are causing issues. Default is 2000.
Default odin code for an application (if any) should be provided in the /defaultCode
folder, in a file named [appName].R
.
Sample data and other supporting files can be provided in any folder structure under /files
and will be available at urls under /files
See the /config
folder for example configuration, used in development.
This codebase has been tested with Node version 20.9.0.
Front-end source can be found under app/static/src
. The front end can be built by running npm run build
from
app/static
. This builds output to be picked up by the back end at app/server/public
.
The entry point script is app/static/src/wodin.ts
.
Run unit tests from app/static
using npm run test:unit
. Run eslint with npm run lint
or npm run lint:fix
.
We use fontawesome for some icons (e.g. glyph in Monaco editor when there's an error or a warning). We have only the icons we need from fontawesome in app/static/src/assets/fontawesome.css
so if you would like to add a new one, you can define a custom class:
.<class-name> {
content: "\<unicode>"
}
where you can define the <class-name>
and the <unicode>
for the icon can be found at Fontawesome (it is in the top right hand corner when you select an icon). Note: we only have the "solid" icons currently.
The back end handles requests for apps by reading the corresponding config files and rendering an html Handlebars template
views/app.hbs
which uses the built front end js file, and also provides configuration from the appConfig
object via the
top-level WodinSession
component. It also sets an appType
variable which is used by wodin.ts
to select which type
of store to initialise.
The back-end server can be built using npm run build
and run using npm run serve
, both from app/server
.
Run tests from app/server
using npm test
. Run eslint with npm run lint
or npm run lint:fix
.
From app/server
using npm run integration-test
Browser tests use Playwright. Run browser tests, while the app is running, using npm run e2e-test
from app/static
.
To publish to npm:
- build both front end and and back end
- increment the version in
/app/server/package.json
- run
npm run genversion
from/app/server
to update the version number insrc/versions.ts
- then
npm publish --access public
, from/app/server
folder (may need tonpm login
first)
The build includes a docker image build which may be easier to deploy. See wodin-demo for an example.
Use the ./scripts/run-version.sh
script setting the branch references for the app and api (defaults to main for both):
./scripts/run-version.sh --app mrc-1234 --api mrc-2345
This repo has two main parts: app/server
(Express server) and app/static
(Vue frontend). The normal way to spin up the app without hot reloading is build frontend, copy build files into public folder in the server (npm run build --prefix=app/static
builds the frontend and copies the files to the server) and run the server (npm run serve --prefix=app/server
). The html file will then look for its javascript src wodin.js
and css src wodin.css
in the app/server/public
directory and load the app from these.
The hot reloading setup is different. The server.js
file (from building the server) takes in a --hot-reload
boolean option which tells it to instead look for the javascript src at http://localhost:5173/src/wodin.ts
since wodin.ts
is our entrypoint (http://localhost:5173
is the default url for vite
dev mode and it serves the files, after transpiling to javascript, based on your folder structure) and css src at http://localhost:5173/src/scss/style.scss
. To run it this way we run npm run dev --prefix=app/static
to start the vite dev server and then we run npm run serve-hot --prefix=app/server
.