Skip to content
pospi edited this page Mar 28, 2017 · 12 revisions

Welcome to the future home of the REA client application interface.

Background info

This application attempts to be a new frontend to existing 'Open Value Network' client / server apps. Much work has been done on the OVN protocol and related specifications by many contributors too numerous to list here. An extremely brief history goes as follows- follow the links to learn more about the theory and concepts behind OVNs.

  • Early 1980s: Bill McCarthy first defines Resource-Event-Agent (REA) model for accounting systems and publishes many papers on the topic.
  • Mid 1990s: Bob Haugen commercially develops 'Quick Response Engine' & becomes interested in supply chain systems.
  • 1995-2000: Bob discovers REA, he and Bill further develop REA as a semantic model for internet supply chain collaboration.
  • 2000: Verna Allee coins the term "Value Network" to describe and model tangible & intangible economic value within organisations.
  • 2002: ISO adopts REA as their economic and accounting ontology.
  • 2005: Bob begins to write to the importance of expanding REA to cover ad-hoc networks of external economic entities.
  • 2005-2011: Bob works closely with Lynn Foster under the name 'Mikorizal Software' on several open supply chain projects; targeting timber, food networks & fishing industries.
  • 2012: Open hardware manufacturer Sensorica gets involved with REA and coins the term "Open Value Network" (OVN). They develop the Network Resource Planning (NRP) software in collaboration with Bob & Lynn. This is the first iteration of the software on which django-rea and its forks are based.
  • 2016: Bill expands upon the concept of an Open Value Network, building on his prior REA model.
  • Q1 2016: Sensorica's NRP software is forked by FreedomCoop and becomes OCP (Open Collaboration Platform). Many updates are made and integrations with economic networks (FairCoin) begin.
  • Q3 2016: Another fork of NRP is made by GoPacifica and further development continues on that project.
  • 2016-2017 Lynn and Bob join with others to continue work on developing the REA ontology, incorporating learnings from prior projects & concepts, including NRP & OVN, as well as others. The project name is genericised to "Value Flows" and becomes focused on working towards common standards.
  • Dec 2016: Valueflows team members discuss and outline requirements for a modular & community-centered design process around OVN-compatible apps.
  • Q1 2017: Members from GoPacifica, FreedomCoop, Sensorica & Mikorizal begin to collaborate on unifying the multiple forks of NRP to a single generic codebase so that development effort can be shared.

General roadmap

This project is a continuation of the refactoring / genericisation work already started on the NRP codebase forks with the ultimate aim of bringing the focus of all projects back together and reducing effort required by all parties. It has three broad general aims:

  1. To iterate the frontend design of NRP, OCP & DEEP and achieve a more approachable and user-friendly interface to the software.
  2. To create a bedrock of modular, reusable UI components which can be recycled and adapted by other projects wishing to build interfaces to OVN systems.
  3. To further the understanding of the ValueFlows vocabulary and create more formal descriptions of higher-level concepts.

1. New user interface

The main goal here is to create a modern and beautiful web app which can target a variety of platforms. To achieve this, we've chosen to use React for its simplicity, large ecosystem of contributors, modular design philosophy and platform-agnostic architecture.

The core app will be built to work across web, mobile and desktop environments; and all will share the same codebase. Platform-specific features will be implemented using Webpack loaders to import different modules at compile-time (simply name components as *.js, *.android.js, *.ios.js etc). Areas of the application which will need to target specific platforms include:

  • Views (src/components). Web-based views are implemented by default; equivalent mobile app views are implemented with React Native components. By working at the component level it becomes much simpler to create consistent interfaces across the different platforms.
  • Routing (src/routes.js). React Router handles all routing for the app when run on the server (to pre-render pages) or in the browser. In native versions we will probably use the native version of react-router rather than the built-in Navigator classes of react-native for consistency with the web-based apps.
  • Build system. The React Native build system is far more complicated than a web build, but can easily coexist alongside it. Desktop apps can be built using Electron using the same source files as for web. There will be subtly different Webpack configurations for the web, mobile and desktop apps; but all will share the same core configuration. In this way we should be able to setup multiple NPM scripts to target the different platforms that are easy enough for anyone familiar with the tools to run.

For more info on some of the libraries and techniques used in this app, see learning material at the end of this page.

