Difference between revisions of "Hooli"

From mn/ifi/inf5750
Jump to: navigation, search
(Architecture)
 
(25 intermediate revisions by 2 users not shown)
Line 6: Line 6:
  
 
==Project==
 
==Project==
[https://wiki.uio.no/mn/ifi/inf5750/index.php/Master_Facility_List Master Facility List]
+
[https://wiki.uio.no/mn/ifi/inf5750/index.php/Master_Facility_List Master Facility List]  
  
[https://github.uio.no/Hooli/master-facility-list GitHub repository] ([http://www.hooli.xyz/ Hooli] )
+
[https://github.uio.no/Hooli/master-facility-list Github Repository]  
  
 
==Product descriptions requirements==
 
==Product descriptions requirements==
  
[[File:hooli_browse.png|450px|right|thumb|the browse view for the organisation unit]]
+
<div style="display: flex; flex-direction: column;">
 +
<div>
 +
=== Design ===
 +
[[File:hooli_wireframe.jpg|450px|right|thumb|First wireframe of the project]]
 +
 
 +
The app is split into two main views: a '''user view'''; and an '''administrator view'''. This is realised through a form of tabs. The former is the view enabling users to search and browse information on the different organisation units; while the latter is the view displaying relevant proposals to the user (whom could be an administrator, or not – in which case it's empty) and providing them with a way to configure which metadata object values to display for organisation unit in which they manage.
 +
 
 +
The user view is again split into three columns: one for ''search and filter''; one for the list of '''query results'''; and one for the '''organisation profile''', which displays information on the user-selected organisation unit.  Clicking on a organisation unit from the query results displays its information in the profile column.
  
=== Users Features ===
+
Searching is done through a text field, filtering by organisation unit name. Further filtering is specified by adding tags corresponding to organisation unit groups and data sets. These are added through another text field, which provides the user with suggestions based on the fields current value.
F1: All users should be able to get a list of all organisation units, and be able to search and filter on it. A user should be able to filter based on organisation unit name, organisation unit groups, data sets, and a combination of these.
 
  
F2: All users should be able to view an organisation unit's information—all attributes, as well as: GIS coordinates on a map, when available; membership in organisation unit groups; data sets, and indicator values (stats).
+
To propose changes for an organisation unit, a button is located on the organisation profile, which opens up a modal for proposing changes. To submit a proposal, the user need to fill out a title, an optional free-text description for further clarifications, and optional references to metadata objects.
  
F3: All users should be able to submit proposals for changes to the information of any organisation unit. These proposals should be stored for later inspection from an appropriate administrator[[File:hooli_adminview.png|450px|right|thumb|the admin view for proposals and configuration]]
+
The administrator view is split into three columns: one for selecting organisation unit; one for the '''proposal view''', which lists all proposals relevant to the selected organisation unit, and let's the user read their content as well as mark them as resolved/invalidated/pending; and one for the '''config view''', which allows them to select which metadata object values (and period) of the selected organisation unit to be up for display in its organisation profile.
 +
</div>
  
=== Admin Features ===
+
<div>
F4: Administrators should be able to view a list of submitted proposals for the organisation units in which they manage. I.e. administrators should only be able to see '''relevant proposals'''.
+
[[File:hooli_browse.png|450px|right|thumb|The user view for the organisation unit]]
  
F5: Administrators should be able to view the content of a submitted relevant proposal. I.e. display the proposed changes, and possibly optional comments as to why the changes should be made.
+
=== Users Features ===
 +
<i>F1</i>: All users should be able to get a list of all organisation units, and be able to search and filter on it. A user should be able to filter based on organisation unit name, organisation unit groups, data sets, and a combination of these.
  
F6: Administrators should be able to mark relevant proposals as resolved/invalid. Marked proposals should, by default, not be displayed to the administrators.
+
<i>F2</i>: All users should be able to view an organisation unit's information—all attributes, as well as: GIS coordinates on a map, when available; membership in organisation unit groups; data sets, and indicator values (stats).
  
F7: Administrators should be able to choose which data elements and indicators are to be displayed for a given organisation unit, in which they manage. Normal users will, then, only be able to see the chosen data elements, when trying to view the organisation unit's information.
+
<i>F3</i>: All users should be able to submit proposals for changes to the information of any organisation unit. These proposals should be stored for later inspection from an appropriate administrator
 +
</div>
  
[[File:hooli_wireframe.jpg|450px|right|thumb|first wireframe of the project]]
+
<div>
 +
[[File:hooli_adminview.png|450px|right|thumb|The admin view for proposals and configuration]]
  
=== Design ===
+
=== Admin Features ===
The app should be split into two main views: a '''user view'''; and an '''administrator view'''. This can be realized through a form of tabs. The former should be the view where all users may search and browse information on the different organisation units; while the latter should be the view displaying relevant proposals to the user (whom could be an administrator, or not—in which case it's empty)
+
<i>F4</i>: Administrators should be able to view a list of submitted proposals for the organisation units in which they manage. I.e. administrators should only be able to see '''relevant proposals'''.
 +
 
 +
<i>F5</i>: Administrators should be able to view the content of a submitted relevant proposal. I.e. display the proposed changes, and possibly optional comments as to why the changes should be made.
  
The user view should again be split into three columns: one for ''search and filter''; one for the list of '''query results'''; and one for the '''organisation profile''', which displays information on the user-selected organisation unit. Clicking on a organisation unit from the query results should display its information in the profile column.
+
<i>F6</i>: Administrators should be able to mark relevant proposals as resolved/invalid. Marked proposals should, by default, not be displayed to the administrators.
  
Searching should by done using a text field for the organisation unit name. And filtering can be further specified by adding tags corresponding to organisation unit groups and data sets. To add these tags, two combo boxes—with search—could be used. As for filtering on organisation unit hierarchy, this will have to be further studied.
+
<i>F7</i>: Administrators should be able to choose which data elements and indicators are to be displayed for a given organisation unit, in which they manage. Normal users will, then, only be able to see the chosen data elements, when trying to view the organisation unit's information.
 +
</div>
 +
</div>
  
To propose changes for an organisation unit; one solution could be to have a button appear on the organisation profile, which opens up a modal for editing/proposing changes. The modal should have buttons for submitting and/or discarding the proposals, one for each.
+
==Architecture==
  
The administrator view can be split into two columns: one for the '''proposal list''', which lists all of the relevant proposals; and one for the '''proposal view''', which displays the text of proposed changes.
+
=== Microarchitecture ===
 +
The application is split into four main parts:
 +
* '''Components''' handle the app's presentation logic; it renders the different parts of the application based on global and local state, as well as dispatches actions on user-triggered events for modifying and fetching data.
  
For resolving and invalidating proposals; two button at the top-right corner of the proposal view should suffice.
+
* '''Reducers''' combine to hold the global state of the application, each reducer managing how actions affect its sub-state. We have chosen to separate our state into the following reducers: config; filters; organisationUnits; proposals; and user. In this way, the data is component agnostic and can be easily accessed from any component.
  
<br />  <br />  <br />  <br />
+
* '''Actions''' are functions which can be called to handle side-effects. They are mainly used by components to trigger changes in the global state, but may also be dispatched through other actions. The majority of our actions are async, as most are meant to either fetch or modify data through the DHIS2 api.
  
==Architecture==
+
* '''API''' is a set of functions for accessing the DHIS2 API, providing an interface for the actions to use. This separates the data-access logic from the application logic.
All components should be dumb—be fed information from the global state.
+
This separation is reflected in our folder structure, with each part having its own folder inside the ''src'' folder. Components are the only ones, who have sub-hierarchies – with related components grouped together. Each hierarchy consists of components with their accompanying stylesheets and tests placed into folders named ''styles'' and ''___tests___'', respectively.
  
Data should only be fetched when needed (i.e. on demand), e.g. when the search
+
This microarchitecture follows the "React way" of designing applications, through the MVVM pattern.
query changes, or the user selects an organisation unit or proposal to view.
 
  
Proposals and configurations should be stored in the app's dataStore namespace:
+
=== Data Store ===
 +
Proposals and configurations are stored in the app's dataStore (the namespace is set to "master-facility-list-hooli"):
 
     {
 
     {
         proposals: [
+
         proposals-<organisationUnitId>: [
 
             {
 
             {
                 id: [organisationUnitId],
+
                 id: <organisationUnitId>,
                 submitted: [dateSubmitted],
+
                 created: <dateSubmitted>,
                 status: ["pending"|"resolved"|"invalid"],
+
                lastUpdated: <lastModifiedDate>,
                 changes: [textOfProposedChanges]
+
                 status: <"pending"|"resolved"|"invalid">,
             }
+
                title: "<title">
 +
                description: "<textOfProposedChanges>",
 +
                dataElements: [<dataElementId>, ...],
 +
                 indicators: [<indicatorId>, ...]
 +
             },
 +
            ...
 
         ],
 
         ],
         configurations: {
+
         config-<organisationUnitId>: {
             [organisationUnitId]: {
+
             period: <"current"|"previous">,
                dataElementSets: [
+
            dataElements: [<dataElementId>, ...],
                    [dataElementId]
+
            indicators: [<indicatorId>, ...]
                ]
 
            }
 
 
         }
 
         }
 
     }
 
     }
  
 +
Due to the Data Store being a key-value store, the app is required to handle some data-access logic. The above naming-scheme was designed to strike a balance between the amount of information retrieved on each request, and the number of requests needed to collect all the necessary information. This design is optimised for the common use case of our application, where proposals and configurations are fetched per organisation unit. Since we're always fetching all proposals for an organisation unit, this might pose a problem when the number of proposals grow bigger. Another concern, is the possibility of race conditions, but this can be mitigated with the use of Etags, which we have yet to make use of.
  
===Frameworks===
+
As can be seen from above, proposals are stored as objects in an array. Another choice would be to store them in an object with their id as key. This would a provided a better look-up time when changing a specific proposal however, we chose against this as it would make it harder for other  non-javascript applications to serialise and parse the data. As we are not sure of what DHIS2 could think of doing with our data, we stuck with the safer choice. This is also the same format that the DHIS2 API uses.
* [https://reactjs.org/ React] - We chose React mainly due to its popularity, giving it a larger ecosystem. Compared to the other two big frameworks (Vue.js, Angular), we followed Goldolick's rule and chose React as it strikes a balance between simplicity (ease of learning) and scalability.
+
 
 +
Another design choice worth noting is that we only store references through IDs. This was intentional to avoid duplicating and storing redundant data, possibly leading to data integrity issues and unreliability when the referenced objects might change (e.g. metadata objects having their names changed). Such a change probably won't happen too often, but we wanted to avoid taking that risk. However, the data store cannot resolve such references by itself, and the trade-off is therefore that the application has to make additional requests to resolve such references.
 +
===Core frameworks and libraries===
 +
* [https://reactjs.org/ React] - We chose React mainly due to its popularity, giving it a larger ecosystem. Compared to the other two big frameworks (Vue.js, Angular), we followed Goldilock's rule and chose React as it strikes a balance between simplicity (ease of learning) and scalability.
 
* [https://react.semantic-ui.com Semantic Css] - We needed a CSS framework to reduce the amount of styling, and chose Semantic as it had a library providing a lot of pre-made React components—and was pleasing to the eye.
 
* [https://react.semantic-ui.com Semantic Css] - We needed a CSS framework to reduce the amount of styling, and chose Semantic as it had a library providing a lot of pre-made React components—and was pleasing to the eye.
 +
* [https://github.com/tomchentw/react-google-maps react-google-maps] - We chose this instead of the GIS map plugin provided by DHIS2, as it fit better in with React. We also noted that the DHIS2 plugin was licensed under GPL, something  we tried to avoid.
  
 
==Division of work==
 
==Division of work==
Line 87: Line 111:
  
 
==Licensing==
 
==Licensing==
React and Semantic are both licensed under MIT, and so are all of our other dependencies. Therefore, we were free to license our project under any license, and chose MIT to remain open source and not restrict derivative works.
+
React and Semantic are both licensed under [https://opensource.org/licenses/MIT MIT], and so are all of our other dependencies. Since [https://opensource.org/licenses/MIT MIT] is an open source and permissive license, we were pretty much free to choose our own license. After a round of discussion, we agreed to keep our project open source and not restrict possible derivative works. As such, we chose to license our own work under the [https://opensource.org/licenses/MIT MIT] license too. By open-sourcing it, we enable anyone to further develop this application if they so desire. This is important as we will only be working on this for the group project.
  
==Timeline==
+
==Milestones==
 
===Week 43===
 
===Week 43===
 
* Studied requirements
 
* Studied requirements
Line 119: Line 143:
 
===Week 48===
 
===Week 48===
 
* The week where we actually do stuff
 
* The week where we actually do stuff
 +
 +
'''Note''': bug fixing lasted until the day before the deadline.

Latest revision as of 21:53, 5 December 2017

Group members

  • Sharanan Kulam (sharanak@ifi.uio.no)
  • Jagat Deep Singh (jagatds@ifi.uio.no)
  • Tin Anh Nguyen (tinng@ifi.uio.no)
  • Son Thanh Vo (sontv@ifi.uio.no)

Project

Master Facility List

Github Repository

Product descriptions requirements

Design

First wireframe of the project

The app is split into two main views: a user view; and an administrator view. This is realised through a form of tabs. The former is the view enabling users to search and browse information on the different organisation units; while the latter is the view displaying relevant proposals to the user (whom could be an administrator, or not – in which case it's empty) and providing them with a way to configure which metadata object values to display for organisation unit in which they manage.

The user view is again split into three columns: one for search and filter; one for the list of query results; and one for the organisation profile, which displays information on the user-selected organisation unit. Clicking on a organisation unit from the query results displays its information in the profile column.

Searching is done through a text field, filtering by organisation unit name. Further filtering is specified by adding tags corresponding to organisation unit groups and data sets. These are added through another text field, which provides the user with suggestions based on the fields current value.

To propose changes for an organisation unit, a button is located on the organisation profile, which opens up a modal for proposing changes. To submit a proposal, the user need to fill out a title, an optional free-text description for further clarifications, and optional references to metadata objects.

The administrator view is split into three columns: one for selecting organisation unit; one for the proposal view, which lists all proposals relevant to the selected organisation unit, and let's the user read their content as well as mark them as resolved/invalidated/pending; and one for the config view, which allows them to select which metadata object values (and period) of the selected organisation unit to be up for display in its organisation profile.

The user view for the organisation unit

Users Features

F1: All users should be able to get a list of all organisation units, and be able to search and filter on it. A user should be able to filter based on organisation unit name, organisation unit groups, data sets, and a combination of these.

F2: All users should be able to view an organisation unit's information—all attributes, as well as: GIS coordinates on a map, when available; membership in organisation unit groups; data sets, and indicator values (stats).

F3: All users should be able to submit proposals for changes to the information of any organisation unit. These proposals should be stored for later inspection from an appropriate administrator

The admin view for proposals and configuration

Admin Features

F4: Administrators should be able to view a list of submitted proposals for the organisation units in which they manage. I.e. administrators should only be able to see relevant proposals.

F5: Administrators should be able to view the content of a submitted relevant proposal. I.e. display the proposed changes, and possibly optional comments as to why the changes should be made.

F6: Administrators should be able to mark relevant proposals as resolved/invalid. Marked proposals should, by default, not be displayed to the administrators.

F7: Administrators should be able to choose which data elements and indicators are to be displayed for a given organisation unit, in which they manage. Normal users will, then, only be able to see the chosen data elements, when trying to view the organisation unit's information.

Architecture

Microarchitecture

The application is split into four main parts:

  • Components handle the app's presentation logic; it renders the different parts of the application based on global and local state, as well as dispatches actions on user-triggered events for modifying and fetching data.
  • Reducers combine to hold the global state of the application, each reducer managing how actions affect its sub-state. We have chosen to separate our state into the following reducers: config; filters; organisationUnits; proposals; and user. In this way, the data is component agnostic and can be easily accessed from any component.
  • Actions are functions which can be called to handle side-effects. They are mainly used by components to trigger changes in the global state, but may also be dispatched through other actions. The majority of our actions are async, as most are meant to either fetch or modify data through the DHIS2 api.
  • API is a set of functions for accessing the DHIS2 API, providing an interface for the actions to use. This separates the data-access logic from the application logic.

This separation is reflected in our folder structure, with each part having its own folder inside the src folder. Components are the only ones, who have sub-hierarchies – with related components grouped together. Each hierarchy consists of components with their accompanying stylesheets and tests placed into folders named styles and ___tests___, respectively.

This microarchitecture follows the "React way" of designing applications, through the MVVM pattern.

Data Store

Proposals and configurations are stored in the app's dataStore (the namespace is set to "master-facility-list-hooli"):

   {
       proposals-<organisationUnitId>: [
           {
               id: <organisationUnitId>,
               created: <dateSubmitted>,
               lastUpdated: <lastModifiedDate>,
               status: <"pending"|"resolved"|"invalid">,
               title: "<title">
               description: "<textOfProposedChanges>",
               dataElements: [<dataElementId>, ...],
               indicators: [<indicatorId>, ...]
           },
           ...
       ],
       config-<organisationUnitId>: {
           period: <"current"|"previous">,
           dataElements: [<dataElementId>, ...],
           indicators: [<indicatorId>, ...]
       }
   }

Due to the Data Store being a key-value store, the app is required to handle some data-access logic. The above naming-scheme was designed to strike a balance between the amount of information retrieved on each request, and the number of requests needed to collect all the necessary information. This design is optimised for the common use case of our application, where proposals and configurations are fetched per organisation unit. Since we're always fetching all proposals for an organisation unit, this might pose a problem when the number of proposals grow bigger. Another concern, is the possibility of race conditions, but this can be mitigated with the use of Etags, which we have yet to make use of.

As can be seen from above, proposals are stored as objects in an array. Another choice would be to store them in an object with their id as key. This would a provided a better look-up time when changing a specific proposal however, we chose against this as it would make it harder for other non-javascript applications to serialise and parse the data. As we are not sure of what DHIS2 could think of doing with our data, we stuck with the safer choice. This is also the same format that the DHIS2 API uses.

Another design choice worth noting is that we only store references through IDs. This was intentional to avoid duplicating and storing redundant data, possibly leading to data integrity issues and unreliability when the referenced objects might change (e.g. metadata objects having their names changed). Such a change probably won't happen too often, but we wanted to avoid taking that risk. However, the data store cannot resolve such references by itself, and the trade-off is therefore that the application has to make additional requests to resolve such references.

Core frameworks and libraries

  • React - We chose React mainly due to its popularity, giving it a larger ecosystem. Compared to the other two big frameworks (Vue.js, Angular), we followed Goldilock's rule and chose React as it strikes a balance between simplicity (ease of learning) and scalability.
  • Semantic Css - We needed a CSS framework to reduce the amount of styling, and chose Semantic as it had a library providing a lot of pre-made React components—and was pleasing to the eye.
  • react-google-maps - We chose this instead of the GIS map plugin provided by DHIS2, as it fit better in with React. We also noted that the DHIS2 plugin was licensed under GPL, something we tried to avoid.

Division of work

We used Trello to organize the features (listed above) into descriptive tasks and sub-tasks. Initially, we assigned primary tasks to each member. During every weekly meeting we discussed the progress for each assigned tasks (e.g. reviewing the code/pull-request, discussing challenges, etc...), and distributed the tasks from the backlog for the upcoming week.

General overview of labour distribution:

  • Thanh Son: Organisation filter and organisation config (F1, F7)
  • Sharanan: Organisation search and admin proposals (F1, F4, F5, F6)
  • Deep: Organisation profile (F2, F3)
  • Tin: Communication between the app and the DHIS2 API and app architecture (F7)

Licensing

React and Semantic are both licensed under MIT, and so are all of our other dependencies. Since MIT is an open source and permissive license, we were pretty much free to choose our own license. After a round of discussion, we agreed to keep our project open source and not restrict possible derivative works. As such, we chose to license our own work under the MIT license too. By open-sourcing it, we enable anyone to further develop this application if they so desire. This is important as we will only be working on this for the group project.

Milestones

Week 43

  • Studied requirements
  • Write wiki-page
    • Discussed framework and architecture
    • Setup time management
  • Setup project
  • Get familiar with react
  • Get familiar with DHIS2

Week 44

  • Implement search: organization unit
  • Implement filter: organization unit
  • implement display: organization unit

Week 45

  • Implement view: user proposing changes
  • implement view: admin reviewing proposals
  • Implement view: admin data display/configurations
  • Implement api for data store usage

Week 46

  • Feature extentions
  • Bug fixing

Week 47

  • Bug fixing

Week 48

  • The week where we actually do stuff

Note: bug fixing lasted until the day before the deadline.