diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..ea3c2059
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+*.iml
+*.zip
+
+node_modules
+jspm_packages
+
+.sass-cache
+build
+
+
diff --git a/gulpfile.js b/gulpfile.js
new file mode 100644
index 00000000..344f76ad
--- /dev/null
+++ b/gulpfile.js
@@ -0,0 +1,86 @@
+'use strict';
+
+const BUILD_DIR = 'build';
+
+const gulp = require('gulp');
+
+gulp.task('clean', function (cb) {
+ var del = require('del');
+
+ del(BUILD_DIR, cb);
+});
+
+gulp.task('build-deploy', function (cb) {
+ var runSequence = require('run-sequence');
+ runSequence('clean', ['app', 'pack', 'deps', 'sass'], 'deploy');
+});
+
+gulp.task('build-prod', function (cb) {
+ var runSequence = require('run-sequence');
+ runSequence('clean', ['app', 'pack', 'deps', 'sass'], 'zip');
+});
+
+gulp.task('zip', function () {
+ var zip = require('gulp-zip');
+
+ return gulp.src(['./build/**'])
+ .pipe(zip('where-is-my-mechanism.zip'))
+ .pipe(gulp.dest('.'));
+});
+
+gulp.task('pack', function (cb) {
+ var Builder = require('systemjs-builder');
+ var builder = new Builder({});
+
+ builder.loadConfig('./src/config.js')
+ .then(function () {
+ builder.config({
+ paths: {
+ 'json': './src/*.js',
+ 'app': './src/*.js'
+ },
+ meta: {
+ 'manifest.webapp!json': { build: false},
+ 'manifest.webapp': { build: false}
+ }
+ });
+
+ return builder.build('app', BUILD_DIR + '/wimm.js', { minify: true, mangle: false, sourceMaps: true })
+ .then(function () {
+ cb();
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ });
+});
+
+gulp.task('app', function () {
+ return gulp.src([
+ 'src/**/*.{html,png}',
+ 'src/config.js',
+ 'src/manifest.webapp'
+ ])
+ .pipe(gulp.dest(BUILD_DIR));
+});
+
+gulp.task('deps', function () {
+ return gulp.src(['jspm_packages/*'])
+ .pipe(gulp.dest([BUILD_DIR, 'jspm_packages'].join('/')));
+});
+
+gulp.task('sass', function () {
+ var rubySass = require('gulp-ruby-sass');
+ return rubySass(['./src/app.sass'], {loadPath: './src', style: 'expanded', compass: true})
+ .on('error', function (err) {
+ console.error('Error!', err.message);
+ })
+ .pipe(gulp.dest(
+ [BUILD_DIR, 'css'].join('/')
+ ));
+});
+
+gulp.task('deploy', function () {
+ return gulp.src(['./build/**'])
+ .pipe(gulp.dest('/Users/markadm/Projects/dhis/DHIS2_HOME/apps/where-is-my-mechanism'));
+});
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..d3e2d677
--- /dev/null
+++ b/package.json
@@ -0,0 +1,36 @@
+{
+ "name": "where-is-my-mechanism",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": "Mark Polak",
+ "license": "BSD",
+ "jspm": {
+ "directories": {},
+ "configFile": "src/config.js",
+ "dependencies": {
+ "angular": "npm:angular@^1.4.0",
+ "jquery": "github:components/jquery@^2.1.4",
+ "systemjs/plugin-json.git": "github:systemjs/plugin-json@^0.1.0"
+ },
+ "devDependencies": {
+ "babel": "npm:babel-core@^5.1.13",
+ "babel-runtime": "npm:babel-runtime@^5.1.13",
+ "core-js": "npm:core-js@^0.9.4"
+ }
+ },
+ "devDependencies": {
+ "del": "^1.2.0",
+ "gulp": "^3.8.11",
+ "gulp-dev": "0.0.2",
+ "gulp-ruby-sass": "^1.0.5",
+ "gulp-zip": "^3.0.2",
+ "systemjs-builder": "^0.10.6"
+ },
+ "dependencies": {
+ "babel": "^5.4.7"
+ }
+}
diff --git a/src/app.js b/src/app.js
new file mode 100644
index 00000000..af35e12c
--- /dev/null
+++ b/src/app.js
@@ -0,0 +1,169 @@
+'use strict';
+import 'jquery';
+import angular from 'angular';
+
+import manifest from 'manifest.webapp!json';
+
+class WhereIsMyMechController {
+ constructor($http, $scope, $location) {
+ this.headerMap = {
+ Date: 'Date',
+ OperatingUnit: 'OU',
+ FiscalYear: 'FY',
+ PlanningReportingCycle: 'Reporting Cycle',
+ HQMechanismID: 'HQ ID',
+ LegacyMechanismID: 'Legacy ID',
+ ImplementingMechanismName: 'IM',
+ FundingAgency: 'Funding Agency',
+ PrimePartner: 'Prime Partner',
+ PrimePartnerID: 'Partner ID',
+ StartDate: 'Start Date',
+ EndDate: 'End Date',
+ Active: 'Active'
+ };
+
+ this.myMechanismSearchString = '';
+ this.api = $http;
+ this.datimInfo = {};
+ this.location = $location;
+
+ $scope.$watch(() => this.myMechanismSearchString, (newVal, oldVal) => {
+ if (newVal !== oldVal) {
+ this.search();
+ }
+ });
+
+ //Set the predefined search if we have one and run the search against the server
+ if ($location.$$search.query) {
+ this.myMechanismSearchString = $location.$$search.query;
+ this.search();
+ }
+ }
+
+ setSearchString(value) {
+ this.myMechanismSearchString = value.replace(/\"/g, '').trim();
+ }
+
+ search() {
+ //Reset found flags
+ this.foundInDatim = false;
+ this.foundInFactsInfo = false;
+ this.datimInfo = {};
+
+ this.location.search('query', this.myMechanismSearchString);
+
+ this.api.get('//sync.datim.org:1777/?search=' + this.myMechanismSearchString)
+ .then(this.buildResultList.bind(this))
+ .then(this.setResultList.bind(this))
+ .then((resultList) => {
+ if (resultList.length > 0) {
+ this.foundInFactsInfo = true;
+ return resultList[0];
+ }
+ return [];
+ })
+ .then(this.loadDATIMMechanism.bind(this));
+ }
+
+ buildResultList(response) {
+ let lines = response.data;
+ let headers = lines.shift();
+
+ return {
+ headers: headers,
+ lines: lines
+ .map(line => {
+ line[line.length - 1] = parseInt(line[line.length - 1], 10);
+ return line;
+ })
+ };
+ }
+
+ setResultList(resultList) {
+ if (!this.headers) {
+ this.headers = resultList.headers;
+ }
+ this.resultList = resultList.lines;
+
+ return this.resultList;
+ }
+
+ loadDATIMMechanism(firstRow) {
+ if (firstRow) {
+ this.datimMechanismCodeToSearch = firstRow[4];
+ } else {
+ this.datimMechanismCodeToSearch = this.myMechanismSearchString;
+ }
+
+ this.api.get('manifest.webapp')
+ .then(response => {
+ return response.data;
+ })
+ .then(manifest => {
+ return manifest.activities.dhis.href;
+ })
+ .then(apiUrl => {
+ return this.api.get([apiUrl, 'api', 'categoryOptions.json?filter=code:eq:' + this.datimMechanismCodeToSearch + '&fields=:all'].join('/'));
+ })
+ .then(response => response.data.categoryOptions[0])
+ .then(categoryOption => {
+ if (categoryOption) {
+ this.foundInDatim = true;
+ this.datimInfo.mechanism = categoryOption;
+ }
+
+ if (categoryOption && categoryOption.categoryOptionGroups.length > 0) {
+ this.datimInfo.agency = categoryOption.categoryOptionGroups.filter(categoryOptionGroup => /^Agency_.+/.test(categoryOptionGroup.code)).reduce((current) => current);
+ this.datimInfo.partner = categoryOption.categoryOptionGroups.filter(categoryOptionGroup => /^Partner_.+/.test(categoryOptionGroup.code)).reduce((current) => current);
+ }
+ });
+
+ }
+}
+
+function initMenu() {
+ //Setup dhis2 global for the menu
+ window.dhis2 = window.dhis2 || {};
+ dhis2.settings = dhis2.settings || {};
+ dhis2.settings.baseUrl = manifest.activities.dhis.href.replace(window.location.origin, '').replace(/^\//, '');
+
+ System.config({
+ paths: {
+ 'commons:*': window.location.origin + '/' + dhis2.settings.baseUrl + '/dhis-web-commons/javascripts/dhis2/*.js'
+ }
+ });
+ let menuFiles = [
+ 'dhis2.translate',
+ 'dhis2.menu',
+ 'dhis2.menu.ui'
+ ];
+
+ let stylesheets = [
+ '/dhis-web-commons/font-awesome/css/font-awesome.min.css',
+ '/dhis-web-commons/css/menu.css'
+ ];
+ let headElement = angular.element(document.querySelector('head'));
+ stylesheets.forEach(stylesheetUrl => {
+ let styleSheetElement = angular.element('');
+ angular.element(document.querySelector('head'))
+ .append(styleSheetElement);
+ });
+
+ return new Promise(function (resolve, reject) {
+ let result = Promise.resolve([]);
+ menuFiles.forEach(menuFile => {
+ result = result.then(function () {
+ return System.import('commons:' + menuFile);
+ });
+ });
+
+ resolve(result);
+ });
+}
+
+angular.module('whereIsMyMech', ['d2HeaderBar'])
+ .controller('WhereIsMyMechController', WhereIsMyMechController);
+
+initMenu()
+ .then(() => angular.bootstrap(document.querySelector('html'), ['whereIsMyMech']))
+ .catch(() => window.console.log('Failed to bootstrap the app'));
diff --git a/src/app.sass b/src/app.sass
new file mode 100644
index 00000000..4202a51b
--- /dev/null
+++ b/src/app.sass
@@ -0,0 +1,110 @@
+@import 'normalize'
+@import 'compass'
+@import 'susy'
+
+.ng-hide
+ display: none
+
+.app
+ padding-top: 75px
+ width: 90%
+ margin: 0 auto
+
+
+input[type=search]
+ font-size: 2rem
+ -webkit-appearance: none
+ -moz-appearance: none
+ border-radius: 2rem
+ border: 1px solid #CCC
+ color: #333
+ padding: .25rem 1rem
+ width: 100%
+ outline: none
+
+ &:focus
+ border-color: orange
+
+.found-statuses
+ @include span(1 of 1)
+
+.datim-info,
+.factsinfo-info
+ @include container()
+
+ h2
+ font-size: 1.2rem
+ color: #CCC
+
+ th, td
+ position: relative
+ padding: .2rem 0.4rem
+ white-space: nowrap
+
+ .longtext-field
+ position: relative
+ max-width: 15rem
+ overflow: hidden
+
+ &:after
+ content: ''
+ display: block
+ position: absolute
+ top: 0
+ right: 0
+ width: 2rem
+ bottom: 0
+
+ .odd :after
+ @include background-image(linear-gradient(left, rgba(254,254,254,0) 0%,rgba(254,254,254,1) 100%))
+
+ .even :after
+ @include background-image(linear-gradient(left, rgba(244,244,244,0) 0%,rgba(244,244,244,1) 100%))
+
+.factsinfo-data-table
+ overflow-x: auto
+
+
+.factsinfo-info
+ tr
+ border-bottom: 1px solid #CCC
+
+.datim-info-blocks
+ @include container()
+
+ div
+ @include span(1 of 3)
+
+ div:last-child
+ @include span(1 of 3 last)
+
+ th, td
+ padding: .25rem
+
+
+table
+ width: 100%
+
+th
+ text-align: left
+ font-weight: normal
+ color: #CCC
+ font-size: .8rem
+
+.even
+ background-color: #F5F5F5
+
+.odd
+ background-color: #FEFEFE
+
+.fa-check
+ color: darkgreen
+
+.fa-times
+ color: darkred
+
+h2, h3
+ margin: 0
+
+h2
+ margin-top: 1rem
diff --git a/src/config.js b/src/config.js
new file mode 100644
index 00000000..95249868
--- /dev/null
+++ b/src/config.js
@@ -0,0 +1,36 @@
+System.config({
+ "baseURL": ".",
+ "transpiler": "babel",
+ "babelOptions": {
+ "optional": [
+ "runtime"
+ ]
+ },
+ "paths": {
+ "*": "*.js",
+ "github:*": "jspm_packages/github/*.js",
+ "npm:*": "jspm_packages/npm/*.js"
+ }
+});
+
+System.config({
+ "map": {
+ "angular": "npm:angular@1.4.0",
+ "babel": "npm:babel-core@5.4.7",
+ "babel-runtime": "npm:babel-runtime@5.4.7",
+ "core-js": "npm:core-js@0.9.13",
+ "jquery": "github:components/jquery@2.1.4",
+ "github:jspm/nodelibs-process@0.1.1": {
+ "process": "npm:process@0.10.1"
+ },
+ "npm:angular@1.4.0": {
+ "process": "github:jspm/nodelibs-process@0.1.1"
+ },
+ "npm:core-js@0.9.13": {
+ "fs": "github:jspm/nodelibs-fs@0.1.2",
+ "process": "github:jspm/nodelibs-process@0.1.1",
+ "systemjs-json": "github:systemjs/plugin-json@0.1.0"
+ }
+ }
+});
+
diff --git a/src/config.rb b/src/config.rb
new file mode 100644
index 00000000..3e4c3cec
--- /dev/null
+++ b/src/config.rb
@@ -0,0 +1,4 @@
+require "compass-normalize"
+require "compass"
+require "breakpoint"
+require "susy"
diff --git a/src/index.html b/src/index.html
new file mode 100644
index 00000000..9510d081
--- /dev/null
+++ b/src/index.html
@@ -0,0 +1,89 @@
+
+
+
+
+
+ Where is my mechanism
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Trying to find mechanism with mechanism code:
+
+
Found in DATIM
+
Found in FACTS Info
+
+
+
+
DATIM info
+
+
+
Mechanism
+
+ Name | |
+ Code | |
+ Country | |
+ Start | |
+ End | |
+
+
+
+
Agency
+
+ Name | |
+ Code | |
+ Created | |
+
+
+
+
Partner
+
+ Name | |
+ Code | |
+ Created | |
+
+
+
+
+
+
FACTS Info to DATIM synchronisation logs
+
+
+
+
+ |
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/json.js b/src/json.js
new file mode 100644
index 00000000..64507bde
--- /dev/null
+++ b/src/json.js
@@ -0,0 +1,6 @@
+/*
+ JSON plugin
+ */
+exports.translate = function(load) {
+ return 'module.exports = ' + load.source;
+}
diff --git a/src/mag.png b/src/mag.png
new file mode 100644
index 00000000..0e5fdfd7
Binary files /dev/null and b/src/mag.png differ
diff --git a/src/manifest.webapp b/src/manifest.webapp
new file mode 100644
index 00000000..71777d32
--- /dev/null
+++ b/src/manifest.webapp
@@ -0,0 +1 @@
+{"version":"0.0.1","name":"Where is my mechanism?","description":"DATIM application to find a mechanism","icons":{"48":"./mag.png"},"developer":{"url":"","name":"Mark Polak, Jim Grace"},"launch_path":"index.html","default_locale":"en","activities":{"dhis":{"href":"*"}}}
\ No newline at end of file