2. Modular UI components

We want UI elements to be built as self-contained modules which can easily be published separately to the main app and used in other projects.

Implementation concerns

Theming should be done via the style layer. Against use of React context:

[...] putting everything into your single point of context is just like making a big global variable which is pretty much what all the new CSS/CSS-in-JS solutions are trying to fix.

https://github.com/elementalui/elemental/issues/53#issuecomment-143745987

Given this, a factory pattern for injecting styles seems the only viable approach. Rethemeable and react-css-themr are common solutions which use context for theming, but passing themes in this fashion should be achievable with some creating scripting of the node module API.

Theming should output real CSS stylesheets instead of inline styles. Against inline JS styles:

  • No style fallbacks can be used (you can't define the same property twice). We want something like autoprefixer to run automatically as well.
  • Media & element queries don't work well.
  • CSS classes are faster than inline styles.
  • Stylehsheets lever browser caching, download parallelisation and reduce FOUC. Inline styles break caching & make initial download times longer.

Custom themes should be easily injectable:

React-themeable currently seems like the best approach for achieving this.

Default theme should be easily customisable:

We need to split up the style layer so that we can inject configuration into it to easily change pallete styles & other simple reconfigurations.

Should be agnostic to style language / CSS preprocessor:

The app currently implements cssnext via PostCSS plugins, but could easily support SASS, LESS or a combination thereof via additional PostCSS plugins. We've tried to configure things in such a way as to allow use of other preprocessors in future if desirable.

Authoring guidelines

  • Create each UI view component in its own folder.
  • Keep all dependencies (styles, images, fonts) bundled in the same folder as the component.
  • Include tests for the component within the folder as well (test framework still needs to be finalised- see #7)
  • Include a base version of the component that can be included without styles, a version that can be easily themed by overriding some control variables, and a version that has a full theme pre-bundled with it.

Here's a blueprint for your component folder:

  • Component- this will be the name of your component as included by other files.
    • Component.js- an unstyled component which accepts a react-themeable themes key.
    • Component.css- base cssnext stylesheet, without configuration vars. This allows child themes to reuse the base styles but include their own variable overrides for simple theming.
    • index.js- a fully styled component as the default export. Should take the compiled class name mappings from index.css and apply the theme to the component, see src/components/themed.js.
    • index.css- full theme styles for the component. Will mostly just load base theme variables & component-specific variables before bringing in styles from Component.css.
    • vars.css- if your component has theme-related configuration variables, separate them into their own file here so that child themes can include their own version.
    • Component.test.js- unit tests for the component. At minimum a single 'render' test should be provided.

:TODO: document react-storybook config

Further reading

3. ValueFlows vocabulary and APIs

A part of developing this project will be expanding the API component of the OVN apps to expose the necessary data. The plan is to use this process as a way of surfacing the key information required to run an OVN system; as well as exposing more of the Valueflows vocabulary in a formal implementation that is self-documenting and true to the model.

It is expected that a GraphQL-based API is the most appropriate approach for fulfilling these requirements. It would give us built-in support for easily querying entity relationships across relationship graphs, a concept that the OVN apps are heavily based on. The work has been started in a feature branch of OCP but has a very long way to go! django-graphene offers us the following possibilities:

  • Distinct binding between graph types and internal models, to provide insight into how external entites from the Valueflows vocabularies map to internal OVN system types, database tables etc.
  • Custom filtering keywords and logic can be bound to graph types, which allows us to easily build up useful searching options on top of the raw data structures.
  • Entity relationships are also defined in the graph types, providing detailed and accessible insight into the wider structure of the Valueflows vocabs and OVN system core.

We should also attempt to use the API to generate RDF-compatible output so that it can become the central resource for communicating data between multiple OVN apps located on different servers- though this may be better done by other means more directly provided by Graphene.

On the client side, things can be integrated relatively easily with Apollo, or GraphQL requests can be sent as regular POSTs and the response data managed manually if necessary. We probably wouldn't choose Relay due to its opinionated conventions and separation from Redux- Apollo looks easier to integrate with client-side application state.

Learning material

There's a lot of new tech underpinning this project, and though modularity is great it can also mean there are a daunting array of things to learn. Following is a list of some helpful learning material and background info on some of the more complicated pieces. This may be especially useful for Python developers or those unfamiliar with the React ecosystem.

ES6 & ES7

These are the modern updates to JavaScript, if you haven't heard of them then you probably know 'classic' JavaScript (ES5). They add a host of convenience features and powerful new syntax.

New syntax

In brief: https://github.com/lukehoban/es6features

Promises, Generators and Async/Await

Three different specs added to ES6 & ES7 which create more modern means of handling asynchronous behaviour.

React

React implements the UI layer of our application. It's rather a departure from the ways you may have developed web applications with pure HTML, CSS and JavaScript before, so getting up to speed on its approach is important.

The recommended pattern for building React applications is via composable views. Since a view is usually just a pure function which transforms data into a DOM structure, composing React views works very much the same as functional composition.

Redux

Redux is the data layer of the application- it has evolved from previous architectures loosely dubbed "Flux", though bears little similarity to them. Essentially it is a convention-enforcing library which implements a one-way dataflow between the UI and application data. It can be summarised by three points:

  • There is a single source of truth for all data in your UI, or if you prefer the "application state". Redux calls this the store.
  • Application state (the data in the store) is read-only. It can only be changed by emitting actions from the UI.
  • Changes to the application state are made by reducers. Reducers are exactly like a 'reducer' or 'fold' that you may be familiar with from functional programming concepts. Reducers accept the previous state & an emitted action, and return a new application state.

This architecture gives you many benefits such as reduced complexity, easier debugging and the ability to time-travel backwards through your application state in order to reproduce previous events. The best place for understanding Redux is the official site.

You may also be interested in some thoughts on testing React + Redux applications.

On top of Redux, many additional features are possible. If you know nodejs already, you can think of Redux as being somewhat similar to 'Express.js for UI data'- it is a very lightweight framework which can have middlewares added to build other features on top of. Some of the core pieces used in our app:

  • Redux saga gives us a defined and simple way of managing asynchronous actions.
  • Redux thunk is some simple middleware to allow returning functions as actions from the UI. The function will be executed until an action object is eventually dispatched. Note that sagas could be implemented directly on thunks- they are a lower-level concept that allows many things to be more readily integrated with Redux.
  • more to come as things evolve...

Webpack

Webpack is the build system which compiles our app for distribution. Pity the fool who ever has to deal with it, because configuration is often complex and arduous. Webpack itself is a continually moving target and you'll probably be building with alpha software at some point.

But that said, once development has started in earnest you should never have to deal with it again.

Webpack is just the build tool- roughly equivalent to 'make'. It's the things you add to your build pipeline (loaders) which do the actual work. Here are some of the more important ones:

  • Babel- transpiles ES7 JavaScript to ES5 in order to run in older browsers, by a process known as bundling. Babel by itself doesn't do anything without its plugins and presets:
    • babel-preset-react allows Babel to compile JSX for React.
    • babel-preset-stage-1 enables most of the modern ES6/7 functionality.
    • react-hot-loader/babel allows files handled by babel to be live-reloaded into the DOM as your code changes.
    • ...more to come...
  • PostCSS, postcss-loader, css-loader and style-loader- these all work together to handle compiling CSS. This means you can simply import CSS in your JavaScript modules directly to describe dependencies between UI components and their styles. The use of these loaders is an example of loader chaining- first postcss-loader is run to compile as standard CSS, then css-loader compiles the styles into a CSS module, and this is injected into the running webpage as a style tag by style-loader. PostCSS can support many types of CSS preprocessors so using it means we are free to choose what is appropriate / familiar.
  • extract-text-webpack-plugin does stuff to pull text out of your main bundle and save it elsewhere. We use it to write css into a *.css file separately to the application JS.
  • The more basic loaders such as url-loader, file-loader, yaml-loader etc allow us to reference and use other assets easily in our JavaScript modules. Usually there is some appropriate behaviour based on the type of import- for example, file-loader copies the file to Webpack's build directory and returns a resolved URL to reference the file; yaml-loader returns the contents of the YAML file as JSON, svg-react-loader imports SVG files directly as React components, and so on.
  • webpack-isomorphic-tools provides a layer to prevent resources only relevant on the client side (CSS, images etc) from crashing when encountered on the server. Usually this just means the files are ignored as the server doesn't care about rendering styles & images.
Clone this wiki locally