Odoo Elm app

I had a couple of cases where I had to implement a custom user interface on top of Odoo. In both of them the requirement was for a specialized app that can be used on a tablet. My initial approach was to use the Odoo JS framework but even then I didn’t like to make manual updates to the DOM using jQuery which is the default approach if you were to follow it. This was early 2016 and React was a quite popular virtual DOM library and still is. I decided to use it instead of the frontend templating system in Odoo and do the actual rendering with it while the Odoo JS framework will handle all RPC calls and instanciate the widgets. This turned out quite nicely as I had all tools of Odoo JS at my disposal (like translations, RPC functions, etc.) and I was able to make a more predictable UI using React. However the development experience was not the greatest and I wasn’t able to use the available tooling for frontend applications, like npm for handling dependencies and webpack for bundling the application. In my last attempt I went with making a web client which is separate from Odoo using what I think is a more streamlined frontend workflow. This is basically what I want to present in this post which will show how you can go about making a web app that will be highly maintanable thanks to the rich toolset available for frontend development. I will show how to do a basic ToDo app using Elm, webpack and npm, which will integrate with Odoo’s Notes module. If you haven’t heard of Elm it is a deligthfull language that compiles to JS and enables to make highly maintanable applications. Almost all errors are caught at compile time and you only need to worry about and test the functionality of your app. Also the complier gives you really user friendly messages and how you can go about and fix the errors.

Development setup

We will be not be doing anything fancy with webpack so instead of configuring it directly we are going to use create-elm-app which is a wrapper around webpack and some other tools and gives a nice default configuration that will be enough for us.

$ npm install create-elm-app -g
$ create-elm-app odoo_todo
$ cd odoo_todo
$ elm-app start

The default app will open automagically in your default browser. While the development server is started, any changes to the source files will trigger a recompile and the browser will refresh. That is a tight feedback loop!

Now we need to add Odoo into the mix. We will go with a docker setup and have a proxy in front so that requests from the app will be routed to the odoo server on the same socket (host + port). This is to prevent cross origin policy errors which will appear if we were to make requests to odoo from a different local port and for sharing the session cookies to enable authenticated requests.

We will add a docker-compose.yml manifest in a new dir.

$ cat odoo_elm/docker-compose.yml
version: '2'

services:
  web:
    image: nginx
    network_mode: host
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/nginx.conf
  odoo:
    image: odoo:12.0
    depends_on:
      - db
    ports:
      - "8069:8069"
      - "8072:8072"
    links:
      - db
    volumes:
      - attachments:/var/lib/odoo
      - .:/mnt/extra-addons
    command: ["odoo", "-d", "odoo", "-i", "note"] # install note (ToDo) module by default
  db:
    image: postgres:10
    environment:
      - POSTGRES_USER=odoo
      - PGUSER=odoo
      - POSTGRES_DB=odoo
      - PGDATA=/var/lib/postgresql/data/pgdata
    volumes:
      - data:/var/lib/postgresql/data
volumes:
  attachments:
    driver: local
  data:
    driver: local

The manifest declares the service stack: nginx proxy, odoo, postgres. They are all using the official vendor images. The nginx proxy runs in host mode which binds it to the host network instead of the dedicated docker network. This so that it can proxy to the webpack development server which is running outside of the docker network. The service configuration for odoo and postgres configuration is pretty straighforward and there is nothing intersting there. Next we will add the custom nginx configuration that will override the default one.

$ cat odoo_elm/nginx.conf
server {
    listen 8000 default_server;

    server_name localhost;

    location / {
        proxy_pass http://localhost:8069;
    }
   
    location /longpolling {
        proxy_pass http://localhost:8072;
    }

    location /elm_app {
        proxy_pass http://localhost:3000;
    }

    location /logo.svg {
        proxy_pass http://localhost:3000;
    }

    location /static/js/bundle.js {
        proxy_pass http://localhost:3000;
    }

    location /static/js/vendors.chunk.js {
        proxy_pass http://localhost:3000;
    }

    location /static/js/main.chunk.js {
        proxy_pass http://localhost:3000;
    }

    location /manifest.json {
        proxy_pass http://localhost:3000;
    }

    location ~ .hot-update.js$ {
        proxy_pass http://localhost:3000;
    }

    location ~ .sockjs.bundle.js$ {
        proxy_pass http://localhost:3000;
    }

    location ~ ^/sockjs-node. {
        proxy_pass http://localhost:3000;
    }
}

The configuration specifies the routes that should be forwarded to the webpack development server and all other should be sent to Odoo. Both the Odoo and the Elm app will be accessable on port 8000 and they can communicate with eachother without triggering the cross origin policy.

Now do:

$ docker-compose up

Congrats! Now you have a running development environment for your Odoo-Elm app.

In my next post I will go over the implementation of the actual app using this setup and give a basic overview of Elm.


842 Words

2019-07-31 17:00 -0700