├── e2e-tests
├── scenarios.js
├── main.spec.js
├── main.po.js
└── protractor.conf.js
├── app
├── src
│ ├── authentication
│ │ ├── authentication.module.js
│ │ ├── login
│ │ │ ├── login.component.spec.js
│ │ │ ├── login.html
│ │ │ └── login.component.js
│ │ ├── forgot
│ │ │ ├── forgot.component.js
│ │ │ └── forgot.html
│ │ ├── register
│ │ │ ├── verification
│ │ │ │ ├── verification.components.js
│ │ │ │ └── verification.html
│ │ │ ├── register.component.js
│ │ │ └── register.html
│ │ ├── authentication.html
│ │ └── authentication.service.js
│ ├── accounts
│ │ ├── account-list
│ │ │ ├── account-list.module.js
│ │ │ ├── account-list.component.spec.js
│ │ │ └── account-list.component.js
│ │ ├── loan-account-detail
│ │ │ ├── loan-account-detail.module.js
│ │ │ ├── loan-account-detail.component.spec.js
│ │ │ ├── loan-account-detail.service.js
│ │ │ └── loan-account-detail.component.js
│ │ └── savings-account-detail
│ │ │ ├── savings-account-detail.module.js
│ │ │ ├── savings-account-detail.component.spec.js
│ │ │ ├── savings-account-detail.service.js
│ │ │ └── savings-account-detail.component.js
│ ├── reports
│ │ ├── view_reports
│ │ │ ├── view_reports.service.js
│ │ │ ├── view_reports.component.js
│ │ │ └── view_reports.html
│ │ └── run_reports
│ │ │ ├── run_reports.service.js
│ │ │ ├── run_reports.html
│ │ │ └── run_reports.component.js
│ ├── common
│ │ ├── coming-soon.html
│ │ ├── translate-helper
│ │ │ ├── translate-helper.html
│ │ │ ├── translate-helper.directive.js
│ │ │ └── translate-helper.component.js
│ │ ├── 404.html
│ │ ├── nav.service.js
│ │ ├── storage.service.js
│ │ ├── directives
│ │ │ └── api-validate
│ │ │ │ └── api-validate.directive.js
│ │ ├── factories
│ │ │ └── APIRequestInterceptor.factory.js
│ │ ├── account.service.js
│ │ ├── main.component.js
│ │ ├── main.filters.js
│ │ └── main.html
│ ├── help
│ │ ├── help.service.js
│ │ ├── help.component.js
│ │ └── help.html
│ ├── aboutUs
│ │ ├── aboutUs.service.js
│ │ ├── aboutUs.component.js
│ │ └── aboutUs.html
│ ├── shares-application
│ │ ├── shares-application.service.js
│ │ ├── shares-application.component.js
│ │ └── shares-application.html
│ ├── savings-application
│ │ ├── savings-application.service.js
│ │ ├── savings-application.component.js
│ │ └── savings-application.html
│ ├── charges
│ │ ├── charges.service.js
│ │ ├── charges.component.js
│ │ └── charges.html
│ ├── recent-transactions
│ │ ├── recent-transactions.service.js
│ │ ├── recent-transactions.component.js
│ │ └── recent-transactions.html
│ ├── transfers
│ │ ├── transfers.service.js
│ │ ├── review-transfer-dialog
│ │ │ ├── review-transfer-dialog.html
│ │ │ └── review-transfer-dialog.component.js
│ │ ├── transfers.html
│ │ └── transfers.component.js
│ ├── loan-application
│ │ ├── loan-application.service.js
│ │ ├── loan-application.html
│ │ └── loan-application.component.js
│ ├── beneficiaries
│ │ ├── beneficiaries.service.js
│ │ ├── beneficiaries-add
│ │ │ ├── review-beneficiary-dialog
│ │ │ │ ├── review-beneficiary-dialog.html
│ │ │ │ └── review-beneficiary-dialog.component.js
│ │ │ ├── beneficiaries-add.component.js
│ │ │ └── beneficiaries-add.html
│ │ ├── beneficiaries-edit
│ │ │ ├── beneficiaries-edit.html
│ │ │ └── beneficiaries-edit.component.js
│ │ └── beneficiaries-list
│ │ │ ├── beneficiaries-list.component.js
│ │ │ └── beneficiaries-list.html
│ ├── tpt
│ │ ├── review-tpt-dialog
│ │ │ ├── review-tpt-dialog.html
│ │ │ └── review-tpt-dialog.component.js
│ │ ├── tpt.component.js
│ │ └── tpt.html
│ └── dashboard
│ │ └── dashboard.html
├── index.scss
├── favicon.ico
├── assets
│ ├── images
│ │ ├── cover.png
│ │ ├── toolbar.png
│ │ ├── MifosX_logo.png
│ │ ├── ic_close_white_24px.svg
│ │ ├── ic_person_black_24px.svg
│ │ ├── ic_person_white_24px.svg
│ │ ├── ic_remove_red_eye_black_24px.svg
│ │ └── ic_search_black_24px.svg
│ └── stylesheets
│ │ ├── 404.scss
│ │ └── _table.scss
├── app.css
├── app.modules.js
├── global-translations
│ ├── locale-hi.json
│ └── locale-en.json
├── app.constants.js
├── index.html
├── app.config.js
└── 404.html
├── .bowerrc
├── .travis.yml
├── .gitignore
├── gulp
├── deploy.js
├── watch.js
├── unit-tests.js
├── e2e-tests.js
├── server.js
├── styles.js
├── proxy.js
├── inject.js
└── build.js
├── .github
├── PULL_REQUEST_TEMPLATE.md
└── ISSUE_TEMPLATE.md
├── .eslintrc
├── gulpfile.js
├── karma.conf.js
├── Dockerfile
├── .jshintrc
├── LICENSE
├── bower.json
├── README.md
├── package.json
└── CONTRIBUTING.md
/e2e-tests/scenarios.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/authentication/authentication.module.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/index.scss:
--------------------------------------------------------------------------------
1 | // injector
2 | // endinjector
3 |
--------------------------------------------------------------------------------
/app/src/accounts/account-list/account-list.module.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/authentication/login/login.component.spec.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/reports/view_reports/view_reports.service.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "bower_components"
3 | }
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "4"
4 |
--------------------------------------------------------------------------------
/app/src/accounts/account-list/account-list.component.spec.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/accounts/loan-account-detail/loan-account-detail.module.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/common/coming-soon.html:
--------------------------------------------------------------------------------
1 | This page is still under construction
--------------------------------------------------------------------------------
/app/src/accounts/savings-account-detail/savings-account-detail.module.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/accounts/loan-account-detail/loan-account-detail.component.spec.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/accounts/savings-account-detail/savings-account-detail.component.spec.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openMF/web-self-service-app/HEAD/app/favicon.ico
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | bower_components/
3 | .sass-cache/
4 | .tmp/
5 | dist/
6 | .idea/
7 | .publish/
8 |
9 |
--------------------------------------------------------------------------------
/app/assets/images/cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openMF/web-self-service-app/HEAD/app/assets/images/cover.png
--------------------------------------------------------------------------------
/app/assets/images/toolbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openMF/web-self-service-app/HEAD/app/assets/images/toolbar.png
--------------------------------------------------------------------------------
/app/assets/images/MifosX_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openMF/web-self-service-app/HEAD/app/assets/images/MifosX_logo.png
--------------------------------------------------------------------------------
/app/app.css:
--------------------------------------------------------------------------------
1 | md-toolbar .md-menu{
2 | margin: 0 1rem;
3 | }
4 | #sidebar-menu .md-button{
5 | text-transform: capitalize;
6 | }
7 | #sidebar-menu__account-types{
8 | margin-left: 1rem;
9 | }
--------------------------------------------------------------------------------
/gulp/deploy.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 | var ghPages = require('gulp-gh-pages');
5 |
6 | gulp.task('deploy', function() {
7 | return gulp.src('./dist/**/*')
8 | .pipe(ghPages());
9 | });
10 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Thank you for contributing to Mifos web self-service.
2 |
3 | ##Description
4 | Describe the changes that were made.
5 |
6 | ##Related issues and discussion
7 | -{Issue Number}
8 |
9 | ##Screenshots/GIFs, if any:
--------------------------------------------------------------------------------
/e2e-tests/main.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('The main view', function () {
4 | var page;
5 |
6 | beforeEach(function () {
7 | browser.get('http://localhost:3000/index.html');
8 | page = require('./main.po');
9 | });
10 |
11 | });
12 |
--------------------------------------------------------------------------------
/app/assets/images/ic_close_white_24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "eslint:recommended",
3 | "plugins": [
4 | "angular"
5 | ],
6 | "rules": {
7 | "angular/controller-as": 0
8 | },
9 | "env": {
10 | "browser": true,
11 | "jasmine": true,
12 | "jquery": true
13 | },
14 | "globals": {
15 | "angular": true
16 | }
17 | }
--------------------------------------------------------------------------------
/app/assets/images/ic_person_black_24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/assets/images/ic_person_white_24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/e2e-tests/main.po.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This file uses the Page Object pattern to define the main page for tests
3 | * https://docs.google.com/presentation/d/1B6manhG0zEXkC-H-tPo2vwU06JhL8w9-XCF9oehXzAQ
4 | */
5 |
6 | 'use strict';
7 |
8 | var MainPage = function() {
9 | };
10 |
11 | module.exports = new MainPage();
12 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | gulp.paths = {
6 | src: 'app',
7 | dist: 'dist',
8 | tmp: '.tmp',
9 | e2e: 'e2e-tests'
10 | };
11 |
12 | require('require-dir')('./gulp');
13 |
14 | gulp.task('default', ['clean'], function () {
15 | gulp.start('build');
16 | });
17 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(config) {
4 |
5 | config.set({
6 | autoWatch : false,
7 |
8 | frameworks: ['jasmine'],
9 |
10 | browsers : ['PhantomJS'],
11 |
12 | plugins : [
13 | 'karma-phantomjs-launcher',
14 | 'karma-jasmine'
15 | ]
16 | });
17 | };
18 |
--------------------------------------------------------------------------------
/gulp/watch.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var paths = gulp.paths;
6 |
7 | gulp.task('watch', ['inject'], function () {
8 | gulp.watch([
9 | paths.src + '/*.html',
10 | paths.src + '/{app,components}/**/*.scss',
11 | paths.src + '/{app,components}/**/*.js',
12 | 'bower.json'
13 | ], ['inject']);
14 | });
15 |
--------------------------------------------------------------------------------
/app/src/common/translate-helper/translate-helper.html:
--------------------------------------------------------------------------------
1 | Change Language:
2 |
3 |
4 | English
5 | हिन्दी
6 |
7 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ##Description
2 | Provide a brief overview of the enhancement or issue.
3 |
4 | ##Steps to reproduce
5 | Please mention the steps to reproduce the error/issue.
6 |
7 | ##Expected Behaviour
8 |
9 | ##Actual Behaviour
10 |
11 | ##Settings:
12 | -Browser used:
13 |
14 | ##Screenshots/GIFs, if any:
15 | Please attach screenshots/GIFs of the error/issue.
--------------------------------------------------------------------------------
/app/app.modules.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService', [
5 | 'ngAnimate',
6 | 'ngCookies',
7 | 'ngSanitize',
8 | 'ngResource',
9 | 'ui.router',
10 | 'ngMaterial',
11 | 'ngMessages',
12 | 'nvd3',
13 | 'md.data.table',
14 | 'pascalprecht.translate'
15 | ])
16 |
17 | })();
--------------------------------------------------------------------------------
/app/assets/images/ic_remove_red_eye_black_24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/assets/images/ic_search_black_24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/global-translations/locale-hi.json:
--------------------------------------------------------------------------------
1 | {
2 | "login.heading.logintoyouraccount": "अपने अकाउंट में लॉग इन करें",
3 | "login.btn.login": "लॉग इन करें",
4 |
5 | "nav.msg.welcome": "नमस्ते,",
6 | "nav.label.accounts": "खातों",
7 | "nav.label.recenttransactions": "हालिया लेनदेन",
8 | "nav.label.charges": "शुल्क",
9 | "nav.label.transfers": "ट्रान्सफर",
10 | "nav.label.aboutus": "हमारे बारे में",
11 | "nav.label.help": "सहायता"
12 | }
--------------------------------------------------------------------------------
/app/src/authentication/forgot/forgot.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('ForgotPwdCtrl', ['$scope', '$state', '$mdToast', 'AuthService', 'AccountService', ForgotPwdCtrl]);
6 |
7 | /**
8 | * @module ForgotPwdCtrl
9 | * @description
10 | * Handles Forgot Password
11 | */
12 | function ForgotPwdCtrl() {
13 |
14 | }
15 |
16 | })();
17 |
--------------------------------------------------------------------------------
/app/src/help/help.service.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .service('HelpService', ['$q', '$http', '$rootScope', '$state', '$resource', HelpService]);
6 |
7 | function HelpService ($q, $http, $rootScope, $state, $resource) {
8 |
9 | this.getFAQ = function () {
10 | return $resource(''); // enter the URL of the FAQ
11 | }
12 |
13 |
14 |
15 | }
16 | })();
--------------------------------------------------------------------------------
/app/src/aboutUs/aboutUs.service.js:
--------------------------------------------------------------------------------
1 | (function (){
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .service('AboutUsService', ['$q', '$http', '$rootScope', '$state', '$resource', AboutUsService]);
6 |
7 | function AboutUsService($q,$http,$rootScope,$state,$resource){
8 |
9 | this.getOrgDetails = function () {
10 | return $resource(''); // enter the URL of the organisations details.
11 | };
12 | }
13 | })();
--------------------------------------------------------------------------------
/app/src/shares-application/shares-application.service.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .service('SharesApplicationService', ['$resource', 'BASE_URL', SharesApplicationService]);
6 |
7 | /**
8 | * @module SharesApplicationService
9 | * @description
10 | * Service required for Shares Application
11 | */
12 | function SharesApplicationService() {
13 |
14 |
15 | }
16 |
17 | })();
--------------------------------------------------------------------------------
/app/src/common/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
404
4 |
Not found :(
5 |
Sorry but we couldn’t find the page you are looking for
6 |
7 |
Go back to home
8 |
9 |
--------------------------------------------------------------------------------
/app/src/savings-application/savings-application.service.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .service('SavingsApplicationService', ['$resource', 'BASE_URL', SavingsApplicationService]);
6 |
7 | /**
8 | * @module SavingsApplicationService
9 | * @description
10 | * Service required for Savings Application
11 | */
12 | function SavingsApplicationService() {
13 |
14 |
15 | }
16 |
17 | })();
--------------------------------------------------------------------------------
/app/app.constants.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 |
6 | .constant("BASE_URL", "https://mobile.openmf.org/fineract-provider/api/v1")
7 |
8 | .constant('AUTH_EVENTS', {
9 | updateUser: 'update-user',
10 | notAuthorized: 'auth-not-authorized',
11 | notAuthenticated: 'auth-not-authenticated'
12 | })
13 |
14 |
15 | .constant("TENANT_IDENTIFIER", "default")
16 |
17 |
18 | .constant('USER_ROLES', {
19 | user: 'USER'
20 | });
21 | })();
22 |
--------------------------------------------------------------------------------
/app/src/charges/charges.service.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 | angular.module('selfService')
4 | .service('ChargesService', ['$q', '$http', '$rootScope', '$resource', 'BASE_URL', ChargesService]);
5 |
6 | function ChargesService($q, $http, $rootScope, $resource, BASE_URL) {
7 |
8 | this.getClientCharges = function (clientId) {
9 | return $resource(BASE_URL + '/self/clients/' + clientId + '/charges')
10 | }
11 |
12 | }
13 |
14 | })();
15 |
--------------------------------------------------------------------------------
/app/src/recent-transactions/recent-transactions.service.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 | angular.module('selfService')
4 | .service('TransactionService', ['$q', '$http', '$rootScope', '$resource', 'BASE_URL', TransactionService]);
5 |
6 | function TransactionService($q, $http, $rootScope, $resource, BASE_URL) {
7 |
8 | this.getClientTransactions = function (clientId) {
9 | return $resource(BASE_URL + '/self/clients/' + clientId + '/transactions')
10 | }
11 |
12 | }
13 |
14 | })();
15 |
--------------------------------------------------------------------------------
/app/src/accounts/loan-account-detail/loan-account-detail.service.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 | //@todo Move this service to the common folder
4 | angular.module('selfService')
5 | .service('LoanAccountService', ['$q', '$http', '$rootScope', '$resource', 'BASE_URL', LoanAccountService]);
6 |
7 | function LoanAccountService($q, $http, $rootScope, $resource, BASE_URL) {
8 |
9 | this.loanAccount = function () {
10 | return $resource(BASE_URL + '/self/loans/:id',{id: '@id'});
11 | }
12 | }
13 |
14 | })();
15 |
--------------------------------------------------------------------------------
/app/src/common/translate-helper/translate-helper.directive.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .directive('translateHelper', translateHelper);
6 |
7 | function translateHelper() {
8 | var directive = {
9 | restrict: 'E',
10 | controller: 'translateHelperCtrl',
11 | controllerAs: 'vm',
12 | scope: {},
13 | templateUrl: 'src/common/translate-helper/translate-helper.html'
14 | }
15 |
16 | return directive;
17 | }
18 |
19 | })();
20 |
--------------------------------------------------------------------------------
/app/src/reports/run_reports/run_reports.service.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .service('RunReportService', ['$q', '$http', '$rootScope', '$state', '$resource', 'BASE_URL', RunReportService]);
6 |
7 | function RunReportService($q, $http, $rootScope, $state, $resource, BASE_URL) {
8 |
9 | this.reports = function () {
10 |
11 | return $resource(BASE_URL + "/self/runreports/:reportName" + '?R_officeId='+ ':id', {reportName: '@reportName', id: '@id'});
12 |
13 |
14 | }
15 |
16 | }
17 |
18 | })();
--------------------------------------------------------------------------------
/app/src/accounts/savings-account-detail/savings-account-detail.service.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 | //@todo Move this service to the common folder
4 | angular.module('selfService')
5 | .service('SavingsAccountService', ['$q', '$http', '$rootScope', '$resource', 'BASE_URL', SavingsAccountService]);
6 |
7 | function SavingsAccountService($q, $http, $rootScope, $resource, BASE_URL) {
8 |
9 | this.savingsAccount = function () {
10 | return $resource(BASE_URL + '/self/savingsaccounts/:id',{id: '@id'});
11 | }
12 | }
13 |
14 | })();
15 |
--------------------------------------------------------------------------------
/app/src/help/help.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('HelpCtrl', ['$scope', '$rootScope', '$state', '$stateParams','HelpService', HelpCtrl]);
6 |
7 | function HelpCtrl ($scope, $rootscope, $state, $stateParams, HelpService) {
8 | var vm=this;
9 |
10 | vm.faqData=[];
11 | vm.getfaq = getfaq;
12 |
13 | function getfaq() {
14 | HelpService.getFAQ().get().$promise.then(function (data) {
15 | vm.faqData = data;
16 |
17 | })
18 | }
19 |
20 | }
21 | })();
--------------------------------------------------------------------------------
/app/src/common/nav.service.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .service('navService', ['$q', navService]);
6 |
7 | function navService($q){
8 | var menuItems = [
9 | {
10 | name: 'Dashboard',
11 | icon: 'view_module',
12 | sref: '.dashboard'
13 | },
14 | {
15 | name: 'Accounts',
16 | icon: 'account_balance_wallet',
17 | sref: '.clients'
18 | }
19 | ];
20 |
21 | return {
22 | loadAllItems : function() {
23 | return $q.when(menuItems);
24 | }
25 | };
26 | }
27 |
28 | })();
--------------------------------------------------------------------------------
/app/src/reports/view_reports/view_reports.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('ViewReportsCtrl', ['$scope', '$rootScope', '$state','$location', ViewReportsCtrl]);
6 |
7 | function ViewReportsCtrl($scope, $rootScope, $state, $location) {
8 | var vm = this;
9 | vm.selected = [];
10 | vm.routeTo = routeTo;
11 |
12 | function routeTo(report) {
13 | $location.path('/run_report/' + report.reportName + '/' + report.id + '/' + report.reportType);
14 | }
15 |
16 | vm.reports = [];
17 |
18 | }
19 |
20 | })();
--------------------------------------------------------------------------------
/app/src/transfers/transfers.service.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 | angular.module('selfService')
4 | .service('AccountTransferService', ['$q', '$http', '$rootScope', '$resource', 'BASE_URL', AccountTransferService]);
5 |
6 | function AccountTransferService($q, $http, $rootScope, $resource, BASE_URL) {
7 |
8 | this.getTransferTemplate = function () {
9 | return $resource(BASE_URL + '/self/accounttransfers/template');
10 | }
11 |
12 | this.transfer = function () {
13 | return $resource(BASE_URL + '/self/accounttransfers');
14 | }
15 |
16 | }
17 |
18 | })();
19 |
--------------------------------------------------------------------------------
/app/src/common/translate-helper/translate-helper.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('translateHelperCtrl', ['$scope', '$rootScope', '$translate', translateHelperCtrl]);
6 |
7 | function translateHelperCtrl($scope, $rootScope, $translate) {
8 | var vm = this;
9 | vm.langCode = getLangCode();
10 | vm.updateLang = updateLang;
11 |
12 | function getLangCode() {
13 | return $translate.use();
14 | }
15 |
16 | function updateLang() {
17 | $translate.use(vm.langCode);
18 | }
19 | }
20 |
21 | })();
22 |
--------------------------------------------------------------------------------
/app/src/loan-application/loan-application.service.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .service('LoanApplicationService', ['$resource', 'BASE_URL', LoanApplicationService]);
6 |
7 | /**
8 | * @module LoanApplicationService
9 | * @description
10 | * Service required for Loan Application
11 | */
12 | function LoanApplicationService($resource, BASE_URL) {
13 |
14 | this.template = function() {
15 | return $resource(BASE_URL + '/self/loans/template');
16 | }
17 |
18 | this.loan = function() {
19 | return $resource(BASE_URL + '/self/loans');
20 | }
21 | }
22 |
23 | })();
--------------------------------------------------------------------------------
/app/src/aboutUs/aboutUs.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('AboutUsCtrl', ['$scope', '$rootScope', '$state', '$stateParams', 'AboutUsService', AboutUsCtrl]);
6 |
7 | function AboutUsCtrl ($scope, $rootScope, $state, $stateParams, AboutUsService) {
8 |
9 | var vm=this;
10 | vm.org = null; // it is an array, when data is available then vm.org = {JSON data};
11 | vm.getDetails = getDetails;
12 |
13 | function getDetails() {
14 | AboutUsService.getOrgDetails.get().$promise.then(function (data){
15 | vm.org =data;
16 | })
17 | }
18 | }
19 | })();
20 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mhart/alpine-node:8.9.4 as builder
2 |
3 | RUN apk update
4 | RUN apk add git
5 | RUN mkdir -p /usr/src/app
6 | WORKDIR /usr/src/app
7 | ENV PATH /usr/src/app/node_modules/.bin:$PATH
8 | COPY package.json /usr/src/app/package.json
9 | COPY gulpfile.js /usr/src/app/gulpfile.js
10 | RUN npm install bower
11 | RUN npm install gulp-cli
12 | COPY . /usr/src/app
13 | RUN bower --allow-root install
14 | RUN npm install -f
15 | RUN npm install --save-dev gulp
16 | RUN npm install --save-dev gulp-inject
17 | RUN npm install --save-dev gulp-ruby-sass
18 | COPY gulpfile.js /usr/src/app/gulpfile.js
19 | RUN gulp build
20 |
21 | FROM nginx:1.19.3
22 | COPY --from=builder /usr/src/app/dist /usr/share/nginx/html
23 | EXPOSE 80
24 | CMD ["nginx", "-g", "daemon off;"]
25 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "esnext": true,
4 | "bitwise": true,
5 | "camelcase": true,
6 | "curly": true,
7 | "eqeqeq": true,
8 | "immed": true,
9 | "indent": 2,
10 | "latedef": true,
11 | "newcap": true,
12 | "noarg": true,
13 | "quotmark": "single",
14 | "regexp": true,
15 | "undef": true,
16 | "unused": true,
17 | "strict": true,
18 | "trailing": true,
19 | "smarttabs": true,
20 | "white": true,
21 | "validthis": true,
22 | "globals": {
23 | "angular": false,
24 | // Angular Mocks
25 | "inject": false,
26 | // JASMINE
27 | "describe": false,
28 | "it": false,
29 | "before": false,
30 | "beforeEach": false,
31 | "after": false,
32 | "afterEach": false,
33 | "expect": false
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/e2e-tests/protractor.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var paths = require('./.yo-rc.json')['generator-gulp-angular'].props.paths;
4 |
5 | // An example configuration file.
6 | exports.config = {
7 | // The address of a running selenium server.
8 | //seleniumAddress: 'http://localhost:4444/wd/hub',
9 | //seleniumServerJar: deprecated, this should be set on node_modules/protractor/config.json
10 |
11 | // Capabilities to be passed to the webdriver instance.
12 | capabilities: {
13 | 'browserName': 'chrome'
14 | },
15 |
16 | // Spec patterns are relative to the current working directly when
17 | // protractor is called.
18 | specs: [paths.e2e + '/**/*.js'],
19 |
20 | // Options to be passed to Jasmine-node.
21 | jasmineNodeOpts: {
22 | showColors: true,
23 | defaultTimeoutInterval: 30000
24 | }
25 | };
26 |
--------------------------------------------------------------------------------
/app/src/common/storage.service.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .service('storageService', ['$q', storageService]);
6 |
7 | function storageService($q){
8 |
9 | return {
10 | getItem: function (key) {
11 | return $q.when(window.localStorage.getItem(key));
12 | },
13 | setItem: function (key, value) {
14 | window.localStorage.setItem(key, value);
15 | },
16 | getObject: function (key) {
17 | return $q.when(JSON.parse(window.localStorage.getItem(key)));
18 | },
19 | setObject: function (key, value) {
20 | value = JSON.stringify(value);
21 | window.localStorage.setItem(key, value);
22 | },
23 | clear: function () {
24 | window.localStorage.clear();
25 | }
26 | };
27 | }
28 |
29 | })();
--------------------------------------------------------------------------------
/app/src/shares-application/shares-application.component.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('SharesApplicationCtrl', ['$scope', '$filter', '$mdToast', 'AccountService', 'SharesApplicationService', SharesApplicationCtrl]);
6 |
7 | /**
8 | * @module SharesApplicationCtrl
9 | * @description
10 | * Controls Application for Shares
11 | */
12 | function SharesApplicationCtrl($scope) {
13 | var vm = this;
14 |
15 | vm.clearForm = clearForm;
16 | vm.submit = submit;
17 | vm.form = {};
18 |
19 | function clearForm() {
20 | $scope.shareApplicationForm.$setPristine();
21 | $scope.shareApplicationForm.$setUntouched();
22 | vm.form = {};
23 | }
24 |
25 | function submit() {
26 |
27 | }
28 |
29 | }
30 | })();
--------------------------------------------------------------------------------
/app/src/common/directives/api-validate/api-validate.directive.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .directive('apiValidate', ['$compile', apiValidate]);
6 |
7 | function apiValidate($compile) {
8 | return {
9 | restrict: 'E',
10 | link: function (scope, elm) {
11 | var template = '' +
12 | '
' +
13 | ' ' +
14 | '{{' + 'errorArray.userMessageGlobalisationCode' + ' | translate:error.args }}' +
15 | ' ' +
16 | '
';
17 | elm.html('').append($compile(template)(scope));
18 | }
19 | };
20 | }
21 |
22 | })();
--------------------------------------------------------------------------------
/app/src/beneficiaries/beneficiaries.service.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .service('BeneficiariesService', ['$q', '$http', '$rootScope', '$state', '$resource', 'BASE_URL', BeneficiariesService]);
6 |
7 | function BeneficiariesService($q, $http, $rootScope, $state, $resource, BASE_URL) {
8 |
9 | this.getBeneficiaries = function () {
10 | return $resource(BASE_URL + '/self/beneficiaries/tpt');
11 | };
12 |
13 | this.template = function() {
14 | return $resource(BASE_URL + '/self/beneficiaries/tpt/template');
15 | }
16 |
17 | this.beneficiary = function () {
18 | return $resource(BASE_URL + '/self/beneficiaries/tpt/:id',{id: '@id'},{
19 | update: {
20 | method: 'PUT'
21 | }
22 | });
23 | }
24 | }
25 |
26 | })();
--------------------------------------------------------------------------------
/app/src/savings-application/savings-application.component.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('SavingsApplicationCtrl', ['$scope', '$filter', '$mdToast', 'AccountService', 'SavingsApplicationService', SavingsApplicationCtrl]);
6 |
7 | /**
8 | * @module SavingsApplicationCtrl
9 | * @description
10 | * Controls Application for Savings
11 | */
12 | function SavingsApplicationCtrl($scope) {
13 | var vm = this;
14 | vm.form = {};
15 |
16 | vm.clearForm = clearForm;
17 | vm.submit = submit;
18 | vm.form = {};
19 |
20 | function clearForm() {
21 | $scope.savingsApplicationForm.$setPristine();
22 | $scope.savingsApplicationForm.$setUntouched();
23 | vm.form = {};
24 | }
25 |
26 | function submit() {
27 |
28 | }
29 | }
30 | })();
--------------------------------------------------------------------------------
/gulp/unit-tests.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var $ = require('gulp-load-plugins')();
6 |
7 | var wiredep = require('wiredep');
8 |
9 | var paths = gulp.paths;
10 |
11 | function runTests (singleRun, done) {
12 | var bowerDeps = wiredep({
13 | directory: 'bower_components',
14 | exclude: ['bootstrap-sass-official'],
15 | dependencies: true,
16 | devDependencies: true
17 | });
18 |
19 | var testFiles = bowerDeps.js.concat([
20 | paths.src + '/{app,components}/**/*.js'
21 | ]);
22 |
23 | gulp.src(testFiles)
24 | .pipe($.karma({
25 | configFile: 'karma.conf.js',
26 | action: (singleRun)? 'run': 'watch'
27 | }))
28 | .on('error', function (err) {
29 | // Make sure failed tests cause gulp to exit non-zero
30 | throw err;
31 | });
32 | }
33 |
34 | gulp.task('test', function (done) { runTests(true /* singleRun */, done) });
35 | gulp.task('test:auto', function (done) { runTests(false /* singleRun */, done) });
36 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/404.scss:
--------------------------------------------------------------------------------
1 | #error-404 {
2 |
3 | background: #f1f1f1;
4 |
5 | .content {
6 | width: 90%;
7 | max-width: 512px;
8 |
9 | .error-code {
10 | font-size: 112px;
11 | text-align: center;
12 | line-height: 1;
13 | margin-bottom: 16px;
14 | font-weight: 500;
15 | }
16 |
17 | .error-code-msg {
18 | font-size: 74px;
19 | text-align: center;
20 | line-height: 1;
21 | margin-bottom: 8px;
22 | font-weight: 500;
23 | }
24 |
25 | .message {
26 | font-size: 24px;
27 | text-align: center;
28 | color: rgba(0, 0, 0, 0.54);
29 | }
30 |
31 | .search {
32 | width: 100%;
33 | height: 56px;
34 | line-height: 56px;
35 | margin: 48px auto 16px auto;
36 | padding: 16px;
37 | background: #FFFFFF;
38 |
39 | input {
40 | padding: 0 0 0 16px;
41 | }
42 | }
43 |
44 | .back-link {
45 | font-size: 15px;
46 | text-align: center;
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/gulp/e2e-tests.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var $ = require('gulp-load-plugins')();
6 |
7 | var browserSync = require('browser-sync');
8 |
9 | var paths = gulp.paths;
10 |
11 | // Downloads the selenium webdriver
12 | gulp.task('webdriver-update', $.protractor.webdriver_update);
13 |
14 | gulp.task('webdriver-standalone', $.protractor.webdriver_standalone);
15 |
16 | function runProtractor (done) {
17 |
18 | gulp.src(paths.e2e + '/**/*.js')
19 | .pipe($.protractor.protractor({
20 | configFile: 'protractor.conf.js',
21 | }))
22 | .on('error', function (err) {
23 | // Make sure failed tests cause gulp to exit non-zero
24 | throw err;
25 | })
26 | .on('end', function () {
27 | // Close browser sync server
28 | browserSync.exit();
29 | done();
30 | });
31 | }
32 |
33 | gulp.task('protractor', ['protractor:src']);
34 | gulp.task('protractor:src', ['serve:e2e', 'webdriver-update'], runProtractor);
35 | gulp.task('protractor:dist', ['serve:e2e-dist', 'webdriver-update'], runProtractor);
36 |
--------------------------------------------------------------------------------
/app/src/help/help.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | FAQ
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{item.Question}}
15 |
16 |
17 |
18 |
19 |
20 | arrow_forward_ios
21 | {{item.Answer}}
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 flatlogic
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "self-service-app",
3 | "description": "Self Service Application",
4 | "homepage": "",
5 | "license": "MIT",
6 | "version": "1.2.0",
7 | "dependencies": {
8 | "jquery": "^3.2.1",
9 | "angular": "^1.8.2",
10 | "angular-material": "^1.1.4",
11 | "angular-animate": "^1.6.5",
12 | "angular-cookies": "^1.6.5",
13 | "angular-touch": "^1.6.5",
14 | "angular-sanitize": "^1.6.5",
15 | "angular-ui-router": "^1.0.6",
16 | "angular-nvd3": "^1.0.9",
17 | "angular-translate-storage-cookie": "2.19.0",
18 | "angular-translate-storage-local": "2.19.0",
19 | "angular-resource": "^1.6.5",
20 | "angular-material-data-table": "^0.10.10",
21 | "angular-translate": "^2.19.0",
22 | "angular-translate-loader-static-files": "^2.19.0",
23 | "components-font-awesome": "^4.7.0",
24 | "ngmap":""
25 | },
26 | "overrides": {
27 | "components-font-awesome": {
28 | "main": [
29 | "./css/font-awesome.css",
30 | "./fonts/*"
31 | ]
32 | }
33 | },
34 | "devDependencies": {
35 | "angular-mocks": "^1.6.5"
36 | },
37 | "resolutions": {
38 | "angular": "1.7.0"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/common/factories/APIRequestInterceptor.factory.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .factory('APIRequestInterceptor', ['$rootScope', '$q', APIRequestInterceptor]);
6 |
7 | function APIRequestInterceptor($rootScope, $q) {
8 | return {
9 | request: function(config) {
10 | $rootScope.blockUI = true;
11 | $rootScope.respERROR = null;
12 | return $q.resolve(config);
13 | },
14 | requestError: function (rejection) {
15 | $rootScope.blockUI = false;
16 | $rootScope.respERROR = null;
17 | return $q.reject(rejection);
18 | },
19 | response: function(response) {
20 | $rootScope.blockUI = false;
21 | $rootScope.respERROR = null;
22 | return $q.resolve(response);
23 | },
24 | responseError: function(response) {
25 | $rootScope.blockUI = false;
26 | $rootScope.respERROR = response;
27 | return $q.reject(response);
28 | }
29 | }
30 | }
31 |
32 | })();
33 |
--------------------------------------------------------------------------------
/app/src/charges/charges.component.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('ChargesCtrl', ['$scope', '$rootScope', '$stateParams', 'AccountService', 'ChargesService', ChargesCtrl]);
6 |
7 | function ChargesCtrl($scope, $rootScope, $stateParams, AccountService, ChargesService) {
8 |
9 | var vm = this;
10 | vm.loadingCharges = true;
11 | vm.charges = {};
12 | vm.onPaginate = onPaginate;
13 | vm.page = 1;
14 | vm.query = {
15 | limit: 5,
16 | offset: 0
17 | }
18 |
19 | vm.getCharges = getCharges(vm.query);
20 |
21 | function getCharges(query){
22 | AccountService.getClientId().then(function (clientId){
23 | ChargesService.getClientCharges(clientId).get(query).$promise.then(function (res) {
24 | vm.loadingCharges = false;
25 | vm.charges = res;
26 | });
27 | });
28 | }
29 |
30 | function onPaginate(offset,limit) {
31 | getCharges(angular.extend({}, vm.query, {offset: (offset - 1) * limit, limit: limit}));
32 | }
33 |
34 | }
35 | })();
--------------------------------------------------------------------------------
/app/src/reports/run_reports/run_reports.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{vm.reportName}}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | {{columnHeader.columnName}}
16 |
17 |
18 |
19 |
20 | {{col}}
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Mifos Self Service App
2 |
3 | ## Getting started
4 | You can follow this README or you can follow this [video](https://mifosforge.jira.com/wiki/spaces/docs/pages/498794497/Developer+Environment+Setup+for+Online+Banking+App+2.0).
5 |
6 | Clone the project:
7 |
8 | $ git clone https://github.com/openMF/web-self-service-app.git
9 |
10 | Install dependencies:
11 |
12 | $ cd web-self-service-app
13 |
14 | $ npm install
15 | $ bower install
16 |
17 | Install gem 'sass'
18 |
19 | Make sure that you have '''ruby''' installed (if not goto https://www.ruby-lang.org/en/documentation/installation/ ).
20 |
21 | $ gem install sass
22 |
23 | Run development web-server:
24 |
25 | $ gulp serve
26 |
27 | Use these credentials to logIn `username: selfservice password: password`
28 |
29 |
30 | ## Contributing Guidelines:
31 | * Contributors must follow these [guidelines](https://github.com/openMF/web-self-service-app/blob/develop/CONTRIBUTING.md)
32 |
33 | ## Features
34 |
35 | * AngularJS
36 | * Angular UI Router
37 | * Angular Material
38 | * Sass styles
39 | * Gulp build
40 | * Stylish, clean, responsive layout with original design
41 | * BrowserSync for the ease of development
42 |
43 | ## Deploy to Github pages
44 |
45 | $ gulp build
46 | $ gulp deploy
47 |
--------------------------------------------------------------------------------
/app/src/recent-transactions/recent-transactions.component.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('RecentTransactionCtrl', ['$scope', '$rootScope', '$stateParams', 'AccountService', 'TransactionService', RecentTransactionCtrl]);
6 |
7 | function RecentTransactionCtrl($scope, $rootScope, $stateParams, AccountService, TransactionService) {
8 |
9 | var vm = this;
10 | vm.loadingTransactions = true;
11 | vm.recenttransactions = {};
12 | vm.onPaginate = onPaginate;
13 | vm.page = 1;
14 | vm.query = {
15 | limit: 5,
16 | offset: 0
17 | }
18 |
19 | vm.getTransactions = getTransactions(vm.query);
20 |
21 | function getTransactions(query){
22 | AccountService.getClientId().then(function (clientId){
23 | TransactionService.getClientTransactions(clientId).get(query).$promise.then(function (res) {
24 | vm.loadingTransactions = false;
25 | vm.recenttransactions = res;
26 | });
27 | });
28 | }
29 |
30 | function onPaginate(offset,limit) {
31 | getTransactions(angular.extend({}, vm.query, {offset: (offset - 1) * limit, limit: limit}));
32 | }
33 |
34 | }
35 | })();
--------------------------------------------------------------------------------
/app/src/beneficiaries/beneficiaries-add/review-beneficiary-dialog/review-beneficiary-dialog.html:
--------------------------------------------------------------------------------
1 |
2 |
42 |
--------------------------------------------------------------------------------
/app/src/reports/run_reports/run_reports.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('RunReportCtrl', ['$http', '$scope', '$rootScope','$state', '$stateParams', '$resource', '$location', 'dateFilter', 'BASE_URL', '$sce', 'RunReportService', RunReportCtrl]);
6 |
7 | function RunReportCtrl($http, $scope, $rootScope, $state, $stateParams, $resource, $location, dateFilter, BASE_URL, $sce, RunReportService) {
8 | var vm = this;
9 |
10 |
11 | vm.reportName = $stateParams.name;
12 | vm.id = $stateParams.id;
13 | vm.reportData = {};
14 | vm.reportData.columnHeaders = [];
15 |
16 | vm.isDecimal = isDecimal
17 |
18 |
19 | RunReportService.reports().get({reportName: vm.reportName, id: vm.id}).$promise.then(function(data) {
20 | vm.reportData = data;
21 | vm.reportData.columnHeaders = data.columnHeaders;
22 | });
23 |
24 | function isDecimal (index) {
25 | if(vm.reportData.columnHeaders && vm.reportData.columnHeaders.length > 0){
26 | for(var i=0; i
2 |
3 |
4 |
5 |
6 | No details to show
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | {{vm.org.name}}
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | {{'label.heading.aboutUs' | translate}}
32 | {{vm.org.description}}
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/gulp/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var paths = gulp.paths;
6 |
7 | var util = require('util');
8 |
9 | var browserSync = require('browser-sync');
10 |
11 | var middleware = require('./proxy');
12 |
13 | function browserSyncInit(baseDir, files, browser) {
14 | browser = browser === undefined ? 'default' : browser;
15 |
16 | var routes = null;
17 | if(baseDir === paths.src || (util.isArray(baseDir) && baseDir.indexOf(paths.src) !== -1)) {
18 | routes = {
19 | '/bower_components': 'bower_components'
20 | };
21 | }
22 |
23 | browserSync.instance = browserSync.init(files, {
24 | startPath: '/',
25 | ghostMode:false,
26 | server: {
27 | baseDir: baseDir,
28 | middleware: middleware,
29 | routes: routes
30 | },
31 | browser: browser
32 | });
33 | }
34 |
35 | gulp.task('serve', ['watch'], function () {
36 | browserSyncInit([
37 | paths.tmp + '/serve',
38 | paths.src
39 | ], [
40 | paths.src + '/src/**/*.js',
41 | paths.src + '/src/**/*.html',
42 | paths.src + '/assets/images/**/*',
43 | paths.tmp + '/serve/*.html',
44 | paths.tmp + '/serve/**/*.html',
45 | paths.tmp + '/serve/**/*.css'
46 | ]);
47 | });
48 |
49 | gulp.task('serve:dist', ['build'], function () {
50 | browserSyncInit(paths.dist);
51 | });
52 |
53 | gulp.task('serve:e2e', ['inject'], function () {
54 | browserSyncInit([paths.tmp + '/serve', paths.src], null, []);
55 | });
56 |
57 | gulp.task('serve:e2e-dist', ['build'], function () {
58 | browserSyncInit(paths.dist, null, []);
59 | });
60 |
--------------------------------------------------------------------------------
/gulp/styles.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var paths = gulp.paths;
6 |
7 | var $ = require('gulp-load-plugins')();
8 |
9 | gulp.task('styles', function () {
10 |
11 | var sassOptions = {
12 | style: 'expanded',
13 | 'sourcemap=none': true
14 | };
15 |
16 | var injectFiles = gulp.src([
17 | paths.src + '/assets/stylesheets/**/*.scss',
18 | '!' + paths.src + '/index.scss'
19 | ], {read: false});
20 |
21 | var injectOptions = {
22 | transform: function (filePath) {
23 | filePath = filePath.replace(paths.src + '/', '');
24 | filePath = filePath.replace(paths.src + '/components/', '../components/');
25 | return '@import \'' + filePath + '\';';
26 | },
27 | starttag: '// injector',
28 | endtag: '// endinjector',
29 | addRootSlash: false
30 | };
31 |
32 | var indexFilter = $.filter('index.scss');
33 |
34 | return gulp.src(paths.src + '/index.scss')
35 | .pipe(indexFilter)
36 | .pipe($.inject(injectFiles, injectOptions))
37 | .pipe(indexFilter.restore())
38 | .pipe($.rubySass(sassOptions)
39 | .on('error', function (err) {
40 | console.error('Error!', err.message);
41 | })
42 | )
43 |
44 | .pipe($.autoprefixer())
45 | .on('error', function handleError(err) {
46 | console.error(err.toString());
47 | this.emit('end');
48 | })
49 | .pipe(gulp.dest(paths.tmp + '/serve/styles/'))
50 | .pipe(gulp.dest(paths.dist + '/styles/'));
51 | });
52 |
--------------------------------------------------------------------------------
/app/src/authentication/register/verification/verification.components.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('VerificationCtrl', ['$scope', '$state', '$mdToast', 'AuthService', '$location', VerificationCtrl]);
6 |
7 |
8 | function VerificationCtrl($scope, $state, $mdToast, AuthService, $location) {
9 | var vm = this;
10 | vm.verifyData = {};
11 |
12 | /* function clearForm() {
13 | $scope.form.$setPristine();
14 | $scope.form.$setUntouched();
15 | vm.verifyData={};
16 |
17 | }*/
18 |
19 | $scope.submit = function() {
20 | AuthService.verifyUser(vm.verifyData).then(function () {
21 | $mdToast.show(
22 | $mdToast.simple()
23 | .textContent('User has been successfully registered')
24 | .position('top right')
25 | );
26 | $location.path('/login');
27 | vm.clearForm();
28 | }, function (resp) {
29 | var errors = '';
30 | if(resp.data){
31 | errors = resp.data.errors.map(function (data) {
32 | return data.defaultUserMessage;
33 | });
34 | errors.join(' ');
35 | }
36 | $mdToast.show(
37 | $mdToast.simple()
38 | .textContent('Error in creating user: ' + errors)
39 | .position('top right')
40 | );
41 |
42 | });
43 |
44 | }
45 |
46 | }
47 |
48 | })();
49 |
--------------------------------------------------------------------------------
/app/src/tpt/review-tpt-dialog/review-tpt-dialog.html:
--------------------------------------------------------------------------------
1 |
2 |
43 |
--------------------------------------------------------------------------------
/app/src/transfers/review-transfer-dialog/review-transfer-dialog.html:
--------------------------------------------------------------------------------
1 |
2 |
43 |
--------------------------------------------------------------------------------
/app/src/authentication/forgot/forgot.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Self-Service-App",
3 | "version": "1.3.0",
4 | "dependencies": {
5 | "ngmap": "^1.18.5"
6 | },
7 | "devDependencies": {
8 | "browser-sync": "~1.7.1",
9 | "chalk": "~0.5.1",
10 | "del": "~0.1.3",
11 | "eslint": "^4.0.0",
12 | "eslint-plugin-angular": "^2.4.2",
13 | "gulp": "~3.9.0",
14 | "gulp-angular-filesort": "~1.0.4",
15 | "gulp-angular-templatecache": "~1.4.2",
16 | "gulp-autoprefixer": "~2.0.0",
17 | "gulp-concat": "^2.6.1",
18 | "gulp-consolidate": "~0.1.2",
19 | "gulp-csso": "~0.2.9",
20 | "gulp-filter": "~1.0.2",
21 | "gulp-flatten": "~0.0.4",
22 | "gulp-gh-pages": "^0.5.4",
23 | "gulp-hash-filename": "^1.2.0",
24 | "gulp-inject": "~1.0.2",
25 | "gulp-jshint": "~1.9.0",
26 | "gulp-karma": "~0.0.4",
27 | "gulp-load-plugins": "~0.7.1",
28 | "gulp-minify-html": "~0.1.7",
29 | "gulp-ng-annotate": "~1.0.0",
30 | "gulp-protractor": "~0.0.11",
31 | "gulp-rename": "~1.2.0",
32 | "gulp-replace": "~0.5.0",
33 | "gulp-rev": "~2.0.1",
34 | "gulp-rev-replace": "~0.3.1",
35 | "gulp-ruby-sass": "~0.7.1",
36 | "gulp-size": "~1.1.0",
37 | "gulp-uglify": "~1.0.1",
38 | "gulp-useref": "~1.0.2",
39 | "http-proxy": "~1.7.0",
40 | "jshint-stylish": "~1.0.0",
41 | "karma-jasmine": "~0.3.1",
42 | "karma-phantomjs-launcher": "~0.1.4",
43 | "main-bower-files": "~2.4.0",
44 | "protractor": "~1.4.0",
45 | "require-dir": "^0.3.2",
46 | "run-sequence": "^1.2.2",
47 | "uglify-save-license": "~0.4.1",
48 | "wiredep": "~2.2.0"
49 | },
50 | "engines": {
51 | "node": ">=0.10.0"
52 | },
53 | "scripts": {
54 | "init": "npm install",
55 | "install": "npm install -g bower && bower install",
56 | "lint": "eslint app/",
57 | "test": "npm run lint"
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/beneficiaries/beneficiaries-add/review-beneficiary-dialog/review-beneficiary-dialog.component.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('ReviewBeneficiaryDialogCtrl', ['$scope', '$rootScope', '$state', '$stateParams', '$filter', '$mdDialog', '$mdToast', 'addBeneficiaryFormData', 'BeneficiariesService', ReviewBeneficiaryDialogCtrl])
6 |
7 | function ReviewBeneficiaryDialogCtrl($scope, $rootScope, $state, $stateParams, $filter, $mdDialog, $mdToast, addBeneficiaryFormData, BeneficiariesService) {
8 |
9 | var vm = this;
10 | vm.addBeneficiaryFormData = Object.assign({}, addBeneficiaryFormData);
11 | vm.cancel = cancel;
12 | vm.accountType = accountType;
13 | vm.add = add;
14 |
15 | function cancel() {
16 | $mdDialog.cancel();
17 | }
18 |
19 | function accountType(id) {
20 | if (1 == id) {
21 | return 'Loan Account';
22 | } else {
23 | return 'Savings Account';
24 | }
25 | }
26 |
27 | function add() {
28 | // Sending
29 | BeneficiariesService.beneficiary().save(vm.addBeneficiaryFormData).$promise.then(function () {
30 | $mdDialog.hide("success");
31 | $mdToast.show(
32 | $mdToast.simple()
33 | .textContent('Beneficiary Added Successfully')
34 | .position('top right')
35 | );
36 | vm.clearForm();
37 | }, function (resp) {
38 | var errors = '';
39 | if (resp.data) {
40 | errors = resp.data.errors.map(function (data) {
41 | return data.defaultUserMessage;
42 | });
43 | errors.join(' ');
44 | }
45 | $mdToast.show(
46 | $mdToast.simple()
47 | .textContent('Error in Adding Beneficiary: ' + errors)
48 | .position('top right')
49 | );
50 | $mdDialog.hide("error");
51 | });
52 | }
53 | }
54 | })();
--------------------------------------------------------------------------------
/app/src/common/account.service.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 | //@todo Move this service to the common folder
4 | angular.module('selfService')
5 | .service('AccountService', ['$http', '$resource', 'BASE_URL', 'storageService', AccountService]);
6 |
7 | function AccountService($http, $resource, BASE_URL, storageService) {
8 |
9 | /**
10 | * Get the clients associated with the current user's account.
11 | *
12 | */
13 | this.getClients = function () {
14 | return $resource(BASE_URL + '/self/clients/');
15 | };
16 |
17 | this.getAllAccounts = function (clientId) {//@todo rename this getClientAccounts
18 | //@todo update this to return $resource(BASE_URL+'/self/clients/'+id+'/accounts'); and test
19 | return $resource(BASE_URL + '/self/clients/' + clientId + '/accounts');
20 | };
21 |
22 | this.getClient = function (id) {
23 | return $resource(BASE_URL + '/self/clients/' + id);
24 | }
25 |
26 | this.getClientImage = function (id) {
27 | return $http({
28 | method: 'GET',
29 | url: BASE_URL + '/self/clients/' + id + '/images'
30 | });
31 | }
32 |
33 | this.getClientCharges = function (id) {
34 | return $resource(BASE_URL + '/self/clients/' + id + '/charges?pendingPayment=true');
35 | }
36 |
37 | this.getClientAccounts = function (id) {
38 | return $resource(BASE_URL + '/self/clients/' + id + '/accounts');
39 | }
40 |
41 | this.getLoanAccount = function (id) {
42 | return $resource(BASE_URL + '/self/loans/' + id);
43 | }
44 |
45 | this.setClientId = function (id) {
46 | storageService.setObject('client_id', id);
47 | }
48 |
49 | this.getClientId = function () {
50 | return storageService.getItem('client_id');
51 | }
52 |
53 | }
54 |
55 | })();
56 |
--------------------------------------------------------------------------------
/gulp/proxy.js:
--------------------------------------------------------------------------------
1 | /*jshint unused:false */
2 |
3 | /***************
4 |
5 | This file allow to configure a proxy system plugged into BrowserSync
6 | in order to redirect backend requests while still serving and watching
7 | files from the web project
8 |
9 | IMPORTANT: The proxy is disabled by default.
10 |
11 | If you want to enable it, watch at the configuration options and finally
12 | change the `module.exports` at the end of the file
13 |
14 | ***************/
15 |
16 | 'use strict';
17 |
18 | var httpProxy = require('http-proxy');
19 | var chalk = require('chalk');
20 |
21 | /*
22 | * Location of your backend server
23 | */
24 | var proxyTarget = 'http://server/context/';
25 |
26 | var proxy = httpProxy.createProxyServer({
27 | target: proxyTarget
28 | });
29 |
30 | proxy.on('error', function(error, req, res) {
31 | res.writeHead(500, {
32 | 'Content-Type': 'text/plain'
33 | });
34 |
35 | console.error(chalk.red('[Proxy]'), error);
36 | });
37 |
38 | /*
39 | * The proxy middleware is an Express middleware added to BrowserSync to
40 | * handle backend request and proxy them to your backend.
41 | */
42 | function proxyMiddleware(req, res, next) {
43 | /*
44 | * This test is the switch of each request to determine if the request is
45 | * for a static file to be handled by BrowserSync or a backend request to proxy.
46 | *
47 | * The existing test is a standard check on the files extensions but it may fail
48 | * for your needs. If you can, you could also check on a context in the url which
49 | * may be more reliable but can't be generic.
50 | */
51 | if (/\.(html|css|js|png|jpg|jpeg|gif|ico|xml|rss|txt|eot|svg|ttf|woff|cur)(\?((r|v|rel|rev)=[\-\.\w]*)?)?$/.test(req.url)) {
52 | next();
53 | } else {
54 | proxy.web(req, res);
55 | }
56 | }
57 |
58 | /*
59 | * This is where you activate or not your proxy.
60 | *
61 | * The first line activate if and the second one ignored it
62 | */
63 |
64 | //module.exports = [proxyMiddleware];
65 | module.exports = [];
66 |
--------------------------------------------------------------------------------
/app/src/authentication/register/verification/verification.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/authentication/login/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Self Service
5 |
Self Service is designed by the Mifos Initiative - a global community that aims to
6 | speed-up the elimination of poverty by enabling organizations to more effectively and efficiently
7 | deliver responsible financial services to the world’s poor and unbanked.
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
{{ 'login.heading.logintoyouraccount' | translate }}
17 |
18 |
19 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/reports/view_reports/view_reports.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{'label.headping.reports' | translate}}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | Hold tight loading Reports...
17 |
18 |
19 |
20 |
21 |
22 |
23 | {{'label.heading.name' | translate}}
24 | {{'label.heading.type' | translate}}
25 | {{'label.heading.category' | translate}}
26 |
27 |
28 |
29 |
31 | {{report.reportName}}
32 | {{report.reportType}}
33 | {{report.reportCategory}}
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/beneficiaries/beneficiaries-add/beneficiaries-add.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('BeneficiariesAddCtrl', ['$scope', '$state', '$stateParams', '$filter', '$mdDialog', '$mdToast', 'BeneficiariesService', BeneficiariesAddCtrl]);
6 |
7 | function BeneficiariesAddCtrl($scope, $state, $stateParams, $filter, $mdDialog, $mdToast, BeneficiariesService) {
8 |
9 | var vm = this;
10 | vm.addBeneficiaryFormData = {
11 | "locale": "en_GB"
12 | };
13 | vm.accountTypeOptions = [];
14 | vm.getBeneficiaryTemplate = getBeneficiaryTemplate();
15 | vm.clearForm = clearForm;
16 | vm.submit = submit;
17 |
18 | function getBeneficiaryTemplate() {
19 | BeneficiariesService.template().get().$promise.then(function (data) {
20 | vm.accountTypeOptions = data.accountTypeOptions;
21 | })
22 | }
23 |
24 | function clearForm() {
25 | $scope.addBeneficiaryForm.$setPristine();
26 | $scope.addBeneficiaryForm.$setUntouched();
27 | vm.addBeneficiaryFormData = {
28 | "locale": "en_GB"
29 | };
30 | }
31 |
32 | function submit(ev) {
33 | $mdDialog.show({
34 | controller: 'ReviewBeneficiaryDialogCtrl',
35 | controllerAs: 'vm',
36 | templateUrl: 'src/beneficiaries/beneficiaries-add/review-beneficiary-dialog/review-beneficiary-dialog.html',
37 | parent: angular.element(document.body),
38 | targetEvent: ev,
39 | locals: {addBeneficiaryFormData: vm.addBeneficiaryFormData},
40 | clickOutsideToClose: true
41 | }).then(function (result) {
42 | if (result === "success"){
43 | clearForm();
44 | }
45 | }, function() {
46 | clearForm();
47 | $mdToast.show(
48 | $mdToast.simple()
49 | .textContent('Add Beneficiary Cancelled')
50 | .position('top right')
51 | );
52 | });
53 | }
54 | }
55 | })();
--------------------------------------------------------------------------------
/app/src/authentication/authentication.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Self Service
5 |
Self Service is designed by the Mifos Initiative - a global community that aims to speed-up the elimination of poverty by enabling organizations to more effectively and efficiently deliver responsible financial services to the world’s poor and unbanked.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
{{ 'login.heading.logintoyouraccount' | translate }}
15 |
16 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/authentication/authentication.service.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .service('AuthService', ['$q', '$http', '$rootScope', '$state', '$resource', 'storageService', 'BASE_URL', 'USER_ROLES', AuthService]);
6 |
7 | function AuthService($q, $http, $rootScope, $state, $resource, storageService, BASE_URL, USER_ROLES) {
8 |
9 | var role = '',
10 | userData = '',
11 | isAuthenticated = false;
12 |
13 | storageService.getObject("user_profile").then(function (data) {
14 | if (data) {
15 | isAuthenticated = true;
16 | role = USER_ROLES.user;
17 | userData = data;
18 | }
19 | })
20 |
21 | this.setUser = function (res) {
22 | storageService.setObject('user_profile', res);
23 | isAuthenticated = true;
24 | userData = res;
25 | role = USER_ROLES.user;
26 | }
27 |
28 | this.getUser = function() {
29 | return userData;
30 | }
31 |
32 | this.isAuthenticated = function () {
33 | return isAuthenticated;
34 | };
35 |
36 | this.role = function () {
37 | return role;
38 | }
39 |
40 | this.isAuthorized = function (authorizedRoles) {
41 | if (!angular.isArray(authorizedRoles)) {
42 | authorizedRoles = [authorizedRoles];
43 | }
44 | return (this.isAuthenticated() && authorizedRoles.indexOf(role) !== -1);
45 | }
46 |
47 | //Resource for REST APIs
48 | this.doLogin = function() {
49 | return $resource(BASE_URL +'/self/authentication');
50 | }
51 |
52 | this.logout = function() {
53 | role = '';
54 | userData = '';
55 | isAuthenticated = false;
56 | storageService.clear();
57 | $state.go('login');
58 | }
59 |
60 | this.register = function(data) {
61 | return $http.post(BASE_URL + '/self/registration',data);
62 | }
63 |
64 | this.verifyUser = function(data){
65 | return $http.post(BASE_URL + '/self/registration/user',data);
66 | }
67 |
68 | }
69 |
70 | })();
71 |
--------------------------------------------------------------------------------
/app/src/common/main.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 |
3 | angular.module('selfService')
4 | .controller('MainCtrl', ['navService', '$mdSidenav', '$mdBottomSheet', '$log', '$q', '$state', '$mdToast', '$scope', 'AuthService', 'AccountService', MainCtrl]);
5 |
6 | function MainCtrl(navService, $mdSidenav, $mdBottomSheet, $log, $q, $state, $mdToast, $scope, AuthService, AccountService) {
7 | var vm = this;
8 |
9 | vm.menuItems = [];
10 | vm.profileImage = null;
11 |
12 | vm.selectItem = selectItem;
13 | vm.toggleItemsList = toggleItemsList;
14 | vm.toggleRightSidebar = toggleRightSidebar;
15 | vm.logout = logout;
16 |
17 | vm.profile = getUserData();
18 |
19 |
20 | navService.loadAllItems().then(function (menuItems) {
21 | vm.menuItems = [].concat(menuItems);
22 | });
23 |
24 | function toggleRightSidebar() {
25 | $mdSidenav('right').toggle();
26 | }
27 |
28 | function toggleItemsList() {
29 | var pending = $mdBottomSheet.hide() || $q.when(true);
30 |
31 | pending.then(function () {
32 | $mdSidenav('left').toggle();
33 | });
34 | }
35 |
36 | function selectItem(itemName) {
37 | vm.title = itemName;
38 | vm.toggleItemsList();
39 | }
40 |
41 | function getUserData() {
42 | AccountService.getClientId().then(function (clientId) {
43 | vm.clientId = clientId;
44 | getClient(clientId);
45 | getClientImage(clientId);
46 | });
47 | }
48 |
49 | function getClient(clientId) {
50 | AccountService.getClient(clientId).get().$promise.then( function (data) {
51 | vm.profile = data;
52 | })
53 | }
54 |
55 | function getClientImage(clientId) {
56 | AccountService.getClientImage(clientId).then( function (resp) {
57 | vm.profileImage = resp.data;
58 | }).catch(function() {
59 | // Not Found Profile image
60 | vm.profileImage = null;
61 | });
62 | }
63 |
64 | function logout() {
65 | AuthService.logout();
66 | }
67 |
68 | }
69 |
70 | })();
71 |
--------------------------------------------------------------------------------
/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Mifos - Self Service Application
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/app/src/authentication/register/register.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('RegisterCtrl', ['$scope', '$state', '$mdToast', 'AuthService', '$location', RegisterCtrl]);
6 |
7 | /**
8 | * @module RegisterCtrl
9 | * @description
10 | * Handles Registration of self service user
11 | */
12 | function RegisterCtrl($scope, $state, $mdToast, AuthService, $location) {
13 | var vm = this;
14 | vm.clearForm = clearForm;
15 |
16 | vm.form={
17 | "authenticationMode" :"email"
18 | };
19 |
20 |
21 | function clearForm() {
22 | $scope.form.$setPristine();
23 | $scope.form.$setUntouched();
24 | vm.form = {
25 | "authenticationMode" :"email"
26 | };
27 |
28 | }
29 |
30 | $scope.submit = function() {
31 | AuthService.register(vm.form).then(function () {
32 | $mdToast.show(
33 | $mdToast.simple()
34 | .textContent('Confirmation email is sent') // The success part is not working as the response
35 | .position('top right') // is not in JSON format
36 | );
37 | vm.clearForm();
38 | }, function (resp) {
39 | var errors = '';
40 | if(resp.data){
41 | errors = resp.data.errors.map(function (data) {
42 | return data.defaultUserMessage;
43 | });
44 | errors.join(' ');
45 | }if(errors!=''){
46 | $mdToast.show(
47 | $mdToast.simple()
48 | .textContent('Error in creating user: ' + errors)
49 | .position('top right')
50 | );
51 | }
52 | else{
53 | $mdToast.show(
54 | $mdToast.simple()
55 | .textContent('Confirmation email is sent')
56 | .position('top right')
57 | );
58 | $location.path('/verify');
59 | vm.clearForm();
60 | }
61 |
62 |
63 | });
64 |
65 | }
66 | }
67 |
68 | })();
69 |
--------------------------------------------------------------------------------
/gulp/inject.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var paths = gulp.paths;
6 |
7 | var $ = require('gulp-load-plugins')();
8 |
9 | var wiredep = require('wiredep').stream;
10 |
11 | gulp.task('inject:build', ['styles'], function () {
12 | var injectStyles = gulp.src(
13 | paths.dist + '/styles/*.css',
14 | {read: false}
15 | );
16 |
17 | var injectScripts = gulp.src([
18 | paths.dist + '/js/*.js'
19 | ]).pipe($.angularFilesort());
20 |
21 | var injectOptions = {
22 | ignorePath: [paths.dist],
23 | addRootSlash: false
24 | };
25 |
26 | var wiredepOptions = {
27 | fileTypes: {
28 | html: {
29 | replace: {
30 | js: function(filePath) {
31 | return '';
32 | },
33 | css: function(filePath) {
34 | return ' ';
35 | }
36 | }
37 | }
38 | }
39 | };
40 |
41 | return gulp.src(paths.src + '/*.html')
42 | .pipe(wiredep(wiredepOptions))
43 | .pipe($.inject(injectStyles, injectOptions))
44 | .pipe($.inject(injectScripts, injectOptions))
45 | .pipe(gulp.dest(paths.dist));
46 | });
47 |
48 | gulp.task('inject', ['styles'], function () {
49 |
50 | var injectStyles = gulp.src([
51 | paths.tmp + '/serve/**/*.css',
52 | '!' + paths.tmp + '/serve/app/vendor.css'
53 | ], {read: false});
54 |
55 | var injectScripts = gulp.src([
56 | paths.src + '/**/*.js',
57 | '!' + paths.src + '/src/**/*.spec.js',
58 | '!' + paths.src + '/src/**/*.mock.js'
59 | ]).pipe($.angularFilesort());
60 |
61 | var injectOptions = {
62 | ignorePath: [paths.src, paths.tmp + '/serve'],
63 | addRootSlash: false
64 | };
65 |
66 | var wiredepOptions = {
67 | directory: 'bower_components',
68 | exclude: [/bootstrap\.css/, /foundation\.css/]
69 | };
70 |
71 | return gulp.src(paths.src + '/*.html')
72 | .pipe($.inject(injectStyles, injectOptions))
73 | .pipe($.inject(injectScripts, injectOptions))
74 | .pipe(wiredep(wiredepOptions))
75 | .pipe(gulp.dest(paths.tmp + '/serve'));
76 |
77 | });
78 |
--------------------------------------------------------------------------------
/app/src/tpt/tpt.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('TPTCtrl', ['$scope', '$rootScope', '$stateParams', '$filter', '$mdDialog', '$mdDateLocale', '$mdToast', 'AccountTransferService', TPTCtrl]);
6 |
7 | function TPTCtrl($scope, $rootScope, $stateParams, $filter, $mdDialog, $mdDateLocale, $mdToast, AccountTransferService) {
8 |
9 | var vm = this;
10 | vm.fromAccountOptions = [];
11 | vm.toAccountOptions = [];
12 | vm.transferFormData = getTransferFormDataObj()
13 |
14 | vm.getTransferTemplate = getTransferTemplate();
15 | vm.clearForm = clearForm;
16 | vm.submit = submit;
17 |
18 | // FORMAT THE DATE FOR THE DATEPICKER
19 | $mdDateLocale.formatDate = function (date) {
20 | return $filter('date')(date, "dd-MM-yyyy");
21 | };
22 |
23 | function getTransferFormDataObj() {
24 | return {
25 | transferDate: new Date()
26 | };
27 | }
28 |
29 | function getTransferTemplate() {
30 | AccountTransferService.getTransferTemplate().get({type: "tpt"},function (data) {
31 | vm.fromAccountOptions = data.fromAccountOptions;
32 | vm.toAccountOptions = data.toAccountOptions;
33 | });
34 | }
35 |
36 | function clearForm() {
37 | vm.transferFormData = getTransferFormDataObj();
38 | $scope.transferForm.$setPristine();
39 | $scope.transferForm.$setUntouched();
40 | }
41 |
42 | function submit(ev) {
43 | $mdDialog.show({
44 | controller: 'ReviewTPTDialogCtrl',
45 | controllerAs: 'vm',
46 | templateUrl: 'src/tpt/review-tpt-dialog/review-tpt-dialog.html',
47 | parent: angular.element(document.body),
48 | targetEvent: ev,
49 | locals: {transferFormData: vm.transferFormData},
50 | clickOutsideToClose: true
51 | }).then(function (result) {
52 | if(result === "success"){
53 | clearForm();
54 | }
55 | }, function () {
56 | clearForm();
57 | $mdToast.show(
58 | $mdToast.simple()
59 | .textContent('Transfer Cancelled')
60 | .position('top right')
61 | );
62 | });
63 | }
64 |
65 |
66 | }
67 | })();
--------------------------------------------------------------------------------
/app/src/accounts/savings-account-detail/savings-account-detail.component.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('SavingsAccountViewCtrl', ['$state', '$stateParams', '$filter', 'SavingsAccountService', SavingsAccountViewCtrl]);
6 |
7 | /**
8 | * @module SavingsAccountViewCtrl
9 | * @description
10 | * Handles the individial savings account detail page
11 | */
12 | function SavingsAccountViewCtrl($state, $stateParams, $filter, SavingsAccountService) {
13 |
14 | var vm = this;
15 | vm.loadingSavingsAccount = true;
16 |
17 | /**
18 | * @name statusClass
19 | * @type {string}
20 | * @description Stores the status class of savings account
21 | */
22 | vm.statusClass = '';
23 |
24 | /**
25 | * @name savingsAccountDetails
26 | * @type {object}
27 | * @description Stores the savings account details from server
28 | */
29 | vm.savingsAccountDetails = getSavingsDetail($stateParams.id);
30 |
31 | /**
32 | * @name transactions
33 | * @type {Array}
34 | */
35 | vm.transactions = [];
36 |
37 | vm.getStatusClass = getStatusClass;
38 | vm.deposit = deposit;
39 | vm.transfer = transfer;
40 |
41 | /**
42 | * @method getSavingsDetail
43 | * @description Gets savings account detail from server
44 | * @param id {number} Savings Account id
45 | */
46 | function getSavingsDetail(id) {
47 | SavingsAccountService.savingsAccount().get({id: id, associations: 'transactions,charges'}).$promise.then(function(res) {
48 | vm.loadingSavingsAccount = false;
49 | vm.savingsAccountDetails = res;
50 | vm.transactions = res.transactions;
51 | getStatusClass();
52 | });
53 | }
54 |
55 | function getStatusClass() {
56 | var statusClass = $filter('StatusLookup')(vm.savingsAccountDetails.status.code);
57 | statusClass = 'bg_' + statusClass;
58 | if(vm.savingsAccountDetails.subStatus.id !== 0) {
59 | statusClass = $filter('StatusLookup')(vm.savingsAccountDetails.status.code+vm.savingsAccountDetails.subStatus.value);
60 | }
61 |
62 | vm.statusClass = statusClass;
63 | }
64 |
65 | function deposit() {
66 | $state.go('app.transfers', {
67 | toAccount: vm.savingsAccountDetails
68 | });
69 | }
70 |
71 | function transfer() {
72 | $state.go('app.transfers', {
73 | fromAccount: vm.savingsAccountDetails
74 | });
75 | }
76 | }
77 | })();
--------------------------------------------------------------------------------
/app/src/accounts/account-list/account-list.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('AccountCtrl', ['$scope', '$rootScope', '$state', 'AccountService', 'AuthService', AccountCtrl]);
6 |
7 | function AccountCtrl($scope, $rootScope, $state, AccountService, AuthService) {
8 |
9 | var vm = this;
10 | vm.selected = [];
11 | vm.getAccounts = getAccounts;
12 | vm.onPaginate = onPaginate;
13 | vm.onReorder = onReorder;
14 | vm.routeTo = routeTo;
15 | vm.userData = AuthService.getUser();
16 | vm.clientId = getClient();//@todo check if this is behind the 2 calls
17 | vm.accounts = [];
18 | vm.loanAccounts = [];
19 | vm.savingsAccounts = [];
20 | vm.shareAccounts = [];
21 | vm.loadingAccountInfo = true;
22 | vm.tabIndex = sessionStorage.getItem("tab");
23 |
24 |
25 | vm.query = {
26 | limit: 5,
27 | offset: 1
28 | };
29 |
30 | function getClient() {
31 | AccountService.getClientId().then(function (clientId) {
32 | vm.clientId = clientId;
33 | getAccounts(clientId);
34 | });
35 | }
36 |
37 | function getAccounts(accountNo) {
38 | AccountService.getAllAccounts(accountNo).get().$promise.then(function (res) {
39 | vm.loanAccounts = res.loanAccounts;
40 | vm.savingsAccounts = res.savingsAccounts;
41 | vm.shareAccounts = res.shareAccounts;
42 | vm.loadingAccountInfo = false;
43 | });
44 | }
45 |
46 | function onPaginate(offset, limit) {
47 | getAccounts(angular.extend({}, vm.query, {offset: offset, limit: limit}));
48 | }
49 |
50 | function onReorder(order) {
51 | getAccounts(angular.extend({}, vm.query, {order: order}));
52 | }
53 |
54 | function routeTo(accountType, id) {
55 | var routingSlug = 'viewloanaccount';
56 | if ('savings' == accountType) {
57 | routingSlug = 'viewsavingsaccount';
58 | sessionStorage.setItem("tab", "1");
59 | } else if ('loan' == accountType) {
60 | routingSlug = 'viewloanaccount';
61 | sessionStorage.setItem("tab", "0");
62 | } else {
63 | routingSlug = 'viewshareaccount';
64 | sessionStorage.setItem("tab", "2");
65 | }
66 | $state.go('app.'+routingSlug, {id: id});
67 | }
68 | }
69 |
70 | })();
71 |
--------------------------------------------------------------------------------
/app/src/accounts/loan-account-detail/loan-account-detail.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('LoanAccountViewCtrl', ['$state', '$stateParams', '$filter', 'LoanAccountService', LoanAccountViewCtrl]);
6 |
7 | /**
8 | * @module LoanAccountViewCtrl
9 | * @description
10 | * Handles the Loan Account Details Page.
11 | */
12 | function LoanAccountViewCtrl($state, $stateParams, $filter, LoanAccountService) {
13 |
14 | var vm = this;
15 |
16 | /**
17 | * @name loadingLoanAccountInfo
18 | * @description flag to check whether account info is loaded or not
19 | * @type {boolean}
20 | */
21 | vm.loadingLoanAccountInfo = true;
22 |
23 | /**
24 | * @name loanAccountDetails
25 | * @type {object}
26 | * @description To store the loan Account details returned by server
27 | */
28 | vm.loanAccountDetails = getLoanDetails($stateParams.id);
29 |
30 | /**
31 | * @name statusClass
32 | * @type {string}
33 | * @description To store the css class for loan status [active, pending, ...]
34 | */
35 | vm.statusClass = '';
36 |
37 | vm.repaymentSchedule = {};
38 |
39 | vm.makePayment = makePayment;
40 |
41 | /**
42 | * @method getLoanDetails
43 | * @description To get the loan details from the server
44 | * @param id {number} Loan Account id
45 | */
46 | function getLoanDetails(id) {
47 | LoanAccountService.loanAccount().get({
48 | id: id,
49 | associations:'repaymentSchedule,transactions'
50 | }).$promise.then(function (res) {
51 | vm.loadingLoanAccountInfo = false;
52 | vm.loanAccountDetails = res;
53 | getStatusClass();
54 | });
55 | }
56 |
57 | /**
58 | * @method getStatusClass
59 | * @description To get the loan account status through the status lookup filter
60 | */
61 | function getStatusClass() {
62 | var statusClass = $filter('StatusLookup')(vm.loanAccountDetails.status.code);
63 | statusClass = 'bg_' + statusClass;
64 | if (vm.loanAccountDetails.inArrears) {
65 | statusClass += 'overdue';
66 | }
67 | vm.statusClass = statusClass;
68 | }
69 |
70 | function makePayment() {
71 | $state.go('app.transfers', {
72 | toAccount: vm.loanAccountDetails
73 | });
74 | }
75 | }
76 | })();
--------------------------------------------------------------------------------
/app/src/beneficiaries/beneficiaries-add/beneficiaries-add.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ 'label.heading.addbeneficiaries' | translate }}
6 |
7 |
8 |
9 |
10 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/beneficiaries/beneficiaries-edit/beneficiaries-edit.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ 'label.heading.editbeneficiaries' | translate }}
6 |
7 |
8 |
9 |
10 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/beneficiaries/beneficiaries-list/beneficiaries-list.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('BeneficiariesListCtrl', ['$scope', '$rootScope', '$state', '$stateParams', '$mdDialog', '$mdToast', 'BeneficiariesService', BeneficiariesListCtrl]);
6 |
7 | function BeneficiariesListCtrl($scope, $rootScope, $state, $stateParams, $mdDialog, $mdToast, BeneficiariesService) {
8 |
9 | var vm = this;
10 | vm.loadingBeneficiaries = true;
11 | vm.beneficiaries = [];
12 | vm.beneficiariesFilter = "";
13 | vm.page = 1;
14 | vm.query = {
15 | limit: 5,
16 | offset: 0
17 | }
18 |
19 | vm.getBeneficiaries = getBeneficiaries();
20 | vm.addBeneficiary = addBeneficiary;
21 | vm.goToEdit = goToEdit;
22 | vm.deleteConfirm = deleteConfirm;
23 |
24 | function getBeneficiaries() {
25 | BeneficiariesService.getBeneficiaries().query().$promise.then(function(data) {
26 | vm.beneficiaries = data;
27 | vm.loadingBeneficiaries = false;
28 | });
29 | }
30 |
31 | function addBeneficiary() {
32 | $state.go('app.addbeneficiary');
33 | }
34 |
35 | function goToEdit(beneficiary) {
36 | $state.go('app.editbeneficiary',{
37 | id: beneficiary.id,
38 | data: beneficiary
39 | });
40 | }
41 |
42 | function deleteConfirm(ev, beneficiary) {
43 | var confirm = $mdDialog.confirm()
44 | .title('Are you sure you want to delete?')
45 | .textContent('This beneficiary will be removed from your account')
46 | .ariaLabel('Lucky day')
47 | .targetEvent(ev)
48 | .ok('Delete!')
49 | .cancel('Cancel');
50 |
51 | $mdDialog.show(confirm).then(function() {
52 | BeneficiariesService.beneficiary().delete({
53 | id: beneficiary.id
54 | }, function() {
55 | $mdToast.show(
56 | $mdToast.simple()
57 | .textContent('Beneficiary Deleted Successfully')
58 | .position('top right')
59 | );
60 | vm.beneficiaries = vm.beneficiaries.filter(function (benef) {
61 | return benef.id !== beneficiary.id
62 | });
63 | });
64 | }, function() {
65 | $mdToast.show(
66 | $mdToast.simple()
67 | .textContent('Error in Deleting Beneficiary')
68 | .position('top right')
69 | );
70 | });
71 | }
72 | }
73 | })();
--------------------------------------------------------------------------------
/app/src/tpt/tpt.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ 'label.heading.tpt' | translate }}
6 |
7 |
8 |
9 |
10 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/tpt/review-tpt-dialog/review-tpt-dialog.component.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('ReviewTPTDialogCtrl', ['$scope', '$rootScope', '$stateParams', '$filter', '$mdDialog', '$mdToast', 'transferFormData', 'AccountTransferService', ReviewTPTDialogCtrl]);
6 |
7 | function ReviewTPTDialogCtrl($scope, $rootScope, $stateParams, $filter, $mdDialog, $mdToast, transferFormData, AccountTransferService) {
8 |
9 | var vm = this;
10 | vm.transferFormData = Object.assign({}, transferFormData);
11 | vm.cancel = cancel;
12 | vm.transfer = transfer;
13 |
14 | vm.transferFormData.transferDate = $filter('DateFormat')(transferFormData.transferDate);
15 |
16 | function cancel() {
17 | $mdDialog.cancel();
18 | }
19 |
20 | function transfer() {
21 | // Transforming Request Data
22 | var transferData = {
23 | fromOfficeId: vm.transferFormData.fromAccount.officeId,
24 | fromClientId: vm.transferFormData.fromAccount.clientId,
25 | fromAccountType: vm.transferFormData.fromAccount.accountType.id,
26 | fromAccountId: vm.transferFormData.fromAccount.accountId,
27 | toOfficeId: vm.transferFormData.toAccount.officeId,
28 | toClientId: vm.transferFormData.toAccount.clientId,
29 | toAccountType: vm.transferFormData.toAccount.accountType.id,
30 | toAccountId: vm.transferFormData.toAccount.accountId,
31 | dateFormat: "dd MMMM yyyy",
32 | locale: "en",
33 | transferDate: vm.transferFormData.transferDate,
34 | transferAmount: "" + vm.transferFormData.amount,
35 | transferDescription: vm.transferFormData.remark
36 | }
37 | // Sending
38 | AccountTransferService.transfer().save({type: "tpt"},transferData).$promise.then(function () {
39 | $mdDialog.hide("success");
40 | $mdToast.show(
41 | $mdToast.simple()
42 | .textContent('Transfer Completed Successfully')
43 | .position('top right')
44 | );
45 | }, function (resp) {
46 | var errors = '';
47 | if(resp.data){
48 | errors = resp.data.errors.map(function (data) {
49 | return data.defaultUserMessage;
50 | });
51 | errors.join(' ');
52 | }
53 | $mdToast.show(
54 | $mdToast.simple()
55 | .textContent('Error in Completing Transfer: ' + errors)
56 | .position('top right')
57 | );
58 | $mdDialog.hide("error");
59 |
60 | });
61 |
62 | }
63 | }
64 | })();
--------------------------------------------------------------------------------
/app/src/transfers/review-transfer-dialog/review-transfer-dialog.component.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('ReviewTransferDialogCtrl', ['$scope', '$rootScope', '$stateParams', '$filter', '$mdDialog', '$mdToast', 'transferFormData', 'AccountTransferService', ReviewTransferDialogCtrl]);
6 |
7 | function ReviewTransferDialogCtrl($scope, $rootScope, $stateParams, $filter, $mdDialog, $mdToast, transferFormData, AccountTransferService) {
8 |
9 | var vm = this;
10 | vm.transferFormData = Object.assign({}, transferFormData);
11 | vm.cancel = cancel;
12 | vm.transfer = transfer;
13 |
14 | vm.transferFormData.transferDate = $filter('DateFormat')(transferFormData.transferDate);
15 |
16 | function cancel() {
17 | $mdDialog.cancel();
18 | }
19 |
20 | function transfer() {
21 | // Transforming Request Data
22 | var transferData = {
23 | fromOfficeId: vm.transferFormData.fromAccount.officeId,
24 | fromClientId: vm.transferFormData.fromAccount.clientId,
25 | fromAccountType: vm.transferFormData.fromAccount.accountType.id,
26 | fromAccountId: vm.transferFormData.fromAccount.accountId,
27 | toOfficeId: vm.transferFormData.toAccount.officeId,
28 | toClientId: vm.transferFormData.toAccount.clientId,
29 | toAccountType: vm.transferFormData.toAccount.accountType.id,
30 | toAccountId: vm.transferFormData.toAccount.accountId,
31 | dateFormat: "dd MMMM yyyy",
32 | locale: "en",
33 | transferDate: vm.transferFormData.transferDate,
34 | transferAmount: "" + vm.transferFormData.amount,
35 | transferDescription: vm.transferFormData.remark
36 | }
37 | // Sending
38 | AccountTransferService.transfer().save(transferData).$promise.then(function () {
39 | $mdDialog.hide("success");
40 | $mdToast.show(
41 | $mdToast.simple()
42 | .textContent('Transfer Completed Successfully')
43 | .position('top right')
44 | );
45 | }, function (resp) {
46 | var errors = '';
47 | if(resp.data){
48 | errors = resp.data.errors.map(function (data) {
49 | return data.defaultUserMessage;
50 | });
51 | errors.join(' ');
52 | }
53 | $mdToast.show(
54 | $mdToast.simple()
55 | .textContent('Error in Completing Transfer: ' + errors)
56 | .position('top right')
57 | );
58 | $mdDialog.hide("error");
59 |
60 | });
61 |
62 | }
63 | }
64 | })();
--------------------------------------------------------------------------------
/app/src/beneficiaries/beneficiaries-edit/beneficiaries-edit.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('BeneficiariesEditCtrl', ['$scope', '$rootScope', '$state', '$stateParams', '$mdToast', 'BeneficiariesService', BeneficiariesEditCtrl]);
6 |
7 | function BeneficiariesEditCtrl($scope, $rootScope, $state, $stateParams, $mdToast, BeneficiariesService) {
8 |
9 | var vm = this;
10 | vm.editBeneficiaryFormData = {
11 | "locale": "en_GB"
12 | };
13 | vm.beneficiary = $stateParams.data;
14 | vm.accountTypeOptions = [];
15 | vm.getBeneficiaryTemplate = getBeneficiaryTemplate();
16 | vm.clearForm = clearForm;
17 | vm.submit = submit;
18 |
19 | function getBeneficiaryTemplate() {
20 | BeneficiariesService.template().get().$promise.then(function (data) {
21 | vm.accountTypeOptions = data.accountTypeOptions;
22 | });
23 |
24 | if(vm.beneficiary !== null) {
25 | vm.editBeneficiaryFormData.accountType = vm.beneficiary.accountType.id;
26 | vm.editBeneficiaryFormData.accountNumber = vm.beneficiary.accountNumber;
27 | vm.editBeneficiaryFormData.officeName = vm.beneficiary.officeName;
28 | vm.editBeneficiaryFormData.transferLimit = vm.beneficiary.transferLimit;
29 | vm.editBeneficiaryFormData.name = vm.beneficiary.name;
30 | }
31 | }
32 |
33 | function clearForm() {
34 | vm.editBeneficiaryFormData = {
35 | "locale": "en_GB"
36 | };
37 | $scope.editBeneficiaryForm.$setPristine();
38 | $scope.addBeneficiaryForm.$setUntouched();
39 | }
40 |
41 | function submit() {
42 | var data = {
43 | name: vm.editBeneficiaryFormData.name,
44 | transferLimit: vm.editBeneficiaryFormData.transferLimit
45 | }
46 |
47 | BeneficiariesService.beneficiary().update({id: vm.beneficiary.id}, data).$promise.then(function () {
48 | $mdToast.show(
49 | $mdToast.simple()
50 | .textContent('Beneficiary Updated Successfully')
51 | .position('top right')
52 | );
53 | }, function (resp) {
54 | var errors = '';
55 | if(resp.data){
56 | errors = resp.data.errors.map(function (data) {
57 | return data.defaultUserMessage;
58 | });
59 | errors.join(' ');
60 | }
61 | $mdToast.show(
62 | $mdToast.simple()
63 | .textContent('Error in Adding Beneficiary: ' + errors)
64 | .position('top right')
65 | );
66 |
67 | });
68 | }
69 | }
70 | })();
--------------------------------------------------------------------------------
/app/src/transfers/transfers.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ 'label.heading.transfers' | translate }}
6 |
7 |
8 |
9 |
10 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/authentication/login/login.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('LoginCtrl', ['$scope', '$rootScope', '$state', '$mdToast', 'AUTH_EVENTS', 'AuthService', 'AccountService', LoginCtrl]);
6 |
7 | function LoginCtrl($scope, $rootScope, $state, $mdToast, AUTH_EVENTS, AuthService, AccountService) {
8 |
9 | var vm = this;
10 | vm.authenticating = false;
11 |
12 | /**
13 | * @method doLogin
14 | * @description To perform the login action on the page
15 | */
16 | $scope.doLogin = function () {
17 | vm.authenticating = true;
18 | AuthService.doLogin().save($scope.loginData).$promise
19 | .then(function (result) {
20 | AuthService.setUser(result);
21 | AccountService.getClients().get().$promise
22 | .then(function (res) {
23 | vm.authenticating = false;
24 | $state.go("app.dashboard");
25 | if (res.pageItems.length !== 0) {
26 | AccountService.setClientId(res.pageItems[0].id);
27 | $mdToast.show(
28 | $mdToast.simple()
29 | .content("Successful Login")
30 | .hideDelay(2000)
31 | .position('top right')
32 | );
33 |
34 | } else {
35 | $mdToast.show(
36 | $mdToast.simple()
37 | .content("No Clients Found")
38 | .hideDelay(2000)
39 | .position('top right')
40 | );
41 | AuthService.logout();
42 | }
43 | })
44 | .catch(function () {
45 | vm.authenticating = false;
46 | $mdToast.show(
47 | $mdToast.simple()
48 | .content("Not a Self Service User")
49 | .hideDelay(2000)
50 | .position('top right')
51 | );
52 | AuthService.logout();
53 | })
54 | }).catch(function () {
55 | vm.authenticating = false;
56 | $mdToast.show(
57 | $mdToast.simple()
58 | .content("Invalid Login Credentials")
59 | .hideDelay(2000)
60 | .position('top right')
61 | );
62 | })
63 | }
64 |
65 | }
66 |
67 | })();
68 |
--------------------------------------------------------------------------------
/app/src/common/main.filters.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .filter('DateFormat', function (dateFilter) {
6 | return function (input) {
7 | if (input) {
8 | var tDate = new Date(input);
9 | return dateFilter(tDate, 'dd MMMM yyyy');//@todo Add this format to localstorage
10 | }
11 | return '';
12 | };
13 | })
14 | .filter('StatusLookup', function () {
15 | return function (input) {
16 | var cssClassNameLookup = {
17 | "true": "statusactive",
18 | "false": "statusdeleted",
19 | "Active": "statusactive",
20 | "loanStatusType.submitted.and.pending.approval": "statuspending",
21 | "loanStatusType.approved": "statusApproved",
22 | "loanStatusType.active": "statusactive",
23 | "loanStatusType.overpaid": "statusoverpaid",
24 | "savingsAccountStatusType.submitted.and.pending.approval": "statuspending",
25 | "savingsAccountStatusType.approved": "statusApproved",
26 | "savingsAccountStatusType.active": "statusactive",
27 | "savingsAccountStatusType.activeInactive": "statusactiveoverdue",
28 | "savingsAccountStatusType.activeDormant": "statusactiveoverdue",
29 | "savingsAccountStatusType.matured": "statusmatured",
30 | "loanProduct.active": "statusactive",
31 | "clientStatusType.pending": "statuspending",
32 | "clientStatusType.closed":"statusclosed",
33 | "clientStatusType.rejected":"statusrejected",
34 | "clientStatusType.withdraw":"statuswithdraw",
35 | "clientStatusType.active": "statusactive",
36 | "clientStatusType.submitted.and.pending.approval": "statuspending",
37 | "clientStatusTYpe.approved": "statusApproved",
38 | "clientStatusType.transfer.in.progress": "statustransferprogress",
39 | "clientStatusType.transfer.on.hold": "statustransferonhold",
40 | "groupingStatusType.active": "statusactive",
41 | "groupingStatusType.pending": "statuspending",
42 | "groupingStatusType.submitted.and.pending.approval": "statuspending",
43 | "groupingStatusType.approved": "statusApproved",
44 | "shareAccountStatusType.submitted.and.pending.approval": "statuspending",
45 | "shareAccountStatusType.approved": "statusApproved",
46 | "shareAccountStatusType.active": "statusactive",
47 | "shareAccountStatusType.rejected": "statusrejected",
48 | "purchasedSharesStatusType.applied": "statuspending",
49 | "purchasedSharesStatusType.approved": "statusApproved",
50 | "purchasedSharesStatusType.rejected": "statusrejected"
51 | }
52 |
53 | return cssClassNameLookup[input];
54 | }
55 | })
56 |
57 | })();
58 |
59 |
--------------------------------------------------------------------------------
/app/app.config.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 | //IS thsichaneg hknjseff
4 | angular.module('selfService')
5 | .config(function ($mdThemingProvider, $mdIconProvider, $httpProvider, $translateProvider, TENANT_IDENTIFIER) {
6 |
7 | $mdThemingProvider
8 | .theme('default')
9 | .primaryPalette('blue', {
10 | 'default': '600'
11 | })
12 | .accentPalette('pink', {
13 | 'default': '500'
14 | })
15 | .warnPalette('defaultPrimary');
16 |
17 | $mdThemingProvider
18 | .theme('dark', 'default')
19 | .primaryPalette('defaultPrimary')
20 | .dark();
21 |
22 | $mdThemingProvider
23 | .theme('grey', 'default')
24 | .primaryPalette('grey');
25 |
26 | $mdThemingProvider
27 | .theme('custom', 'default')
28 | .primaryPalette('defaultPrimary', {
29 | 'hue-1': '50'
30 | });
31 |
32 | $mdThemingProvider
33 | .definePalette('defaultPrimary', {
34 | '50': '#FFFFFF',
35 | '100': 'rgb(255, 198, 197)',
36 | '200': '#E75753',
37 | '300': '#E75753',
38 | '400': '#E75753',
39 | '500': '#E75753',
40 | '600': '#E75753',
41 | '700': '#E75753',
42 | '800': '#E75753',
43 | '900': '#E75753',
44 | 'A100': '#E75753',
45 | 'A200': '#E75753',
46 | 'A400': '#E75753',
47 | 'A700': '#E75753'
48 | });
49 |
50 | $mdIconProvider
51 | .icon('user', 'assets/images/user.svg', 64);
52 |
53 | $httpProvider.defaults.useXDomain = true;
54 | //Set headers
55 | $httpProvider.defaults.headers.common['Content-Type'] = 'application/json; charset=utf-8';
56 | // Mifos set Tenant
57 | $httpProvider.defaults.headers.common['Fineract-Platform-TenantId'] = TENANT_IDENTIFIER;
58 | $httpProvider.interceptors.push('APIRequestInterceptor');
59 |
60 | var defaultLocale = 'en';
61 | $translateProvider
62 | .useStaticFilesLoader({
63 | prefix: 'global-translations/locale-',
64 | suffix: '.json'
65 | })
66 | .useLocalStorage()
67 | .useSanitizeValueStrategy('escape')
68 | .preferredLanguage(defaultLocale)
69 | .fallbackLanguage(defaultLocale);
70 | }
71 | )
72 |
73 | .run(['$rootScope', '$location', 'AuthService', function($rootScope, $location, AuthService) {
74 | $rootScope.$on('$locationChangeStart', function (event) {
75 | // redirect to login page if not logged in and trying to access a restricted page
76 | var restrictedPage = $.inArray($location.path(), ['/login', '/forgot', '/register', '/verify']) === -1;
77 | var loggedIn = AuthService.isAuthenticated();
78 | if (restrictedPage) {
79 | if(!loggedIn) {
80 | $location.path('/login');
81 | }
82 | }
83 | else if(loggedIn) {
84 | event.preventDefault();
85 | }
86 | });
87 | }])
88 |
89 | })();
90 |
--------------------------------------------------------------------------------
/gulp/build.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp');
4 |
5 | var paths = gulp.paths;
6 |
7 | var $ = require('gulp-load-plugins')({
8 | pattern: ['gulp-*', 'main-bower-files', 'uglify-save-license', 'del']
9 | });
10 | var hash = require('gulp-hash-filename');
11 |
12 | var wiredep = require('wiredep').stream;
13 | var runSequence = require('run-sequence');
14 |
15 | gulp.task('partials', function () {
16 | return gulp.src([
17 | paths.src + '/src/**/*.html',
18 | paths.tmp + '/src/**/*.html'
19 | ])
20 | .pipe($.minifyHtml({
21 | empty: true,
22 | spare: true,
23 | quotes: true
24 | }))
25 | .pipe($.angularTemplatecache('templateCacheHtml.js', {
26 | module: 'selfService',
27 | root: 'src/'
28 | }))
29 | .pipe(hash({
30 | "format": "{name}.{hash:8}{ext}"
31 | }))
32 | .pipe(gulp.dest(paths.dist + '/js'))
33 | });
34 |
35 | gulp.task('html', ['partials'], function () {
36 |
37 | return gulp.src(paths.src + '/*.html')
38 | .pipe($.minifyHtml({
39 | empty: true,
40 | spare: true,
41 | quotes: true
42 | }))
43 | .pipe(gulp.dest(paths.dist + '/'))
44 | .pipe($.size({title: paths.dist + '/', showFiles: true}));
45 | });
46 |
47 | gulp.task('vendor', function () {
48 | var jsFilter = $.filter('**/*.js');
49 | var cssFilter = $.filter('**/*.css');
50 |
51 | return gulp.src($.mainBowerFiles())
52 | .pipe(jsFilter)
53 | .pipe($.angularFilesort())
54 | .pipe(gulp.dest(paths.dist + '/vendor'))
55 | .pipe(jsFilter.restore())
56 | .pipe(cssFilter)
57 | .pipe(gulp.dest(paths.dist + '/vendor'))
58 | .pipe(cssFilter.restore())
59 | });
60 |
61 | gulp.task('app-js', function () {
62 | return gulp.src(paths.src + '/*.js')
63 | .pipe(gulp.dest(paths.dist));
64 | })
65 |
66 | gulp.task('js', ['vendor', 'partials', 'app-js'], function () {
67 |
68 | return gulp.src([
69 | paths.src + '/src/**/*.js',
70 | '!' + paths.src + '/src/**/*.spec.js',
71 | '!' + paths.src + '/src/**/*.mock.js'
72 | ])
73 | .pipe($.angularFilesort())
74 | .pipe($.concat('app.js'))
75 | .pipe(hash({
76 | "format": "{name}.{hash:8}{ext}"
77 | }))
78 | .pipe(gulp.dest(paths.dist + '/js'));
79 | })
80 |
81 | gulp.task('images', function () {
82 | return gulp.src(paths.src + '/assets/images/**/*')
83 | .pipe(gulp.dest(paths.dist + '/assets/images/'));
84 | });
85 |
86 | gulp.task('fonts', function () {
87 | return gulp.src($.mainBowerFiles())
88 | .pipe($.filter('**/*.{eot,svg,ttf,woff}'))
89 | .pipe($.flatten())
90 | .pipe(gulp.dest(paths.dist + '/fonts/'));
91 | });
92 |
93 | gulp.task('misc', function () {
94 | return gulp.src([
95 | paths.src + '/**/*.ico',
96 | paths.src + '/**/locale-*.json'
97 | ])
98 | .pipe(gulp.dest(paths.dist + '/'));
99 | });
100 |
101 | gulp.task('clean', function (done) {
102 | $.del([paths.dist + '/', paths.tmp + '/'], done);
103 | });
104 |
105 | gulp.task('build', function (callback) {
106 | runSequence('clean',
107 | 'js', 'inject:build',
108 | 'images', 'fonts', 'misc',
109 | callback);
110 | });
111 |
--------------------------------------------------------------------------------
/app/src/loan-application/loan-application.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ 'label.heading.applyloan' | translate }}
6 |
7 |
8 |
9 |
10 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/app/src/shares-application/shares-application.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ 'label.heading.applyshares' | translate }}
6 |
7 |
8 |
9 |
10 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/app/src/transfers/transfers.component.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('AccountTransferCtrl', ['$scope', '$stateParams', '$filter', '$mdDialog', '$mdDateLocale', '$mdToast', 'AccountTransferService', AccountTransferCtrl]);
6 |
7 | /**
8 | * @module AccountTransferCtrl
9 | * @description
10 | * Account Transfer Controller
11 | */
12 | function AccountTransferCtrl($scope, $stateParams, $filter, $mdDialog, $mdDateLocale, $mdToast, AccountTransferService) {
13 |
14 | var vm = this;
15 | vm.fromAccountOptions = [];
16 | vm.toAccountOptions = [];
17 | vm.transferFormData = getTransferFormDataObj()
18 |
19 | vm.disabledToAccount = false;
20 | vm.disabledfromAccount = false;
21 |
22 | vm.transferFormData = getTransferFormDataObj();
23 | vm.getTransferTemplate = getTransferTemplate();
24 | vm.clearForm = clearForm;
25 | vm.submit = submit;
26 |
27 | // FORMAT THE DATE FOR THE DATEPICKER
28 | $mdDateLocale.formatDate = function (date) {
29 | return $filter('date')(date, "dd-MM-yyyy");
30 | };
31 |
32 | function getTransferFormDataObj() {
33 | return {
34 | transferDate: new Date()
35 | };
36 | }
37 |
38 | function getTransferTemplate() {
39 | AccountTransferService.getTransferTemplate().get(function (data) {
40 | vm.fromAccountOptions = data.fromAccountOptions;
41 | vm.toAccountOptions = data.toAccountOptions;
42 |
43 | if($stateParams.toAccount) {
44 | var i = 0;
45 | for(i=0; i < vm.toAccountOptions.length; i++) {
46 | if(vm.toAccountOptions[i].accountNo == $stateParams.toAccount.accountNo) {
47 | vm.transferFormData.toAccount = vm.toAccountOptions[i];
48 | vm.disabledToAccount = true;
49 | break;
50 | }
51 | }
52 | }
53 |
54 | if($stateParams.fromAccount) {
55 | for(i=0; i < vm.fromAccountOptions.length; i++) {
56 | if(vm.fromAccountOptions[i].accountNo == $stateParams.fromAccount.accountNo) {
57 | vm.transferFormData.fromAccount = vm.fromAccountOptions[i];
58 | vm.disabledfromAccount = true;
59 | break;
60 | }
61 | }
62 | }
63 |
64 | });
65 | }
66 |
67 | function clearForm() {
68 | vm.transferFormData = getTransferFormDataObj();
69 | $scope.transferForm.$setPristine();
70 | $scope.transferForm.$setUntouched();
71 | }
72 |
73 | function submit(ev) {
74 | $mdDialog.show({
75 | controller: 'ReviewTransferDialogCtrl',
76 | controllerAs: 'vm',
77 | templateUrl: 'src/transfers/review-transfer-dialog/review-transfer-dialog.html',
78 | parent: angular.element(document.body),
79 | targetEvent: ev,
80 | locals: {transferFormData: vm.transferFormData},
81 | clickOutsideToClose: true
82 | }).then(function (result) {
83 | if(result === "success"){
84 | clearForm();
85 | }
86 | }, function () {
87 | clearForm();
88 | $mdToast.show(
89 | $mdToast.simple()
90 | .textContent('Transfer Cancelled')
91 | .position('top right')
92 | );
93 | });
94 | }
95 |
96 |
97 | }
98 | })();
--------------------------------------------------------------------------------
/app/src/loan-application/loan-application.component.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | 'use strict';
3 |
4 | angular.module('selfService')
5 | .controller('LoanApplicationCtrl', ['$scope', '$filter', '$mdToast', 'AccountService', 'LoanApplicationService', LoanApplicationCtrl]);
6 |
7 | /**
8 | * @module LoanApplicationCtrl
9 | * @description
10 | * Controls Application for Loan
11 | */
12 | function LoanApplicationCtrl($scope, $filter, $mdToast, AccountService, LoanApplicationService) {
13 | var vm = this;
14 |
15 | vm.form = {
16 | locale: 'en_GB',
17 | dateFormat: 'dd MMMM yyyy',
18 | loanType: 'individual'
19 | };
20 | vm.template = {};
21 | vm.clientId = null;
22 |
23 | vm.init = init;
24 | vm.getLoanTemplate = getLoanTemplate;
25 | vm.clearForm = clearForm;
26 | vm.submit = submit;
27 |
28 | init();
29 |
30 | function init() {
31 | AccountService.getClientId().then(function (clientId) {
32 | vm.clientId = clientId;
33 | getLoanTemplate(clientId, null);
34 | });
35 | }
36 |
37 | function getLoanTemplate(clientId, productId) {
38 | LoanApplicationService.template().get({
39 | templateType: 'individual',
40 | clientId: clientId,
41 | productId: productId
42 | }).$promise.then(function(template) {
43 | vm.template = template;
44 | vm.form.principal = vm.template.principal;
45 | vm.form.submittedOnDate = $filter('date','dd MMMM yyyy')(new Date(), 'dd MMMM yyyy');
46 | vm.form.expectedDisbursementDate = $filter('date')(new Date(), 'dd MMMM yyyy');
47 | });
48 | }
49 |
50 | function clearForm() {
51 | $scope.loanApplicationForm.$setPristine();
52 | $scope.loanApplicationForm.$setUntouched();
53 | vm.template = {};
54 | vm.form = {
55 | locale: 'en_GB',
56 | dateFormat: 'dd MMMM yyyy',
57 | loanType: 'individual'
58 | };
59 | init();
60 | }
61 |
62 | function submit() {
63 | var loanTemp = {
64 | clientId: vm.clientId,
65 | loanTermFrequency: vm.template.termFrequency,
66 | loanTermFrequencyType: vm.template.termPeriodFrequencyType.id,
67 | numberOfRepayments: vm.template.numberOfRepayments,
68 | repaymentEvery: vm.template.repaymentEvery,
69 | repaymentFrequencyType: vm.template.repaymentFrequencyType.id,
70 | interestRatePerPeriod: vm.template.interestRatePerPeriod,
71 | amortizationType: vm.template.amortizationType.id,
72 | interestType: vm.template.interestType.id,
73 | interestCalculationPeriodType: vm.template.interestCalculationPeriodType.id,
74 | transactionProcessingStrategyId: vm.template.transactionProcessingStrategyId
75 | };
76 | var data = Object.assign({}, loanTemp, vm.form);
77 | LoanApplicationService.loan().save(data).$promise.then(function() {
78 | clearForm();
79 | $mdToast.show(
80 | $mdToast.simple()
81 | .content("Loan Application Submitted Successfully")
82 | .hideDelay(2000)
83 | .position('top right')
84 | );
85 | }, function(){
86 | $mdToast.show(
87 | $mdToast.simple()
88 | .content("Error Creating Loan Application")
89 | .hideDelay(2000)
90 | .position('top right')
91 | );
92 | });
93 | }
94 | }
95 | })();
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | We are glad that you here to contribute to the Online Banking App. Now, First things first, before you start contributing please do the following things:
2 |
3 | 1. Setup the developer environment. For that, you can refer the [README.md](https://github.com/openMF/web-self-service-app/blob/develop/README.md) or you can follow this [video](https://mifosforge.jira.com/wiki/spaces/docs/pages/498794497/Developer+Environment+Setup+for+Online+Banking+App+2.0).
4 | 2. Sign our [Mifos CLA](http://mifos.org/about-us/financial-legal/mifos-contributor-agreement/).
5 |
6 | After you are done with the previous steps, please follow these guidelines:
7 |
8 | ## Submitting an issue
9 |
10 | - Before submitting an issue please search the issue tracker whether that issue is already present or not.
11 | - Follow the issue template while creating the issue
12 | - Please include screenshots.
13 | - In case of feature addition please give a detailed description of the feature so, that we could help you in getting that feature successfully accepted into the project.
14 | - For UI enhancements please include mockups and workflows.
15 |
16 | ## Getting assigned to an issue
17 | - If you would like to work on an issue. please inform in the issue ticket by commenting on it ( you can comment like this eg: I would like to work on this issue)
18 | - Please reproduce the issue before commenting on the ticket. If you are not able to reproduce the issue please ask for clarification by commenting or ask the issue creator.
19 | - If any other contributor is already working on the issue, please ask the previous contributor whether he/she is still working on the issue.
20 |
21 | ## Coding guidelines
22 | - Please run `npm run lint` ( Eslint check whether the code is in the right format or not )
23 | - Do not use inline statements for CSS changes.
24 |
25 | ## Submitting a Pull Request (PR)
26 | - If you are not at the develop branch them checkout to develop branch by
27 |
28 | ` git checkout develop`
29 |
30 | - Once, you are at develop branch then, before you start working on the fix or the feature , create a new branch using
31 |
32 | `git checkout -b `
33 |
34 | Branch name eg: Fix #1234 - Issue Description
35 | `
36 | - After you have done the changes, follows these steps to create a commit
37 | ` git add ` or ` git add -A `
38 |
39 | ` git commit -m""` ( commit message : Fix #IssueNo. - brief description to make everyone understand what you have done)
40 |
41 | ` git push origin `
42 |
43 | - If you have pushed the changes and want to do some changes to it after that
44 | 1. Go to the branch of the PR
45 | 2. Do the changes which you want to do.
46 | 3. Then `git add -A `
47 | 4. ` git commit --amend` ( You can also change the commit name here )
48 | 5. ` git push -f origin ` ( force push)
49 |
50 | - If you want to squash multiple commits then ( For example you want to squash last 2 commits on this branch to into one commit)
51 |
52 | `git rebase --interactive HEAD~2`
53 |
54 | `git push -f origin `
55 |
56 | - Update your branch from the repository
57 |
58 | `git add upstream https://github.com/openMF/web-self-service-app.git`
59 |
60 | `git pull --rebase upstream develop` ( this will fetch from upstream and will rebase the branch too).
61 |
62 | ## Communication Channels
63 | - [Gitter channel](https://gitter.im/openMF/web-self-service-app)
64 | - [Mailing list](https://lists.sourceforge.net/lists/listinfo/mifos-developer)
65 |
66 |
67 | ## Important Points for new contributors:
68 | - Registration feature for a new user is only available in develop branch (for now). You can use these credentials `username: self-service password: password`.
69 |
70 | - These features are only UI ( because of unavailability of API for now), please do not create new issue specifying not working of these features. You are invited to do any UI modification to them, but please first ask before creating any UI modification issue.
71 | 1. Applying for new share and savings products.
72 | 2. Reports
73 | 3. About Us
--------------------------------------------------------------------------------
/app/src/savings-application/savings-application.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ 'label.heading.applysavings' | translate }}
6 |
7 |
8 |
9 |
10 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/app/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Page Not Found :(
6 |
141 |
142 |
143 |
144 |
Not found :(
145 |
Sorry, but the page you were trying to view does not exist.
146 |
It looks like this was the result of either:
147 |
148 | a mistyped address
149 | an out-of-date link
150 |
151 |
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/app/src/recent-transactions/recent-transactions.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ 'label.heading.recentTransactions' | translate }}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | {{ 'label.msg.loadingRecentTransactions' | translate }}...
17 |
18 |
19 |
20 |
21 |
22 |
23 | {{ 'label.heading.id' | translate }}
24 | {{ 'label.heading.type' | translate }}
25 | {{ 'label.heading.officeName' | translate }}
26 | {{ 'label.heading.amount' | translate }}
27 | {{ 'label.heading.date' | translate }}
28 |
29 |
30 |
31 |
33 | {{ transaction.id }}
34 | {{ transaction.type.value }}
35 | {{ transaction.officeName}}
36 | {{ transaction.currency.displaySymbol + ' ' + transaction.amount}}
37 | {{ transaction.date | DateFormat }}
38 |
39 |
40 |
41 |
42 |
43 |
46 |
47 |
48 |
49 |
50 |
51 | {{ 'label.heading.recentTransactions' | translate }}
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
{{transaction.id}}
64 |
65 |
Type:
66 |
{{ transaction.type.value }}
67 |
68 |
69 |
Office Name:
70 |
{{ transaction.officeName}}
71 |
72 |
73 |
Amount:
74 |
{{ transaction.currency.displaySymbol + ' ' + transaction.amount}}
75 |
76 |
77 |
Date:
78 |
{{ transaction.date | DateFormat }}
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_table.scss:
--------------------------------------------------------------------------------
1 | // This file based on http://codepen.io/zavoloklom/pen/IGkDz
2 |
3 | // VARIABLES
4 | $table-header-font-weight: 400;
5 | $table-header-font-color: #757575;
6 |
7 | $table-cell-padding: 1.2rem;
8 |
9 | $table-bg: #fff;
10 | $table-bg-accent: #f5f5f5;
11 | $table-bg-hover: rgba(0,0,0,.12);
12 | $table-bg-active: $table-bg-hover;
13 | $table-border-color: #e0e0e0;
14 |
15 |
16 | // MIXINS
17 | @mixin transition($transition-property, $transition-time, $method) {
18 | -webkit-transition: $transition-property $transition-time $method;
19 | -moz-transition: $transition-property $transition-time $method;
20 | -ms-transition: $transition-property $transition-time $method;
21 | -o-transition: $transition-property $transition-time $method;
22 | transition: $transition-property $transition-time $method;
23 | }
24 |
25 |
26 | //TABLES
27 | .table {
28 | border-spacing: 0;
29 | width: 100%;
30 | max-width: 100%;
31 | margin-bottom: 2rem;
32 | background-color: $table-bg;
33 | > thead,
34 | > tbody,
35 | > tfoot {
36 | > tr {
37 | @include transition(all, 0.3s, ease);
38 | > th,
39 | > td {
40 | text-align: left;
41 | padding: $table-cell-padding;
42 | vertical-align: top;
43 | border-top: 0;
44 | @include transition(all, 0.3s, ease);
45 | }
46 | }
47 | }
48 | > thead > tr > th {
49 | font-weight: $table-header-font-weight;
50 | color: $table-header-font-color;
51 | vertical-align: bottom;
52 | border-bottom: 1px solid rgba(0,0,0,.12);
53 | }
54 | > caption + thead,
55 | > colgroup + thead,
56 | > thead:first-child {
57 | > tr:first-child {
58 | > th,
59 | > td {
60 | border-top: 0;
61 | }
62 | }
63 | }
64 | > tbody + tbody {
65 | border-top: 1px solid rgba(0,0,0,.12);
66 | }
67 |
68 | // Nesting
69 | .table {
70 | background-color: $table-bg;
71 | }
72 |
73 | // Remove border
74 | .no-border {
75 | border: 0;
76 | }
77 | }
78 |
79 | // Bordered version
80 | //
81 | // Add horizontal borders between columns.
82 | .table-bordered {
83 | border: 0;
84 | > thead,
85 | > tbody,
86 | > tfoot {
87 | > tr {
88 | > th,
89 | > td {
90 | border: 0;
91 | border-bottom: 1px solid $table-border-color;
92 | }
93 | }
94 | }
95 | > thead > tr {
96 | > th,
97 | > td {
98 | border-bottom-width: 2px;
99 | }
100 | }
101 | }
102 |
103 |
104 | // Hover effect
105 | //
106 | .table-hover {
107 | > tbody > tr:hover {
108 | > td,
109 | > th {
110 | background-color: $table-bg-hover;
111 | }
112 | }
113 | }
114 |
115 | // Responsive tables (vertical)
116 | //
117 | // Wrap your tables in `.table-responsive-vertical` and we'll make them mobile friendly
118 | // by vertical table-cell display. Only applies <768px. Everything above that will display normally.
119 | // For correct display you must add 'data-title' to each 'td'
120 | .table-responsive-vertical {
121 |
122 | @media screen and (max-width: 768px) {
123 |
124 | // Tighten up spacing
125 | > .table {
126 | margin-bottom: 0;
127 | background-color: transparent;
128 | > thead,
129 | > tfoot {
130 | display: none;
131 | }
132 |
133 | > tbody {
134 | display: block;
135 |
136 | > tr {
137 | display: block;
138 | border: 1px solid $table-border-color;
139 | border-radius: 2px;
140 | margin-bottom: $table-cell-padding;
141 |
142 | > td {
143 | background-color: $table-bg;
144 | display: block;
145 | vertical-align: middle;
146 | text-align: right;
147 | }
148 | > td[data-title]:before {
149 | content: attr(data-title);
150 | float: left;
151 | font-size: inherit;
152 | font-weight: $table-header-font-weight;
153 | color: $table-header-font-color;
154 | padding-right: 10px;
155 | }
156 | }
157 | }
158 | }
159 |
160 | // Special overrides for shadows
161 | &.shadow-z-1 {
162 | -webkit-box-shadow: none;
163 | -moz-box-shadow: none;
164 | box-shadow: none;
165 | > .table > tbody > tr {
166 | border: none;
167 | }
168 | }
169 |
170 | // Special overrides for the bordered tables
171 | > .table-bordered {
172 | border: 0;
173 |
174 | // Nuke the appropriate borders so that the parent can handle them
175 | > tbody {
176 | > tr {
177 | > td {
178 | border: 0;
179 | border-bottom: 1px solid $table-border-color;
180 | }
181 | > td:last-child {
182 | border-bottom: 0;
183 | }
184 | }
185 | }
186 | }
187 |
188 | // Special overrides for the striped tables
189 | > .table-striped {
190 | > tbody > tr > td,
191 | > tbody > tr:nth-child(odd) {
192 | background-color: $table-bg;
193 | }
194 | > tbody > tr > td:nth-child(odd) {
195 | background-color: $table-bg-accent;
196 | }
197 | }
198 |
199 | // Special overrides for hover tables
200 | > .table-hover {
201 | > tbody {
202 | > tr:hover > td,
203 | > tr:hover {
204 | background-color: $table-bg;
205 | }
206 | > tr > td:hover {
207 | background-color: $table-bg-hover;
208 | }
209 | }
210 | }
211 | }
212 | }
213 |
--------------------------------------------------------------------------------
/app/src/authentication/register/register.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/global-translations/locale-en.json:
--------------------------------------------------------------------------------
1 | {
2 | "login.heading.logintoyouraccount" : "Login to your account",
3 | "login.btn.login": "Login",
4 | "login.btn.forgot": "Forgot Password",
5 | "login.btn.register": "New User? Create an Account",
6 |
7 | "nav.msg.welcome": "Welcome,",
8 | "nav.label.dashboard": "Dashboard",
9 | "nav.label.accounts": "Accounts",
10 | "nav.label.recenttransactions": "Recent Transactions",
11 | "nav.label.charges": "Charges",
12 | "nav.label.transfers": "Transfers",
13 | "nav.label.tpttransfers": "Third Party Transfers",
14 | "nav.label.beneficiaries": "Beneficiaries",
15 | "nav.label.aboutus": "About us",
16 | "nav.label.help": "Help",
17 | "nav.label.applyloan": "Apply For Loan",
18 | "nav.label.reports": "Reports",
19 | "nav.label.applysavings": "Apply For Savings",
20 | "nav.label.applyshares": "Apply For Shares",
21 |
22 | "label.heading.loans": "Loans",
23 | "label.heading.loanAccountList": "Loan Account List",
24 | "label.heading.status": "Status",
25 | "label.heading.accountNo": "Account #",
26 | "label.heading.loanAccount": "Loan Account",
27 | "label.heading.originalLoan": "Original Loan",
28 | "label.heading.loanBalance": "Loan Balance",
29 | "label.heading.amountPaid": "Amount Paid",
30 | "label.heading.type": "Type",
31 | "label.heading.savings": "Savings",
32 | "label.heading.savingAccountList": "Savings Account List",
33 | "label.heading.account": "Account",
34 | "label.heading.accountType": "Account Type",
35 | "label.heading.accountBalance": "Account Balance",
36 | "label.heading.shares": "Shares",
37 | "label.heading.shareAccountList": "Shares Account List",
38 | "label.heading.approvedShares": "Approved Shares",
39 | "label.heading.pendingShares": "Shares Pending Approval",
40 | "label.heading.charges": "Charges",
41 | "label.heading.name": "Name",
42 | "label.heading.dueAsOf": "Due As Of",
43 | "label.heading.due": "Due",
44 | "label.heading.paid": "Paid",
45 | "label.heading.waived": "Waived",
46 | "label.heading.outstanding": "Outstanding",
47 | "label.heading.recentTransactions": "Recent Transactions",
48 | "label.heading.id": "Id",
49 | "label.heading.officeName": "Office Name",
50 | "label.heading.amount": "Amount",
51 | "label.heading.date": "Date",
52 | "label.heading.transfers": "Transfers",
53 | "label.heading.beneficiariesList": "Beneficiaries List",
54 | "label.heading.clientName": "Client Name",
55 | "label.heading.transferLimit": "Transfer Limit",
56 | "label.heading.addbeneficiaries": "Add Beneficiary",
57 | "label.heading.actions": "Actions",
58 | "label.heading.editbeneficiaries": "Edit Beneficiary",
59 | "label.heading.accountId": "Account Id",
60 | "label.heading.currency": "Currency",
61 | "label.heading.balance": "Balance",
62 | "label.heading.totalAccounts": "Total Accounts",
63 | "label.heading.savingsAccounts": "Savings Accounts",
64 | "label.heading.shareAccounts": "Share Accounts",
65 | "label.heading.totalSavings": "Total Savings",
66 | "label.heading.totalLoan": "Total Loan",
67 | "label.heading.loanAccountOverview": "Loan Account Overview",
68 | "label.heading.savingsAccountOverview": "Savings Account Overview",
69 | "label.heading.shareAccountOverview": "Share Account Overview",
70 | "label.heading.applyloan": "Apply For Loan",
71 | "label.heading.applysavings": "Apply For Savings",
72 | "label.heading.applyshares": "Apply For Shares",
73 | "label.heading.outstanding": "Outstanding Balance",
74 | "label.heading.accountId": "Account Id",
75 | "label.heading.currency": "Currency",
76 | "label.heading.tpt": "Third Party Transfers",
77 | "label.heading.transactionhistoryGraph": "Graph for transaction history",
78 | "label.heading.category": "Category",
79 | "label.headping.reports": "Reports",
80 | "label.heading.aboutUs": "About Us",
81 |
82 | "label.msg.loadingCharges": "Loading Charges",
83 | "label.msg.loadingRecentTransactions": "Loading Recent Transactions",
84 | "label.msg.loadingBeneficiaries": "Loading Beneficiaries",
85 | "label.msg.logginIn": "Logging In",
86 |
87 | "label.input.search": "Search",
88 | "label.input.payTo": "Pay To",
89 | "label.input.payFrom": "Pay From",
90 | "label.input.amount": "Amount",
91 | "label.input.transferDate": "Transfer Date",
92 | "label.input.remark": "Remark",
93 | "label.input.beneficiaryName": "Beneficiary Name",
94 | "label.input.officeName": "Office Name",
95 | "label.input.accountNumber": "Account Number",
96 | "label.input.transferLimit": "Transfer Limit",
97 | "label.input.accountType": "Account Type",
98 | "label.input.loanproductOptions": "Loan Product Options",
99 | "label.input.savingsproductOptions": "Savings Product Options",
100 | "label.input.sharesproductOptions": "Shares Product Options",
101 | "label.input.purposeOfLoan": "Purpose Of Loan",
102 | "label.input.currency": "Currency",
103 | "label.input.principal": "Principal",
104 | "label.input.submittedOn": "Submitted On",
105 | "label.input.expectedDisbursementDate": "Expected Disbursement Date",
106 | "label.input.accountno": "Account Number",
107 | "label.input.accountType" : "Account Type",
108 | "label.input.repaymentType": "Repayment Type",
109 | "label.input.transactionType": "Transaction Type",
110 | "label.input.numberOfShares": "Number of Shares",
111 | "label.input.todaysPrice": "Today's Price",
112 | "label.input.defaultSavingsAccount": "Default Savings Account",
113 | "label.input.applicationDate": "Application Date",
114 | "label.input.nominalAnnualInterest": "Nominal Annual Interest",
115 | "label.input.interestCompoundingPeriod": "Interest Compounding Period",
116 | "label.input.interestPostingPeriod": "Interest Posting Period",
117 | "label.input.interestCalculatedUsing": "Interest Calculated Using",
118 | "label.input.daysInYear": "Days In Year",
119 |
120 | "label.btn.cancel": "Cancel",
121 | "label.btn.reviewTransfer": "Review Transfer",
122 | "label.btn.reviewBeneficiary": "Review Beneficiary",
123 | "label.btn.editBeneficiary": "Edit Beneficiary",
124 | "label.btn.deposit": "Deposit",
125 | "label.btn.makepayment": "Make Payment",
126 | "label.btn.transfer": "Transfer",
127 | "label.btn.apply": "Apply"
128 | }
--------------------------------------------------------------------------------
/app/src/charges/charges.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ 'label.heading.charges' | translate }}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | {{ 'label.msg.loadingCharges' | translate }}...
17 |
18 |
19 |
20 |
21 |
22 |
23 | {{ 'label.heading.status' | translate }}
24 | {{ 'label.heading.name' | translate }}
25 | {{ 'label.heading.dueAsOf' | translate }}
26 | {{ 'label.heading.due' | translate }}
27 | {{ 'label.heading.paid' | translate }}
28 | {{ 'label.heading.waived' | translate }}
29 | {{ 'label.heading.outstanding' | translate }}
30 |
31 |
32 |
33 |
35 |
36 | {{charge.name}}
37 | {{charge.dueDate | DateFormat}}
38 | {{charge.currency.displaySymbol + ' ' + (charge.amount | number)}}
39 | {{charge.currency.displaySymbol + ' ' + (charge.amountPaid | number)}}
40 | {{charge.currency.displaySymbol + ' ' + (charge.amountWaived | number)}}
41 | {{charge.currency.displaySymbol + ' ' + (charge.amountOutstanding | number)}}
42 |
43 |
44 |
45 |
46 |
47 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
{{ 'label.heading.charges' | translate }}
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
{{charge.name}}
72 |
73 |
Due As of:
74 |
{{charge.dueDate | DateFormat}}
75 |
76 |
77 |
Due:
78 |
{{charge.currency.displaySymbol + ' ' + (charge.amount | number)}}
79 |
80 |
81 |
Paid:
82 |
{{charge.currency.displaySymbol + ' ' + (charge.amountPaid | number)}}
83 |
84 |
85 |
Waived:
86 |
{{charge.currency.displaySymbol + ' ' + (charge.amountWaived | number)}}
87 |
88 |
89 |
Outstanding:
90 |
{{charge.currency.displaySymbol + ' ' + (charge.amountOutstanding | number)}}
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
106 |
107 |
--------------------------------------------------------------------------------
/app/src/dashboard/dashboard.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ 'label.heading.totalAccounts' | translate }}
7 |
8 |
9 |
10 |
11 | {{ vm.dashboardData.totalAccounts}}
12 |
13 |
14 |
15 |
16 |
17 | {{ 'label.heading.loanAccount' | translate }}
18 |
19 |
20 |
21 |
22 | {{ vm.dashboardData.loanAccounts.length}}
23 |
24 |
25 |
26 |
27 |
28 | {{ 'label.heading.savingsAccounts' | translate }}
29 |
30 |
31 |
32 |
33 | {{ vm.dashboardData.savingsAccounts.length}}
34 |
35 |
36 |
37 |
38 |
39 | {{ 'label.heading.shareAccounts' | translate }}
40 |
41 |
42 |
43 |
44 | {{ vm.dashboardData.shareAccounts.length}}
45 |
46 |
47 |
48 |
49 |
50 | {{ 'label.heading.totalAccounts' | translate }}
51 | {{ vm.dashboardData.totalSavings }}
52 |
53 |
54 | {{ 'label.heading.totalLoan' | translate }}
55 | {{ vm.dashboardData.totalLoan }}
56 |
57 |
58 |
59 |
60 |
61 | {{ 'label.heading.loanAccountOverview' | translate }}
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | {{ 'label.heading.savingsAccountOverview' | translate }}
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | {{ 'label.heading.shareAccountOverview' | translate }}
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | {{'label.heading.transactionhistoryGraph' | translate}}
92 |
93 |
94 |
95 |
125 |
126 |
127 | {{vm.accountType}}
128 |
129 |
130 |
131 | Sorry, Graphs for Shares are not available now...
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/app/src/beneficiaries/beneficiaries-list/beneficiaries-list.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ 'label.heading.beneficiariesList' | translate }}
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | {{ 'label.msg.loadingBeneficiaries' | translate }}...
18 |
19 |
20 |
21 |
22 |
23 |
24 | {{ 'label.heading.id' | translate }}
25 | {{ 'label.heading.accountNo' | translate }}
26 | {{ 'label.heading.accountType' | translate }}
27 | {{ 'label.heading.transferLimit' | translate }}
28 | {{ 'label.heading.name' | translate }}
29 | {{ 'label.heading.officeName' | translate }}
30 | {{ 'label.heading.clientName' | translate }}
31 | {{ 'label.heading.actions' | translate }}
32 |
33 |
34 |
35 |
37 | {{ beneficiary.id }}
38 | {{ beneficiary.accountNumber }}
39 | {{ beneficiary.accountType.value }}
40 | {{ beneficiary.transferLimit }}
41 | {{ beneficiary.name }}
42 | {{ beneficiary.officeName }}
43 | {{ beneficiary.clientName }}
44 |
45 |
46 | edit
47 |
48 |
49 | delete
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
{{ 'label.heading.beneficiariesList' | translate }}
67 |
68 |
69 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
{{ beneficiary.id }}
79 |
80 |
Account#:
81 |
{{ beneficiary.accountNumber }}
82 |
83 |
84 |
Account Type:
85 |
{{ beneficiary.accountType.value }}
86 |
87 |
88 |
Transfer Limit:
89 |
{{ beneficiary.transferLimit }}
90 |
91 |
92 |
Name:
93 |
{{ beneficiary.name }}
94 |
95 |
96 |
Office Name:
97 |
{{ beneficiary.officeName }}
98 |
99 |
100 |
Client Name:
101 |
{{ beneficiary.clientName }}
102 |
103 |
104 |
105 |
106 | edit
107 |
108 |
109 | delete
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
125 |
126 |
127 |
128 |
129 |
130 | add
131 |
132 |
--------------------------------------------------------------------------------
/app/src/common/main.html:
--------------------------------------------------------------------------------
1 |
2 |
11 |
107 |
108 |
109 |
110 |
111 |
112 | menu
113 |
114 |
115 |
116 | {{vm.userDetails.username}}
117 |
118 |
119 |
120 |
121 |
122 |
123 |
126 |
127 |
128 |
129 |
130 |
133 |
134 |
135 |
136 |
137 |
138 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
--------------------------------------------------------------------------------