Skip to content
Ivan Arrizabalaga Getino edited this page Oct 18, 2016 · 4 revisions

Goal

The main goal of this app is to serve a shortcut to deal with datasets in a quicker manner.

It is a react (https://facebook.github.io/react/) based app

React quick tips

React is NOT a full MVVM framework (like angularjs), it is supposed to deal with just the VIEWS (there could be a much longer discussion in this point but this is the official claim).

In order to deal with the views react proposal is dealing with Components (like angular2, jsf, taglibs) aggregated one on top another.

Recommended tutorial (https://scotch.io/tutorials/learning-react-getting-started-and-concepts)

SPECS, LIFECYCLE & STATE

The render method is the only required spec for creating a component, but there are several lifecycle methods & specs we can use that are mighty helpful when you actually want your component to do anything.

LIFECYCLE METHODS

  • componentWillMount – Invoked once, on both client & server before rendering occurs.
  • componentDidMount – Invoked once, only on the client, after rendering occurs.
  • shouldComponentUpdate – Return value determines whether component should update.
  • componentWillUnmount – Invoked prior to unmounting component.

SPECS

  • getInitialState – Return value is the initial value for state.
  • getDefaultProps – Sets fallback props values if props aren’t supplied.
  • mixins – An array of objects, used to extend the current component’s functionality.

STATE

Every component has a state object and a props object. State is set using the setState method. Calling setState triggers UI updates and is the bread and butter of React’s interactivity. If we want to set an initial state before any interaction occurs we can use the getInitialState method.

#Structure Our app so far follows this hierarchy of components

App
  HeaderBar
  <!-- Floating action button -->
  ListActionBar
  SinglePanelLayout
    MainContent
      <!--Search field -->
      SearchBox
      Pagination
      LoadingStatus
      <!-- List of datasets -->
      DataTable

#i18N In order to translate strings you must consider:

  • i18N is a utility packed with d2, it is configured in the app.js where the properties files are loaded.

app.js

function configI18n(userSettings) {
    const uiLocale = userSettings.keyUiLocale;

    if (uiLocale !== 'en') {
        // Add the language sources for the preferred locale
        config.i18n.sources.add(`./i18n/i18n_module_${uiLocale}.properties`);
    }

    // Add english as locale for all cases (either as primary or fallback)
    config.i18n.sources.add('./i18n/i18n_module_en.properties');
}
//...
getManifest('./manifest.webapp')
.then(manifest => {
    const baseUrl = process.env.NODE_ENV === 'production' ? manifest.getBaseUrl() : dhisDevConfig.baseUrl;
    config.baseUrl = `${baseUrl}/api`;
})
.then(getUserSettings)
.then(configI18n)
.then(init)
.then(startApp)
.catch(log.error.bind(log));
  • Those property files are loaded dinamically from the d2 boostrap function (init), thus the webpack.config.js and the package.json have been modified copy and serve those files under the i18n folder.

webpack.config.js

devServer: {
    progress: true,
    colors: true,
    port: 8081,
    inline: true,
    compress: true,
    proxy: [
        ...
        { path: '/i18n/*', target: 'http://localhost:8081/src', bypass: log },
    ],
}

package.json:

"scripts": {
    "postbuild": "cp src/i18n build/ ..."
    ...
}
  • Any component with Translate mixin gets a getTranslation function that it is the only you must use in order to translate your strings. That mixin assumes your component can access to context.d2 so your root component cannot add that mixin.

SearchBox.component.js import Translate from 'd2-ui/lib/i18n/Translate.mixin'; ...

const SearchBox = React.createClass({
    ...

    mixins: [ObservedEvents, Translate],

    ...

    render() {
        return (
            <div className="search-list-items">
                <TextField
                    hintText={`${this.getTranslation('search_by_name')}`}
                />
            </div>
        );
    }
}    

#Useful links

  • d2: d2 js library that wraps every dhis2 endpoint to ease js development.
  • d2-ui: a set of ui components (based on material-ui project ) that should be reused to build dhis2 apps.

#Changing credentials for development database

While working in development you will use the default account (admin/district) anytime you rely on the d2 api. This is just fine but you're going to need something different when your db does not have that account or the password is different from the default one.

webpack.config.js:

dhisConfig = {
    baseUrl: 'http://localhost:8080',
    authorization: 'Basic YWRtaW46ZGlzdHJpY3Q=', // admin:district
};

That YWRtaW46ZGlzdHJpY3Q= string corresponds to the base64 of admin:district so in order to change those credentials you need to encode your "user:password" using base64.

In javascript this is really simple, just open your console and type:

btoa("admin:district")
Clone this wiki locally