Welcome to the REA client application. This project uses ZenHub to manage our workflow, please install it and navigate to 'Boards' to see what is being developed currently.
Note that many issues are logged only for gathering future requirements and exist as placeholders. These are placed into the ZenHub 'icebox' for later analysis and development and should not be seen as active work items.
Here are the things you'll need to run this project and details on how to configure them.
The latest release of node at time of writing is 7.7.2
. You should be able to run with any other 7.x
version, but this is untested; some tools depend on particular node versions.
The best way to install node for development is to install NVM and then run nvm install 7.7.2
. This allows you to easily run different node versions for different projects. If you use NVM, you may also wish to add this to your .bashrc
, which will ensure your node version is synced with any projects which define an .nvmrc
file:
cd () { builtin cd "$@" && chNodeVersion; }
pushd () { builtin pushd "$@" && chNodeVersion; }
popd () { builtin popd "$@" && chNodeVersion; }
chNodeVersion() {
if [ -f ".nvmrc" ] ; then
nvm use;
fi
}
chNodeVersion;
Note that any commands installed via NPM or Yarn will only be available if you are using the same node version as was active at install time.
This repository actually uses two package managers: Lerna & Yarn. Lerna manages multi-package repositories (like this one), Yarn does the same thing as node's built-in package manager (NPM), but is much faster at it.
Before starting, you must install Yarn globally. Contrary to the install instructions, the easiest way to install is via NPM: npm i -g yarn
. Note however the following caveats:
npm i -g
instead of yarn global add
for installing global packages, but feel free to use Yarn for all other package-related tasks.npm i -g redux-dispatch-cli
Linters are basically a requirement for writing 'good' JavaScript code, since there are so many 'bad' ways to do it. This will also keep your code style aligned with other contributors.
1. Install tslint. You will need at least tslint 5.3.2
.
npm i -g typescript tslint tslint-react tsutils
2. Setup your editor.
Sublime Text 3:
SublimeLinter-contrib-tslint
user.linters
and that your node paths are set correctly under user.paths
. Note that the global node packages must be installed in the same node version as you specify here.CTRL/CMD + ~
) if you need more help!Other editors
Please add instructions here!
We use Typescript to author the app. Typescript is a typed superset of JavaScript, which adds a lot of code intelligence and safety features on top of JS.
Something you might need to be aware of from time to time with Typescript is that TS modules, standard nodejs modules (ie. 'commonjs') and ES6 JavaScript modules are all slightly different formats; and you will have to deal with them differently.
import myModule from 'mymodule'
works fine, as does import { something } from 'mymodule'
.import * as myModule from 'mymodule'
is required, as there is no such thing as a 'default export'. The abbreviated form will error.(Note: Babel is still used in the codebase, but only to process files generated by the SVG loader plugin.)
Now that you have all the prerequisites ready, you can setup the project. Clone this repo, then:
yarn
to install all dependenciesnpm run dev
to spin up a development serverThe app accepts the following env vars to control its behaviour:
NODE_ENV
: as usual, set to production
to run a non-debug build, omit to use debug mode or set to test
when running tests.IP
and PORT
specify the interface and port to listen on. Defaults to 0.0.0.0:3000
. If running in development, the webpack-dev-server
will be run on (port + 1)
.API_URL
: sets the base path to the OCP API. If not provided will default to http://localhost:8000/api
for connecting to a local instance.PUBLIC_PATH
sets the base URL to the website. If not provided, will default to /
.Since the repository is setup with Lerna, often when you try to run NPM commands within each packge rather than at the top level they won't be able to find the right dependencies. To workaround this, simply use Lerna's scope
option to target the specific package, for example: lerna run --scope @vflows/views test
.
In order to run for production, you need to configure the correct environment variables. This has to be done both when building the code and when running the webserver, as some configuration is compiled into the packaged JS files whilst others are read during execution of the pre-render webserver. Simply set the appropriate values in the below string and prepend it to each command you run.
NODE_ENV=production PORT=3000 WEB_BASEURL=http://localhost:3000 ASSET_BASEURL=http://localhost:3000 API_URL=http://localhost:8000/api/graph
First, build the app by running the build command. This will generate packaged assets into the dist
folder within the app package.
{ENV_SETTINGS} npm run build
To run the webserver, use the serve
command:
{ENV_SETTINGS} npm run serve
That's it!
In practise, you'll probably want to run the app via a process manager like PM2, to keep it online. Here's the PM2 control file for our test server as an example:
{
"apps" : [{
"name": "kamasi",
"script": "index.js",
"cwd": "app/static/kamasi/packages/app/",
"watch": true,
"env": {
"NODE_ENV": "production",
"PORT": 4430,
"WEB_BASEURL": "http://testocp.freedomcoop.eu:4430",
"ASSET_BASEURL": "http://testocp.freedomcoop.eu:4430",
"API_URL": "https://testocp.freedomcoop.eu/api/graph"
}
}]
}
Along with the process file, you'll also need to configure PM2 to start on boot. Since it's running in watch
mode, all that should be necessary is to rebuild the app and it will automatically update. If you prefer you can save some system resources by disabling this and running pm2 start
/ pm2 restart
etc manually.
postcss-import
won't combine them correctly.packages/ui-views
) bound to Redux by way of higher-order components (packages/ui-bindings
). Essentially the design goal is enforcing one-way dataflow and separation of concerns, this is done by writing the UI as simple functional transforms of props
data (pure view components) which bind to a single application state (in Redux) by way of accessor functions which pull the data out (higher-order components). All data going back in is sent through Redux's reducers by way of firing a Redux action.