Skip to content

bengler/imdikator

Repository files navigation

Imdikator frontend Build StatusDependency status

Application summary

The entire stand alone React front-end application for IMDi - Tall og Statistikk. Contains charting library based on D3 that supports Norwegian Central Bureau of Statistics conventions for missing and suppressed data.

Prerequisites

  • Node.js (v6.x or later)
  • npm (v3.x or later)

Getting started

npm install
npm start

Now the app should be up and running on http://localhost:3000

Contributing

TL;DR

Push to feature branch -> review -> merge to develop

/or/

  1. $ git checkout -b feature-name
  2. write code and commit
  3. $ git push origin feature-name
  4. open a pull request Pull Requests · bengler/imdikator · GitHub
  5. make someone review (or not)
  6. merge feature into branch develop

Detailed git rules

https://github.com/wearehive/project-guidelines#1-git

Important files

cardpages.json

-> Specifiaction against Visma backend. Name of pages = name of tables.

queryResultPresenter.js

-> Check data from Visma. (What the data looks like, how to present it etc)

chartTypes.js

-> mappings for how many dimensions each chart type allows

Application structure

├── /actions
│   ├── /ActionTypes.js        - Action constants used by actions/reducers
│   └── /*.js                  - Redux action creators
│
├── /bin
│   ├── / server.js             - SERVER: Starts express server - (ONLY FOR DEV)
│   ├── / *calculateSimilar.js  - Process data and find similar counties in terms of size/other data
│   └── / *.js                  - Various data processing helpers. Generates .json data files (OLD)
│
├── /bundles
│   ├── /debug                  - CLIENT: Local debug page available at `/debug/embeds/`
│   ├── /embeds                 - CLIENT: Renders the "embed" version of the app (allows multiple instances)
│   ├── /site                   - CLIENT: Renders the "site" version of the app (single instance)
│   └── / loader.js             - FIRST ENTRY - bootstraps application based on type(s) required
│
├── /components
│   ├── / *.jsx                 - React components (mixed)
│   └── /testbed                - Generate static markup (fake environment) since app is served as .js
│
├── /config
│   ├── /apiClient.js           - api client config
│   └── / *.js                  - other app config files
│
├── /data
│   ├── / *.json                - Data sources for app. Generated by the `/bin` helpers (or static)
│   └── / cardPages.json        - Specifiaction against Visma backend. Name of pages = name of tables
│
├── /import
│   └── / *.csv                 - Raw .csv data from SSB (Used by `/bin` processors)
│
├── /lib
│   ├── /api-client             - Collates API's into single point of access (VISMA, Episerver & local .json files)
│   ├── /http                   - (fetch implementation)
│   └── *.js                    - Utility helpers. (check tests for documentation)
│
├── /reducers
│   ├── / index.js              - Reducer combiner
│   └── / *.js                   - Redux reducers
│
├── /static-routes
│   └── / *.js                  - Defines the different bundles
│
├── /stylesheets
│   └── /bundles                - Used in dev/test mode (imports full stylesheet from node-modules)
│
├── /test
│   └── /                       - Test specs and runner config
│
└── /*                          - Project root

App initialisation

Here's how the app starts and hwo the tables are built from load to render, including where the data comes from.

1: loader.js runs and finds the api/data host based on the div with id #imdikator-loader in the document in which Imdikator is included.

2: loader.js checks if Imdikator should run in site or embed mode depending on what data-attribute the root div has ([data-imdikator=site] or [data-imdikator=embed])

3: Finally, loader.js loads the right version of Imdikator into the document. (site.js or embeds.js).

4: Next, the site.js or embeds.js file will be loaded through ajax and initialise the Imdikator react app.

5: Now the app can start and will have the URL of the apiHost and the contentApiHost available through the window element.

  • apiHost is the database where all table data is fetched from
  • contentApiHost is the episerver endpoint where table variables are gotten from (example: innvkat_4 = "Innvandrere under 16 år")

6: The starting point for each of two versions of Imdikator is the entry.jsx file in the bundles folder. Here the react app is initialised in the correct div and routing is setup. The file first runs loadInitialState which gets region and cardPage data from the api/local files, and then afterwards runs bootstrap which starts the react app and initialises the Redux store.

Data flow

All data is fetched through the lib/api-client file, which exposes a set of functions used throughout the app to get data from all available sources.

The data fetching is driven by the URL. Once a user lands on a page, it will be matched in the bundles/site/routes file and depending on the route, an action will be dispatched to Redux to fetch the required data. (example: loadCardsPage for a card page and openCard for a card)

  • A cardPage is a main category page, for example "Befolkning og bosetting"
  • A card is a single table/chart within a cardpage, for example "Sammensetning av befolkning"
  • The structure and hirarchy of these are all configured in cardPages.json.

D3.js

The perfect tutorial to learn how d3 is used throughout this code: http://alignedleft.com/tutorials/d3/binding-data

  • Card.jsx === A charts outer wrapper containing filters, print buttons with it's filters. Every chart uses this as a parent
  • BarChart/PyramidChart/BubbleChart/etc.../.jsx === unique d3 configuration for a specific type of chart. This is the unique file for every type of (bubble, stacked, bar) chart
  • D3Chart.jsx AND _d3chart.js === a generic initializer for every d3 instance. All d3 configuration that is applied on all charts goes here. If you want to pass props to a Chart - you have to pass it from Card.jsx to every chart you want to use, e.g BarChart and pass it down to D3Chart's componentDidUpdate() inside the this.chart.update(overload this function with the props) and repass it through _d3chart.js constructor and append it to this.update(). Yikes.

git

  • Make a local feature branch $ git checkout -b add-barchart and $ git push origin add-barchart
  • Merge the pull requests into master
  • Place the folder imdikator-deploy (ask tobias or bård) as a sibling to the local imdikator folder and push to test with the test script inside imdikator deploy package.json
  • Make a comment in jira with the commit hash that has been published to test, so when the test is accepted, roll back to this commit and run imdikator deploy's production script.

Hvordan å legge til nye steder som f.eks kommunenr?

Når det må gjøres endringer i kommuner eller fylker må man oppdatere statistikken. Slik gjør du, enkelt oppsummert:

  1. IMDi overleverer et nytt komplett datasett til Netlife, som inneholder de nye stedene. La oss bruke regioninndeling-fylker-kommuner.csv som et eksempel.
  2. Netlife erstatter /import/regioninndeling-fylker-kommuner.csv med det nye.
  3. Netlife kjører kommandoen npm run import-regions deretter npm run calculate-similar
  4. That’s it.

Deployment

For å deploye til test/prod må du ha prosjektet Imdikator-deploy lokalt, og i samme mappe som imdikator (ikke inne i imdikator).

For å deploye til test: npm run deploy_test

For å deploye til produksjon: npm run deploy

URL's

Test og prod

Innhold fra episerver

Other notes

  • babel polyfill is Included in bundle.