- Started using TypeScript

- Using SystemJS as Module Loader
 - Auth and Permissions moved to Credentials.service from $rootScope
 - Toasts moved to Messages.service
 - Massive Changes
 - Sprint 1 done to move to Angular.io from AngularJS
 - Should be fully working!! :)
This commit is contained in:
tanshu
2018-05-13 00:18:12 +05:30
parent d05625ba39
commit f3c1bfa57b
342 changed files with 6810 additions and 10313 deletions

4
.gitignore vendored
View File

@ -5,3 +5,7 @@ env
*/__pycache__/
.idea/
*.egg-info/
brewman/static/node_modules
brewman/static/app/**/*.js
brewman/static/app/**/*.map
brewman/static/package-lock.json

View File

@ -13,6 +13,7 @@ def includeme(config):
config.add_static_view('partial', 'brewman:static/partial', cache_max_age=get_age(10))
config.add_static_view('template', 'brewman:static/template', cache_max_age=get_age(10))
config.add_static_view('app', 'brewman:static/app', cache_max_age=get_age(10))
config.add_static_view('node_modules', 'brewman:static/node_modules', cache_max_age=get_age(10))
config.add_route('api_dashboard', '/api/Dashboard')
config.add_route('dashboard', '/Dashboard')
@ -23,6 +24,8 @@ def includeme(config):
config.add_route('logout', '/logout')
config.add_route('home', '/')
config.add_route('tsconfig', '/tsconfig.json')
config.add_route('systemjs', '/systemjs.config.js')
config.add_route('api_account_type_list', '/api/AccountTypes')

View File

@ -5,34 +5,34 @@
<label for="txtCode" class="col-md-2 control-label">Code</label>
<div class="col-md-10">
<input type="text" id="txtCode" class="form-control" disabled="disabled" ng-model="account.Code"/>
<input type="text" id="txtCode" class="form-control" disabled="disabled" ng-model="vm.account.Code"/>
</div>
</div>
<div class="form-group">
<label for="txtName" class="col-md-2 control-label">Name</label>
<div class="col-md-10">
<input type="text" id="txtName" class="form-control" ng-model="account.Name" focus-on="foName"/>
<input type="text" id="txtName" class="form-control" ng-model="vm.account.Name" focus-on="vm.foName"/>
</div>
</div>
<div class="form-group">
<label for="ddlType" class="col-md-2 control-label">Type</label>
<div class="col-md-10">
<select id="ddlType" class="form-control" ng-model="account.Type"
ng-options="l.AccountTypeID as l.Name for l in accountTypes"> </select>
<select id="ddlType" class="form-control" ng-model="vm.account.Type"
ng-options="l.AccountTypeID as l.Name for l in vm.accountTypes"> </select>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-5">
<label class="checkbox-inline">
<input type="checkbox" ng-model="account.IsActive"> Is Active
<input type="checkbox" ng-model="vm.account.IsActive"> Is Active
</label>
</div>
<div class="col-md-5">
<label class="checkbox-inline">
<input type="checkbox" ng-model="account.IsReconcilable"> Is Reconcilable
<input type="checkbox" ng-model="vm.account.IsReconcilable"> Is Reconcilable
</label>
</div>
</div>
@ -40,15 +40,15 @@
<label for="ddlCostCentre" class="col-md-2 control-label">Cost Centre</label>
<div class="col-md-10">
<select id="ddlCostCentre" class="form-control" ng-model="account.CostCentre.CostCentreID"
ng-options="l.CostCentreID as l.Name for l in costCentres"> </select>
<select id="ddlCostCentre" class="form-control" ng-model="vm.account.CostCentre.CostCentreID"
ng-options="l.CostCentreID as l.Name for l in vm.costCentres"> </select>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button class="btn btn-primary" ng-click="save()">Save</button>
<button class="btn btn-danger" ng-show="account.LedgerID" ng-click="confirm()">Delete</button>
<button class="btn btn-primary" ng-click="vm.save()">Save</button>
<button class="btn btn-danger" ng-show="vm.account.LedgerID" ng-click="vm.confirm()">Delete</button>
</div>
</div>
</form>

View File

@ -0,0 +1,7 @@
import {AccountListController} from './account-list.controller';
export const AccountListComponent = {
templateUrl: '/app/account/account-list.html',
controller: AccountListController,
controllerAs: 'vm'
};

View File

@ -1,80 +0,0 @@
angular
.module('overlord')
.controller('AccountListController', AccountListController);
AccountListController.$inject = ['$scope', '$location', '$routeParams', 'Tokenizer', 'accounts'];
function AccountListController($scope, $location, $routeParams, Tokenizer, accounts) {
$scope.search = $routeParams.q || '';
$scope.info = accounts;
$scope.$watch('search', function (value) {
$scope.filterAccounts(value);
}, true);
$scope.$on('$destroy', function () {
Tokenizer.doFilter.cache = {};
});
$scope.searchInfo = {
comparator: {
'n': {'Col': 'Name', 'Comparator': 'text'},
't': {'Col': 'Type', 'Comparator': 'text'},
'a': {'Col': 'IsActive', 'Comparator': 'boolean'},
'r': {'Col': 'IsReconcilable', 'Comparator': 'boolean'},
'c': {'Col': 'CostCentre', 'Comparator': 'text'}
},
def: 'n',
sorter: {
'n': 'Name',
't': 'Type',
'a': 'IsActive',
'r': 'IsReconcilable',
'c': 'CostCentre'
}
};
$scope.filterAccounts = _.debounce(function (q) {
if (q !== $scope._search) {
$scope._search = q;
if (angular.isUndefined(q) || q === '') {
$location.path('/Accounts').search('q', null).replace();
} else {
$location.path('/Accounts').search({'q': q}).replace();
}
$scope.$apply(function () {
var matches = Tokenizer.parseFilterString(q, $scope.searchInfo);
$scope.accounts = Tokenizer.doFilter(q, $scope.info, matches);
});
}
}, 350);
$scope.selected = -1;
$scope.setSelected = function (index) {
$scope.selected = Math.min(Math.max(0, index), $scope.accounts.length - 1);
};
$scope.shortcuts = {
'up': function (e) {
if ($scope.selected > 0) {
$scope.$apply(function () {
$scope.selected = Math.min(Math.max(0, $scope.selected - 1), $scope.accounts.length - 1);
});
$("#" + $scope.selected).scrollintoview();
e.preventDefault();
}
},
'down': function (e) {
if ($scope.selected < $scope.accounts.length - 1) {
$scope.$apply(function () {
$scope.selected = Math.min(Math.max(0, $scope.selected + 1), $scope.accounts.length - 1);
});
$("#" + $scope.selected).scrollintoview();
e.preventDefault();
}
}
};
};
AccountListResolver.$inject = ['Account'];
function AccountListResolver(Account) {
return Account.query({}).$promise;
}

View File

@ -0,0 +1,87 @@
import * as angular from 'angular';
import * as _ from 'lodash';
import * as $ from 'jquery';
import 'jqScrollIntoView';
export class AccountListController {
static $inject = ['$scope', '$location', '$routeParams', 'Tokenizer'];
search: any;
info: any;
searchInfo: any;
filterAccounts: any;
selected: any;
shortcuts: any;
accounts: any;
constructor(public $scope, public $location, public $routeParams, public Tokenizer) {
this.accounts = $scope.$parent.res.accounts;
this.search = $routeParams.q || '';
this.info = this.accounts;
$scope.$watch('vm.search', (value) => {
this.filterAccounts(value);
}, true);
$scope.$on('$destroy', () => {
this.Tokenizer.doFilter.cache = {};
});
this.searchInfo = {
comparator: {
'n': {'Col': 'Name', 'Comparator': 'text'},
't': {'Col': 'Type', 'Comparator': 'text'},
'a': {'Col': 'IsActive', 'Comparator': 'boolean'},
'r': {'Col': 'IsReconcilable', 'Comparator': 'boolean'},
'c': {'Col': 'CostCentre', 'Comparator': 'text'}
},
def: 'n',
sorter: {
'n': 'Name',
't': 'Type',
'a': 'IsActive',
'r': 'IsReconcilable',
'c': 'CostCentre'
}
};
this.filterAccounts = _.debounce((q) => {
if (q !== $scope._search) {
$scope._search = q;
if (angular.isUndefined(q) || q === '') {
this.$location.path('/Accounts').search('q', null).replace();
} else {
this.$location.path('/Accounts').search({'q': q}).replace();
}
$scope.$apply(() => {
let matches = Tokenizer.parseFilterString(q, this.searchInfo);
this.accounts = Tokenizer.doFilter(q, this.info, matches);
});
}
}, 350);
this.selected = -1;
this.shortcuts = {
'up': (e) => {
if (this.selected > 0) {
this.$scope.$apply(() => {
this.selected = Math.min(Math.max(0, this.selected - 1), this.accounts.length - 1);
});
$("#" + this.selected).scrollintoview();
e.preventDefault();
}
},
'down': (e) => {
if (this.selected < this.accounts.length - 1) {
this.$scope.$apply(() => {
this.selected = Math.min(Math.max(0, this.selected + 1), this.accounts.length - 1);
});
$("#" + this.selected).scrollintoview();
e.preventDefault();
}
}
};
}
setSelected(index) {
this.selected = Math.min(Math.max(0, index), this.accounts.length - 1);
}
}

View File

@ -3,7 +3,7 @@
<div class="col-md-10">
<input type="text" class="form-control"
placeholder="Search: n:Name, a:Active, u:Units, g:Group, e:true for extended properties, &quot; or ' for Quotes"
ng-model="search">
ng-model="vm.search">
</div>
<div class="col-md-2">
<a href="/Account" class="btn btn-success btn-block">Add <i
@ -11,7 +11,7 @@
</div>
</div>
</h2>
<table class="table table-condensed table-bordered table-striped" keypress="shortcuts">
<table class="table table-condensed table-bordered table-striped" keypress="vm.shortcuts">
<thead>
<tr>
<th>Name</th>
@ -22,8 +22,8 @@
</tr>
</thead>
<tbody>
<tr id="{{$index}}" ng-repeat="item in accounts" ng-class="{warning:$index==selected}"
ng-click="setSelected($index)">
<tr id="{{$index}}" ng-repeat="item in vm.accounts" ng-class="{warning:$index==vm.selected}"
ng-click="vm.setSelected($index)">
<td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td>{{item.Type}}</td>
<td>{{item.IsActive}}</td>

View File

@ -0,0 +1,3 @@
export function AccountListResolver(Account) {
return Account.query({}).$promise;
}

View File

@ -0,0 +1,3 @@
export function AccountType($resource) {
return $resource('/api/AccountTypes');
}

View File

@ -0,0 +1,4 @@
export function AccountTypesResolver(AccountType) {
return AccountType.query({}).$promise;
}

View File

@ -0,0 +1,7 @@
import {AccountController} from './account.controller';
export const AccountComponent = {
templateUrl: '/app/account/account-detail.html',
controller: AccountController,
controllerAs: 'vm'
};

View File

@ -1,64 +0,0 @@
angular
.module('overlord')
.controller('AccountController', AccountController);
AccountController.$inject = ['$scope', '$location', '$uibModal', 'account', 'accountTypes', 'costCentres'];
function AccountController($scope, $location, $modal, account, accountTypes, costCentres) {
$scope.account = account;
$scope.accountTypes = accountTypes;
$scope.costCentres = costCentres;
$scope.save = function () {
$scope.account.$save(function () {
$scope.toasts.push({Type: 'Success', Message: ''});
$location.path('/Accounts');
}, function (data) {
$scope.toasts.push({Type: 'Danger', Message: data.data});
});
};
$scope.delete = function () {
$scope.account.$delete(function () {
$scope.toasts.push({Type: 'Success', Message: ''});
$location.path('/Accounts');
}, function (data) {
$scope.toasts.push({Type: 'Danger', Message: data.data});
});
};
$scope.confirm = function () {
var modalInstance = $modal.open({
backdrop: true,
templateUrl: '/template/modal/confirm.html',
controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) {
$scope.title = "Delete Account";
$scope.body = "Are you sure? This cannot be undone.";
$scope.isDelete = true;
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}]
});
modalInstance.result.then(function () {
$scope.delete();
});
};
$scope.foName = true;
};
AccountController.resolve = {
account: ['$route', 'Account', function ($route, Account) {
var id = $route.current.params.id;
return Account.get({id: id}).$promise;
}],
accountTypes: ['AccountType', function (AccountType) {
return AccountType.query({}).$promise;
}],
costCentres: ['CostCentre', function (CostCentre) {
return CostCentre.query({}).$promise;
}]
};

View File

@ -0,0 +1,61 @@
export class AccountController {
static $inject = ['$scope', '$location', '$uibModal', 'Messages'];
foName: any;
account: any;
accountTypes: any;
costCentres: any;
constructor(public $scope, public $location, public $modal, public Messages) {
this.account = $scope.$parent.res.account;
this.accountTypes = $scope.$parent.res.accountTypes;
this.costCentres = $scope.$parent.res.costCentres;
this.foName = true;
}
save() {
this.account.$save(() => {
this.Messages.push({Type: 'Success', Message: ''});
this.$location.path('/Accounts');
}, (data) => {
this.Messages.push({Type: 'Danger', Message: data.data});
});
}
delete() {
this.account.$delete(() => {
this.Messages.push({Type: 'Success', Message: ''});
this.$location.path('/Accounts');
}, (data) => {
this.Messages.push({Type: 'Danger', Message: data.data});
});
}
confirm() {
let modalInstance = this.$modal.open({
backdrop: true,
templateUrl: '/template/modal/confirm.html',
controller: ['$uibModalInstance', class {
title: any;
body: any;
isDelete: boolean;
constructor(public $modalInstance) {
this.title = "Delete Account";
this.body = "Are you sure? This cannot be undone.";
this.isDelete = true;
}
ok() {
this.$modalInstance.close();
}
cancel() {
this.$modalInstance.dismiss('cancel');
}
}]
});
modalInstance.result.then(() => {
this.delete();
});
}
}

View File

@ -0,0 +1,4 @@
export function AccountResolver($route, Account) {
const id = $route.current.params.id;
return Account.get({id: id}).$promise;
}

View File

@ -0,0 +1,8 @@
export function Account($resource) {
return $resource('/api/Account/:id',
{id: '@LedgerID'}, {
query: {method: 'GET', params: {list: true}, isArray: true},
autocomplete: {method: 'GET', params: {term: ''}, isArray: true},
balance: {method: 'GET', params: {b: true, d: ''}}
});
}

View File

@ -0,0 +1,3 @@
export function PaymentAccountsResolver(Account) {
return Account.autocomplete({term: '', type: 1}).$promise;
}

View File

@ -0,0 +1,3 @@
export function ReceiptAccountsResolver(Account) {
return Account.autocomplete({term: '', type: 1}).$promise;
}

View File

@ -0,0 +1,10 @@
import * as angular from 'angular';
export function AttendanceInfoResolver($route, Attendance) {
const date = $route.current.params.date;
if (angular.isUndefined(date)) {
return Attendance.get({}).$promise;
} else {
return Attendance.get({date: date}).$promise;
}
}

View File

@ -1,29 +0,0 @@
angular
.module('overlord')
.controller('AttendanceSubController', AttendanceSubController);
AttendanceSubController.$inject = ['$scope'];
function AttendanceSubController($scope) {
$scope.original = {};
angular.copy($scope.item, $scope.original);
$scope.isLabel = function () {
return true;
};
$scope.isError = function () {
return $scope.item.Worked === 'Error';
};
$scope.isGood = function () {
return $scope.item.Worked === true;
};
$scope.isBad = function () {
return $scope.item.Worked === false;
};
$scope.isDirty = function () {
return !angular.equals($scope.original, $scope.item);
};
}

View File

@ -0,0 +1,35 @@
import * as angular from 'angular';
export class AttendanceSubController {
static $inject = ['$scope'];
item: any;
original: any;
attendanceTypes: any;
constructor(public $scope) {
this.attendanceTypes = $scope.attendanceTypes;
this.item = $scope.item;
this.original = {};
angular.copy(this.item, this.original);
}
isLabel() {
return true;
}
isError() {
return this.item.Worked === 'Error';
}
isGood() {
return this.item.Worked === true;
}
isBad() {
return this.item.Worked === false;
}
isDirty() {
return !angular.equals(this.original, this.item);
}
}

View File

@ -0,0 +1,14 @@
import {AttendanceSubController} from './attendance-sub.controller';
export function AttendanceSubDirective() {
return {
scope: {
item: '=attendanceSub',
attendanceTypes: '=attendanceTypes'
},
restrict: 'A',
templateUrl: '/app/attendance/attendance-sub.html',
controller: AttendanceSubController,
controllerAs: 'vmSub',
};
}

View File

@ -0,0 +1,12 @@
<td class="text-right">{{item.Code}}</td>
<td><i class="glyphicon glyphicon-leaf" ng-show="vmSub.isDirty()"></i> {{item.Name}}</td>
<td>{{item.Designation}}</td>
<td>{{item.Department}}</td>
<td>
<select class="form-control" ng-model="item.AttendanceTypeID"
ng-options="i.AttendanceTypeID as i.Name for i in vmSub.attendanceTypes"></select>
</td>
<td class="no-bg">{{item.Prints}}
<span ng-show="item.Hours.length > 0"
ng-class="{'label': vmSub.isLabel(), 'label-success': vmSub.isGood(), 'label-warning': vmSub.isBad(), 'label-important': vmSub.isError()}">{{item.Hours}}</span>
</td>

View File

@ -0,0 +1,3 @@
export function AttendanceTypesResolver(AttendanceTypes) {
return AttendanceTypes.query({}).$promise;
}

View File

@ -0,0 +1,3 @@
export function AttendanceTypes($resource) {
return $resource('/api/AttendanceTypes');
}

View File

@ -0,0 +1,7 @@
import {AttendanceController} from './attendance.controller';
export const AttendanceComponent = {
templateUrl: '/app/attendance/attendance.html',
controller: AttendanceController,
controllerAs: 'vm',
};

View File

@ -1,42 +0,0 @@
angular
.module('overlord')
.controller('AttendanceController', AttendanceController);
AttendanceController.$inject = ['$scope', '$location', 'asDateFilter', 'Attendance', 'attendanceTypes', 'info', 'uibDateParser'];
function AttendanceController($scope, $location, asDate, Attendance, attendanceTypes, info, dateParser) {
var _info_Date = dateParser.parse(info.Date, "dd-MMM-yyyy");
$scope.info_Date = function (value) {
if (arguments.length) {
$scope.info.Date = asDate(value);
_info_Date = value;
}
return _info_Date;
};
$scope.attendanceTypes = attendanceTypes;
$scope.info = info;
$scope.show = function () {
$location.path('/Attendance/' + $scope.info.Date);
};
$scope.save = function () {
return $scope.info.$save(function (u) {
$scope.toasts.push({Type: 'Success', Message: u.Code});
}, function (data) {
$scope.toasts.push({Type: 'Danger', Message: data.data});
});
};
$scope.foDate = true;
}
tendanceController.resolve = {
info: ['$route', 'Attendance', function ($route, Attendance) {
var date = $route.current.params.date;
if (angular.isUndefined(date)) {
return Attendance.get({}).$promise;
} else {
return Attendance.get({date: date}).$promise;
}
}],
attendanceTypes: ['AttendanceTypes', function (AttendanceTypes) {
return AttendanceTypes.query({}).$promise;
}]
};

View File

@ -0,0 +1,34 @@
export class AttendanceController {
static $inject = ['$scope', '$location', 'asDateFilter', 'Attendance', 'uibDateParser', 'Messages'];
_info_Date: any;
foDate: boolean;
attendanceTypes: any;
info: any;
constructor(public $scope, public $location, public asDate, public Attendance, public dateParser, public Messages) {
this.attendanceTypes = $scope.$parent.res.attendanceTypes;
this.info = $scope.$parent.res.info;
this._info_Date = dateParser.parse(this.info.Date, "dd-MMM-yyyy");
this.foDate = true;
}
info_Date(value) {
if (arguments.length) {
this.info.Date = this.asDate(value);
this._info_Date = value;
}
return this._info_Date;
}
show() {
this.$location.path('/Attendance/' + this.info.Date);
}
save() {
return this.info.$save((u) => {
this.Messages.push({Type: 'Success', Message: u.Code});
}, (data) => {
this.Messages.push({Type: 'Danger', Message: data.data});
});
}
}

View File

@ -6,9 +6,9 @@
<div class="col-md-8">
<div class="input-group">
<input class="form-control" id="txtDate" type="text" uib-datepicker-popup="dd-MMM-yyyy" is-open="dOpen"
ng-focus="dOpen = true" ng-model="info_Date" ng-model-options="{getterSetter: true}"
focus-on="foDate"/>
<input class="form-control" id="txtDate" type="text" uib-datepicker-popup="dd-MMM-yyyy" is-open="vm.dOpen"
ng-focus="vm.dOpen = true" ng-model="vm.info_Date" ng-model-options="{getterSetter: true}"
focus-on="vm.foDate"/>
<span class="input-group-btn">
<button class="btn btn-default"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
@ -16,7 +16,7 @@
</div>
<div class="col-md-2">
<button class="btn btn-info" ng-click="show()">Show <i class="glyphicon glyphicon-eye-open"></i></button>
<button class="btn btn-info" ng-click="vm.show()">Show <i class="glyphicon glyphicon-eye-open"></i></button>
</div>
</div>
<table id="gvGrid" class="table table-condensed table-bordered table-striped">
@ -31,27 +31,14 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="item in info.Body"
ng-class="{0:'', 1:'Present', 2:'Off', 3:'Leave', 4:'Absent', 5:'HalfDay', 6:'Double', 7:'PaidLeaveAvailed', 8:'CasualLeaveAvailed', 9:'COff', 10:'HalfPL', 11:'HalfCL'}[item.AttendanceTypeID]"
ng-controller="AttendanceSubController">
<td class="text-right">{{item.Code}}</td>
<td><i class="glyphicon glyphicon-leaf" ng-show="isDirty()"></i> {{item.Name}}</td>
<td>{{item.Designation}}</td>
<td>{{item.Department}}</td>
<td>
<select class="form-control" ng-model="item.AttendanceTypeID"
ng-options="i.AttendanceTypeID as i.Name for i in attendanceTypes"></select>
</td>
<td class="no-bg">{{item.Prints}}
<span ng-show="item.Hours.length > 0"
ng-class="{'label': isLabel(), 'label-success': isGood(), 'label-warning': isBad(), 'label-important': isError()}">{{item.Hours}}</span>
</td>
<tr attendance-sub="item" ng-repeat="item in vm.info.Body" attendance-types="vm.attendanceTypes"
ng-class="{0:'', 1:'Present', 2:'Off', 3:'Leave', 4:'Absent', 5:'HalfDay', 6:'Double', 7:'PaidLeaveAvailed', 8:'CasualLeaveAvailed', 9:'COff', 10:'HalfPL', 11:'HalfCL'}[item.AttendanceTypeID]">
</tr>
</tbody>
</table>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button tan-click="save()" ng-disabled="isClean() || frmForm.$invalid" class="btn btn-primary">Save</button>
<button tan-click="vm.save()" ng-disabled="vm.isClean() || frmForm.$invalid" class="btn btn-primary">Save</button>
</div>
</div>
</form>

View File

@ -0,0 +1,3 @@
export function Attendance($resource) {
return $resource('/api/Attendance/:date', {date: '@Date'});
}

View File

@ -0,0 +1,7 @@
import {BalanceSheetController} from './balance-sheet.controller';
export const BalanceSheetComponent = {
templateUrl: '/app/balance-sheet/balance-sheet.html',
controller: BalanceSheetController,
controllerAs: 'vm'
};

View File

@ -1,32 +0,0 @@
angular
.module('overlord')
.controller('BalanceSheetController', BalanceSheetController);
BalanceSheetController.$inject = ['$scope', '$location', 'asDateFilter', 'info', 'uibDateParser'];
function BalanceSheetController($scope, $location, asDate, info, dateParser) {
var _info_Date = dateParser.parse(info.Date, "dd-MMM-yyyy");
$scope.info_Date = function (value) {
if (arguments.length) {
$scope.info.Date = asDate(value);
_info_Date = value;
}
return _info_Date;
};
$scope.info = info;
$scope.show = function () {
$location.path('/BalanceSheet/' + $scope.info.Date);
};
$scope.foDate = true;
}
BalanceSheetController.resolve = {
info: ['$route', 'BalanceSheet', function ($route, BalanceSheet) {
var date = $route.current.params.date;
if (angular.isUndefined(date)) {
return BalanceSheet.get({}).$promise;
} else {
return BalanceSheet.get({date: date}).$promise;
}
}]
};

View File

@ -0,0 +1,24 @@
export class BalanceSheetController {
static $inject = ['$scope', '$location', 'asDateFilter', 'uibDateParser'];
_info_Date: any;
foDate: boolean;
info: any;
constructor(public $scope, public $location, public asDate, public dateParser) {
this.info = $scope.$parent.res.info;
this._info_Date = dateParser.parse(this.info.Date, "dd-MMM-yyyy");
this.foDate = true;
}
info_Date(value) {
if (arguments.length) {
this.info.Date = this.asDate(value);
this._info_Date = value;
}
return this._info_Date;
}
show() {
this.$location.path('/BalanceSheet/' + this.info.Date);
}
}

View File

@ -7,7 +7,7 @@
<div class="col-md-8">
<div class="input-group">
<input type="text" class="form-control" id="txtDate" uib-datepicker-popup="dd-MMM-yyyy"
is-open="dOpen" ng-focus="dOpen = true" ng-model="info_Date" focus-on="foDate"
is-open="vm.dOpen" ng-focus="vm.dOpen = true" ng-model="vm.info_Date" focus-on="vm.foDate"
ng-model-options="{getterSetter: true}"/>
<span class="input-group-btn">
<button class="btn btn-default"><i class="glyphicon glyphicon-calendar"></i></button>
@ -15,7 +15,7 @@
</div>
</div>
<div class="col-md-2">
<button class="btn btn-info" ng-click="show()">Show <i class="glyphicon glyphicon-eye-open"></i></button>
<button class="btn btn-info" ng-click="vm.show()">Show <i class="glyphicon glyphicon-eye-open"></i></button>
</div>
</div>
@ -29,7 +29,7 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="item in info.Body">
<tr ng-repeat="item in vm.info.Body">
<td>{{item.Group}}</td>
<td>{{item.Name}}</td>
<td class="text-right">{{item.SubAmount | currency | clr}}</td>
@ -37,7 +37,7 @@
</tr>
</tbody>
<tfoot>
<tr ng-repeat="item in info.Footer">
<tr ng-repeat="item in vm.info.Footer">
<td><strong>{{item.Group}}</strong></td>
<td>{{item.Name}}</td>
<td class="text-right">{{item.SubAmount | currency | clr}}</td>

View File

@ -0,0 +1,11 @@
import * as angular from 'angular';
export function BalanceSheetResolver($route, BalanceSheet) {
const date = $route.current.params.date;
if (angular.isUndefined(date)) {
return BalanceSheet.get({}).$promise;
} else {
return BalanceSheet.get({date: date}).$promise;
}
}

View File

@ -0,0 +1,3 @@
export function BalanceSheet($resource) {
return $resource('/api/BalanceSheet/:date');
}

View File

@ -0,0 +1,32 @@
import * as angular from 'angular';
export class BaseController {
static $inject = ['$rootScope', 'Auth', '$location', '$routeParams', 'Messages', 'Credentials'];
constructor(public $rootScope, public Auth, public $location, public $routeParams, public Messages, public Credentials) {
$rootScope.$on('loginRequired', () => {
if (this.Credentials.Auth.isAuthenticated) {
this.$location.path('/');
} else {
var came_from = this.$routeParams.came_from;
if (angular.isUndefined(came_from) && $location.path() !== '/login') {
came_from = $location.url();
}
this.$location.path('/login').search({came_from: came_from});
}
});
$rootScope.$on("$routeChangeStart", (event, next, current) => {
this.Auth.get((u, putResponseHeaders) => {
this.Credentials.Auth = u;
this.Credentials.Perms = u.perms;
});
});
}
clearToast(item) {
var idx = this.Messages.indexOf(item);
if (idx !== -1) {
this.Messages.splice(idx, 1);
}
}
}

View File

@ -0,0 +1,7 @@
import {CashFlowController} from './cash-flow.controller';
export const CashFlowComponent = {
templateUrl: '/app/cash-flow/cash-flow.html',
controller: CashFlowController,
controllerAs: 'vm',
};

View File

@ -1,49 +0,0 @@
angular
.module('overlord')
.controller('CashFlowController', CashFlowController);
CashFlowController.$inject = ['$scope', '$routeParams', '$location', 'asDateFilter', 'cashFlow', 'uibDateParser'];
function CashFlowController($scope, $routeParams, $location, asDate, cashFlow, dateParser) {
var _info_StartDate = dateParser.parse(cashFlow.StartDate, "dd-MMM-yyyy"),
_info_FinishDate = dateParser.parse(cashFlow.FinishDate, "dd-MMM-yyyy");
$scope.info_StartDate = function (value) {
if (arguments.length) {
$scope.info.StartDate = asDate(value);
_info_StartDate = value;
}
return _info_StartDate;
};
$scope.info_FinishDate = function (value) {
if (arguments.length) {
$scope.info.FinishDate = asDate(value);
_info_FinishDate = value;
}
return _info_FinishDate;
};
$scope.info = cashFlow;
$scope.show = function () {
$location.path('/CashFlow').search({StartDate: $scope.info.StartDate, FinishDate: $scope.info.FinishDate});
};
$scope.total = function (type) {
return $scope.info.Body[type].reduce(function (accumulator, current) {
return accumulator + current.Amount;
}, 0);
};
$scope.foDate = true;
}
CashFlowController.resolve = {
cashFlow: ['$route', 'CashFlow', function ($route, CashFlow) {
var id = $route.current.params.id,
startDate = $route.current.params.StartDate,
finishDate = $route.current.params.FinishDate;
if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) {
return CashFlow.get({}).$promise;
} else if (angular.isUndefined(id)) {
return CashFlow.get({StartDate: startDate, FinishDate: finishDate}).$promise;
} else {
return CashFlow.get({id: id, StartDate: startDate, FinishDate: finishDate}).$promise;
}
}]
};

View File

@ -0,0 +1,42 @@
export class CashFlowController {
static $inject = ['$scope', '$routeParams', '$location', 'asDateFilter', 'uibDateParser'];
_info_StartDate: any;
_info_FinishDate: any;
cashFlow: any;
info: any;
foDate: boolean;
constructor(public $scope, public $routeParams, public $location, public asDate, public dateParser) {
this.cashFlow = $scope.$parent.res.cashFlow;
this._info_StartDate = dateParser.parse(this.cashFlow.StartDate, "dd-MMM-yyyy");
this._info_FinishDate = dateParser.parse(this.cashFlow.FinishDate, "dd-MMM-yyyy");
this.info = this.cashFlow;
this.foDate = true;
}
info_StartDate(value) {
if (arguments.length) {
this.info.StartDate = this.asDate(value);
this._info_StartDate = value;
}
return this._info_StartDate;
}
info_FinishDate(value) {
if (arguments.length) {
this.info.FinishDate = this.asDate(value);
this._info_FinishDate = value;
}
return this._info_FinishDate;
}
show() {
this.$location.path('/CashFlow').search({StartDate: this.info.StartDate, FinishDate: this.info.FinishDate});
}
total(type) {
return this.info.Body[type].reduce(function (accumulator, current) {
return accumulator + current.Amount;
}, 0);
}
}

View File

@ -7,7 +7,7 @@
<div class="col-md-4">
<div class="input-group">
<input class="form-control" id="txtStartDate" type="text" uib-datepicker-popup="dd-MMM-yyyy"
is-open="sdOpen" ng-focus="sdOpen = true" ng-model="info_StartDate" focus-on="foDate"
is-open="vm.sdOpen" ng-focus="vm.sdOpen = true" ng-model="vm.info_StartDate" focus-on="vm.foDate"
ng-model-options="{getterSetter: true}"/>
<span class="input-group-btn">
<button class="btn btn-default"><i class="glyphicon glyphicon-calendar"></i></button>
@ -17,7 +17,7 @@
<div class="col-md-4">
<div class="input-group">
<input type="text" id="txtFinishDate" class="form-control" uib-datepicker-popup="dd-MMM-yyyy"
is-open="fdOpen" ng-focus="fdOpen = true" ng-model="info_FinishDate"
is-open="vm.fdOpen" ng-focus="vm.fdOpen = true" ng-model="vm.info_FinishDate"
ng-model-options="{getterSetter: true}"/>
<span class="input-group-btn">
<button class="btn btn-default"><i class="glyphicon glyphicon-calendar"></i></button>
@ -25,7 +25,7 @@
</div>
</div>
<div class="col-md-2">
<button class="btn btn-info" ng-click="show()">Show <i class="glyphicon glyphicon-eye-open"></i></button>
<button class="btn btn-info" ng-click="vm.show()">Show <i class="glyphicon glyphicon-eye-open"></i></button>
</div>
</div>
@ -37,48 +37,48 @@
<th>Total</th>
</tr>
</thead>
<tbody ng-if="info.Body.Details.length">
<tr ng-repeat="item in info.Body.Details">
<tbody ng-if="vm.info.Body.Details.length">
<tr ng-repeat="item in vm.info.Body.Details">
<td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td class="text-right">{{item.Amount | currency | clr}}</td>
<td></td>
</tr>
</tbody>
<tbody ng-if="info.Body.Operating.length">
<tbody ng-if="vm.info.Body.Operating.length">
<tr>
<td colspan="2"><strong>Cash flows from Operating activities</strong></td>
<td class="text-right">{{total('Operating') | currency | clr}}</td>
<td class="text-right">{{vm.total('Operating') | currency | clr}}</td>
</tr>
<tr ng-repeat="item in info.Body.Operating">
<tr ng-repeat="item in vm.info.Body.Operating">
<td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td class="text-right">{{item.Amount | currency | clr}}</td>
<td></td>
</tr>
</tbody>
<tbody ng-if="info.Body.Investing.length">
<tbody ng-if="vm.info.Body.Investing.length">
<tr>
<td colspan="2"><strong>Cash flows from Investing activities</strong></td>
<td class="text-right">{{total('Investing') | currency | clr}}</td>
<td class="text-right">{{vm.total('Investing') | currency | clr}}</td>
</tr>
<tr ng-repeat="item in info.Body.Investing">
<tr ng-repeat="item in vm.info.Body.Investing">
<td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td class="text-right">{{item.Amount | currency | clr}}</td>
<td></td>
</tr>
</tbody>
<tbody ng-if="info.Body.Financing.length">
<tbody ng-if="vm.info.Body.Financing.length">
<tr>
<td colspan="2"><strong>Cash flows from Financing activities</strong></td>
<td class="text-right">{{total('Financing') | currency | clr}}</td>
<td class="text-right">{{vm.total('Financing') | currency | clr}}</td>
</tr>
<tr ng-repeat="item in info.Body.Financing">
<tr ng-repeat="item in vm.info.Body.Financing">
<td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td class="text-right">{{item.Amount | currency | clr}}</td>
<td></td>
</tr>
</tbody>
<tfoot>
<tr ng-repeat="item in info.Footer">
<tr ng-repeat="item in vm.info.Footer">
<td colspan="2"><em>{{item.Name}}</em></td>
<td class="text-right">{{item.Amount | currency | clr}}</td>
</tr>

View File

@ -0,0 +1,15 @@
import * as angular from 'angular';
export function CashFlowResolver($route, CashFlow) {
const id = $route.current.params.id,
startDate = $route.current.params.StartDate,
finishDate = $route.current.params.FinishDate;
if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) {
return CashFlow.get({}).$promise;
} else if (angular.isUndefined(id)) {
return CashFlow.get({StartDate: startDate, FinishDate: finishDate}).$promise;
} else {
return CashFlow.get({id: id, StartDate: startDate, FinishDate: finishDate}).$promise;
}
}

View File

@ -0,0 +1,3 @@
export function CashFlow($resource) {
return $resource('/api/CashFlow/:id');
}

View File

@ -5,21 +5,21 @@
<label for="txtCode" class="col-md-2 control-label">Code</label>
<div class="col-md-10">
<input type="text" id="txtCode" class="form-control" disabled="disabled" ng-model="client.Code"/>
<input type="text" id="txtCode" class="form-control" disabled="disabled" ng-model="vm.client.Code"/>
</div>
</div>
<div class="form-group">
<label for="txtName" class="col-md-2 control-label">Name</label>
<div class="col-md-10">
<input type="text" id="txtName" class="form-control" ng-model="client.Name" focus-on="foName"/>
<input type="text" id="txtName" class="form-control" ng-model="vm.client.Name" focus-on="vm.foName"/>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="client.Enabled"> Enabled
<input type="checkbox" ng-model="vm.client.Enabled"> Enabled
</label>
</div>
</div>
@ -29,14 +29,14 @@
<label for="txtOTP" class="col-md-2 control-label">OTP</label>
<div class="col-md-10">
<input type="text" id="txtOTP" class="form-control" ng-model="client.OTP"/>
<input type="text" id="txtOTP" class="form-control" ng-model="vm.client.OTP"/>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button class="btn btn-primary" ng-click="save()">Save</button>
<button class="btn btn-danger" ng-show="client.ClientID" ng-click="confirm()">Delete</button>
<button class="btn btn-primary" ng-click="vm.save()">Save</button>
<button class="btn btn-danger" ng-show="vm.client.ClientID" ng-click="vm.confirm()">Delete</button>
</div>
</div>
</form>

View File

@ -0,0 +1,7 @@
import {ClientListController} from './client-list.controller';
export const ClientListComponent = {
templateUrl: '/app/client/client-list.html',
controller: ClientListController,
controllerAs: 'vm'
};

View File

@ -1,14 +0,0 @@
angular
.module('overlord')
.controller('ClientListController', ClientListController);
ClientListController.$inject = ['$scope', 'clients'];
function ClientListController($scope, clients) {
$scope.info = clients;
}
ClientListController.resolve = {
clients: ['Client', function (Client) {
return Client.query({}).$promise;
}]
};

View File

@ -0,0 +1,10 @@
export class ClientListController {
static $inject = ['$scope'];
info: any;
clients: any;
constructor(public $scope) {
this.clients = $scope.$parent.res.clients;
this.info = this.clients;
}
}

View File

@ -11,7 +11,7 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="item in info">
<tr ng-repeat="item in vm.info">
<td>{{item.Code}}</td>
<td><a href="{{item.Url}}">{{item.Name}}</a></td>
<td>{{item.Enabled}}</td>

View File

@ -0,0 +1,3 @@
export function ClientListResolver(Client) {
return Client.query({}).$promise;
}

View File

@ -0,0 +1,7 @@
import {ClientController} from './client.controller';
export const ClientComponent = {
templateUrl: '/app/client/client-detail.html',
controller: ClientController,
controllerAs: 'vm'
};

View File

@ -1,55 +0,0 @@
angular
.module('overlord')
.controller('ClientController', ClientController);
ClientController.$inject = ['$scope', '$location', '$uibModal', 'client'];
function ClientController($scope, $location, $modal, client) {
$scope.client = client;
$scope.save = function () {
$scope.client.$save(function () {
$scope.toasts.push({Type: 'Success', Message: ''});
$location.path('/Clients');
}, function (data) {
$scope.toasts.push({Type: 'Danger', Message: data.data});
});
};
$scope.delete = function () {
$scope.client.$delete(function () {
$scope.toasts.push({Type: 'Success', Message: ''});
$location.path('/Clients');
}, function (data) {
$scope.toasts.push({Type: 'Danger', Message: data.data});
});
};
$scope.confirm = function () {
var modalInstance = $modal.open({
backdrop: true,
templateUrl: '/template/modal/confirm.html',
controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) {
$scope.title = "Delete Client";
$scope.body = "Are you sure? This cannot be undone.";
$scope.isDelete = true;
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}]
});
modalInstance.result.then(function () {
$scope.delete();
});
};
$scope.foName = true;
}
ClientController.resolve = {
client: ['$route', 'Client', function ($route, Client) {
var id = $route.current.params.id;
return Client.get({id: id}).$promise;
}]
};

View File

@ -0,0 +1,57 @@
export class ClientController {
static $inject = ['$scope', '$location', '$uibModal', 'Messages'];
foName: boolean;
client: any;
constructor(public $scope, public $location, public $modal, public Messages) {
this.client = $scope.$parent.res.client;
this.foName = true;
}
save() {
this.client.$save(() => {
this.Messages.push({Type: 'Success', Message: ''});
this.$location.path('/Clients');
}, (data) => {
this.Messages.push({Type: 'Danger', Message: data.data});
});
}
delete() {
this.client.$delete(() => {
this.Messages.push({Type: 'Success', Message: ''});
this.$location.path('/Clients');
}, (data) => {
this.Messages.push({Type: 'Danger', Message: data.data});
});
}
confirm() {
const modalInstance = this.$modal.open({
backdrop: true,
templateUrl: '/template/modal/confirm.html',
controller: ['$uibModalInstance', class {
title: any;
body: any;
isDelete: boolean;
constructor(public $modalInstance) {
this.title = "Delete Client";
this.body = "Are you sure? This cannot be undone.";
this.isDelete = true;
}
ok() {
this.$modalInstance.close();
}
cancel() {
this.$modalInstance.dismiss('cancel');
}
}]
});
modalInstance.result.then(() => {
this.delete();
});
}
}

View File

@ -0,0 +1,4 @@
export function ClientResolver($route, Client) {
const id = $route.current.params.id;
return Client.get({id: id}).$promise;
}

View File

@ -0,0 +1,6 @@
export function Client($resource) {
return $resource('/api/Client/:id',
{id: '@ClientID'}, {
query: {method: 'GET', params: {list: true}, isArray: true}
});
}

View File

@ -0,0 +1,7 @@
import {ClosingStockController} from './closing-stock.controller';
export const ClosingStockComponent = {
templateUrl: '/app/closing-stock/closing-stock.html',
controller: ClosingStockController,
controllerAs: 'vm',
};

View File

@ -1,32 +0,0 @@
angular
.module('overlord')
.controller('ClosingStockController', ClosingStockController);
ClosingStockController.$inject = ['$scope', '$location', 'asDateFilter', 'info', 'uibDateParser'];
function ClosingStockController($scope, $location, asDate, info, dateParser) {
var _info_Date = dateParser.parse(info.Date, "dd-MMM-yyyy");
$scope.info_Date = function (value) {
if (arguments.length) {
$scope.info.Date = asDate(value);
_info_Date = value;
}
return _info_Date;
};
$scope.info = info;
$scope.show = function () {
$location.path('/ClosingStock/' + $scope.info.Date);
};
$scope.foDate = true;
}
ClosingStockController.resolve = {
info: ['$route', 'ClosingStock', function ($route, ClosingStock) {
var date = $route.current.params.date;
if (angular.isUndefined(date)) {
return ClosingStock.get({}).$promise;
} else {
return ClosingStock.get({date: date}).$promise;
}
}]
};

View File

@ -0,0 +1,24 @@
export class ClosingStockController {
static $inject = ['$scope', '$location', 'asDateFilter', 'uibDateParser'];
_info_Date: any;
foDate: boolean;
info: any;
constructor(public $scope, public $location, public asDate, public dateParser) {
this.info = $scope.$parent.res.info;
this._info_Date = dateParser.parse(this.info.Date, "dd-MMM-yyyy");
this.foDate = true;
}
info_Date(value) {
if (arguments.length) {
this.info.Date = this.asDate(value);
this._info_Date = value;
}
return this._info_Date;
}
show() {
this.$location.path('/ClosingStock/' + this.info.Date);
}
}

View File

@ -7,7 +7,7 @@
<div class="col-md-8">
<div class="input-group">
<input type="text" class="form-control" id="txtDate" uib-datepicker-popup="dd-MMM-yyyy"
is-open="dOpen" ng-focus="dOpen = true" ng-model="info_Date" focus-on="foDate"
is-open="vm.dOpen" ng-focus="vm.dOpen = true" ng-model="vm.info_Date" focus-on="vm.foDate"
ng-model-options="{getterSetter: true}"/>
<span class="input-group-btn">
<button class="btn btn-default"><i class="glyphicon glyphicon-calendar"></i></button>
@ -15,7 +15,7 @@
</div>
</div>
<div class="col-md-2">
<button class="btn btn-info" ng-click="show()">Show <i class="glyphicon glyphicon-eye-open"></i></button>
<button class="btn btn-info" ng-click="vm.show()">Show <i class="glyphicon glyphicon-eye-open"></i></button>
</div>
</div>
@ -29,7 +29,7 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="item in info.Body">
<tr ng-repeat="item in vm.info.Body">
<td><a href="{{item.Url}}">{{item.Product}}</a></td>
<td>{{item.Group}}</td>
<td class="text-right">{{item.Quantity | number:2}}</td>

View File

@ -0,0 +1,11 @@
import * as angular from 'angular';
export function ClosingStockResolver($route, ClosingStock) {
const date = $route.current.params.date;
if (angular.isUndefined(date)) {
return ClosingStock.get({}).$promise;
} else {
return ClosingStock.get({date: date}).$promise;
}
}

View File

@ -0,0 +1,3 @@
export function ClosingStock($resource) {
return $resource('/api/ClosingStock/:date');
}

View File

@ -0,0 +1,15 @@
import * as angular from 'angular';
export function Accounting(currencyFilter) {
return function (amount) {
amount = currencyFilter(amount);
if (angular.isUndefined(amount) || amount === '') {
return '';
}
if (amount.indexOf('-') !== -1) {
return amount.replace('-', '') + '\u00A0Cr';
} else {
return amount + '\u00A0Dr';
}
};
}

View File

@ -0,0 +1,7 @@
import * as angular from 'angular';
export function AsDate(dateFilter) {
return function (input) {
return angular.isDate(input) ? dateFilter(input, 'dd-MMM-yyyy') : input;
};
}

View File

@ -0,0 +1,5 @@
export function Auth($resource) {
return $resource('/api/Auth', {}, {
login: {method: 'GET', params: {list: true}, isArray: true}
});
}

View File

@ -0,0 +1,10 @@
import * as angular from 'angular';
export function Clr() {
return function (input) {
if (input === '\u20B9\u00A00.00' || input === '0.00') {
return '';
}
return input;
};
}

View File

@ -0,0 +1,6 @@
export function Credentials() {
return {
Auth:{},
Perms:[]
};
}

View File

@ -0,0 +1,11 @@
export function Debit () {
return function (input) {
if (input === -1) {
return 'Cr';
} else if (input === 1) {
return 'Dr';
} else {
return '';
}
};
}

View File

@ -0,0 +1,21 @@
import * as $ from 'jquery';
export function Fadey() {
return {
restrict: 'A',
link: function (scope, element, attrs) {
const duration = 500;
element = $(element);
element.hide();
element.fadeIn(duration);
scope.destroy = function (complete) {
element.fadeOut(duration, function () {
if (complete) {
complete.apply(scope);
}
});
};
}
};
}

View File

@ -0,0 +1,15 @@
export function FileUpload() {
return {
scope: true, //create a new scope
link: function (scope, el, attrs) {
el.bind('change', function (event) {
var files = event.target.files;
//iterate files since 'multiple' may be specified on the element
for (var i = 0; i < files.length; i++) {
//emit event upward
scope.$emit("fileSelected", {file: files[i]});
}
});
}
};
}

View File

@ -0,0 +1,17 @@
export function FocusOn($timeout, $parse) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.$watch(attrs.focusOn, function (value) {
if (value === true) {
var getter = $parse(attrs.focusOn);
var setter = getter.assign;
setter(scope, false);
$timeout(function () {
element[0].focus();
});
}
});
}
};
}

View File

@ -1,7 +1,7 @@
'use strict';
import * as $ from 'jquery';
overlordService.factory('growl', ['$http', '$compile', '$timeout', function ($http, $compile, $timeout) {
var growl = {};
export function Growl($http, $compile, $timeout) {
var growl:any = {};
growl.defaultOptions = {
offset: {
from: "top",
@ -15,7 +15,7 @@ overlordService.factory('growl', ['$http', '$compile', '$timeout', function ($ht
};
growl.show = function (element, scope, options) {
var options = jQuery.extend({}, growl.defaultOptions, options);
var options = $.extend({}, growl.defaultOptions, options);
if (options.top_offset) {
options.offset = {
from: "top",
@ -23,7 +23,7 @@ overlordService.factory('growl', ['$http', '$compile', '$timeout', function ($ht
};
}
var offsetAmount = options.offset.amount;
jQuery(".bootstrap-growl").each(function (index) {
$(".bootstrap-growl").each(function (index) {
var offset = parseInt($(this).css(options.offset.from)) + $(this).outerHeight() + options.stackup_spacing;
if (isNaN(offset)) {
offset = 0;
@ -60,4 +60,4 @@ overlordService.factory('growl', ['$http', '$compile', '$timeout', function ($ht
return element;
};
return growl;
}]);
}

View File

@ -0,0 +1,15 @@
import * as angular from 'angular';
export function JournalDebit () {
return function (input, debit) {
let list = [];
if (!angular.isUndefined(input)) {
for (let i = 0, l = input.length; i < l; i++) {
if (input[i].Debit === debit) {
list.push(input[i]);
}
}
}
return list;
};
}

View File

@ -0,0 +1,31 @@
import * as Mousetrap from 'mousetrap';
import * as _ from 'lodash';
import 'bmMousetrap';
// export function Keypress() {
// return {
// link: function (scope, element, attrs) {
// const keypress = scope.$eval(attrs.keypress || '{}');
// Mousetrap.bind(keypress);
// element.on('$destroy', function () {
// Mousetrap.unbind(keypress);
// });
//
// }
// }
// }
export function Keypress() {
return function (scope, element, attrs) {
const keypress = scope.$eval(attrs.keypress || '{}');
_.forEach(keypress, function (value, key) {
Mousetrap.bind(key, value);
});
element.on('$destroy', function () {
_.forEach(keypress, function (value, key) {
Mousetrap.unbind(key, value);
});
});
};
}

View File

@ -0,0 +1,51 @@
import * as angular from 'angular';
export function LocalTime() {
const months = {
Jan: 1,
Feb: 2,
Mar: 3,
Apr: 4,
May: 5,
Jun: 6,
Jul: 7,
Aug: 8,
Sep: 9,
Oct: 10,
Nov: 11,
Dec: 12
};
const monthsReverse = {
1: 'Jan',
2: 'Feb',
3: 'Mar',
4: 'Apr',
5: 'May',
6: 'Jun',
7: 'Jul',
8: 'Aug',
9: 'Sep',
10: 'Oct',
11: 'Nov',
12: 'Dec'
};
function padNumber(input, width?: number) {
input = input + '';
width = width || 2;
return input.length >= width ? input : new Array(width - input.length + 1).join('0') + input;
}
return function (input) {
if (angular.isUndefined(input)) {
return '';
}
const d = input.match(/(\w+)/g);
if (d.length !== 5) {
return input;
}
const dateInt = new Date(parseInt(d[2]), months[d[1]] - 1, parseInt(d[0]), parseInt(d[3]), parseInt(d[4])).getTime();
const date = new Date(dateInt - (new Date().getTimezoneOffset() * 60000));
return padNumber(date.getDate()) + '-' + monthsReverse[date.getMonth() + 1] + '-' + date.getFullYear() + ' ' + padNumber(date.getHours()) + ':' + padNumber(date.getMinutes());
};
}

View File

@ -0,0 +1,20 @@
import * as math from 'mathjs';
export function MathSolver() {
return function Test(expr) {
var ans;
try {
if (typeof expr === 'number') {
ans = expr;
} else {
ans = math.eval(expr.trim().replace(',', ''));
}
}
catch (e) {
ans = Number.NaN;
}
finally {
return ans;
}
};
}

View File

@ -0,0 +1,8 @@
import {Showdown} from 'showdown';
export function Md() {
var converter = new Showdown.converter();
return function (input) {
return converter.makeHtml(input || '');
};
}

View File

@ -0,0 +1,3 @@
export function Messages() {
return [];
}

View File

@ -0,0 +1,11 @@
export function NgGrowl(growl, $parse) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var options = {
dismissFunction: attrs["toClose"]
};
growl.show(element, scope, options);
}
};
}

View File

@ -0,0 +1,17 @@
export function OnReturn($parse) {
return {
compile: function ($element, attr) {
var fn = $parse(attr.onReturn);
return function (scope, element) {
element.on("keypress", function (event) {
if (event.which === 13) {
scope.$apply(function () {
fn(scope, {$event: event});
});
event.preventDefault();
}
});
};
}
};
}

View File

@ -0,0 +1,10 @@
import * as angular from 'angular';
export function Percent(numberFilter) {
return function (input) {
if (!angular.isNumber(input)) {
return input;
}
return numberFilter(input * 100, 2) + '%';
};
}

View File

@ -0,0 +1,5 @@
export function Posted () {
return function (input) {
return input === true ? 'Posted' : 'Post';
};
}

View File

@ -0,0 +1,46 @@
import * as angular from 'angular';
export function ReaderPromise($q) {
const onLoad = function (reader, deferred) {
return function () {
deferred.resolve(reader.result);
};
};
const onError = function (reader, deferred) {
return function () {
deferred.reject(reader.result);
};
};
const onProgress = function (reader, scope) {
return function (event) {
scope.$emit("fileProgress",
{
total: event.total,
loaded: event.loaded
});
};
};
const getReader = function (deferred, scope) {
const reader = new FileReader();
reader.onload = onLoad(reader, deferred);
reader.onerror = onError(reader, deferred);
if (!angular.isUndefined(scope)) {
reader.onprogress = onProgress(reader, scope);
}
return reader;
};
const readAsDataURL = function (file, scope) {
const deferred = $q.defer(),
reader = getReader(deferred, scope);
reader.readAsDataURL(file);
return deferred.promise;
};
return {
readAsDataURL: readAsDataURL
};
}

View File

@ -0,0 +1,5 @@
export function SaveButtonText() {
return function (input) {
return (!input) ? 'Save' : 'Update';
};
}

View File

@ -0,0 +1,27 @@
import * as angular from 'angular';
export function TanClick($parse, $timeout) {
return {
compile: function ($element, attr) {
var fn = $parse(attr.tanClick);
return function (scope, element, attr) {
element.on('click', function (event) {
scope.$apply(function () {
var disabled = attr.ngDisabled ? $parse(attr.ngDisabled) : angular.noop;
attr.$set('disabled', true);
var v = fn(scope, {$event: event}) || angular.noop;
if (v && v.then) {
v.finally(function () {
attr.$set('disabled', !!disabled(scope) || false);
});
} else {
$timeout(function () {
attr.$set('disabled', !!disabled(scope) || false);
}, 5000);
}
});
});
};
}
};
}

View File

@ -0,0 +1,145 @@
import * as moment from 'moment';
import * as _ from 'lodash';
export function Tokenizer($filter) {
var parseFilterString = function (q, searchInfo) {
// '[^']+'|"[^"]+"|[^ ]+ == Match a space delimited string or quoted string. ms for short
// ((ms\s*:\s*ms)|ms) == Match string : Match string OR Match string
var re = /((('[^']+'|"[^"]+"|[^\s]+)\s*:\s*('[^']+'|"[^"]+"|[^\s]+))|('[^']+'|"[^"]+"|[^\s]+))/g,
comparator = searchInfo.comparator || {},
sorter = searchInfo.sorter || {},
flagger = searchInfo.flags || {},
defaultKey = searchInfo.def,
matches = [],
sorting = [],
flags = {},
operators = {
'<': function (a, b) {
return a < b;
},
'>': function (a, b) {
return a > b;
},
'<=': function (a, b) {
return a <= b;
},
'>=': function (a, b) {
return a >= b;
},
'==': function (a, b) {
return a === b;
},
'!=': function (a, b) {
return a !== b;
}
},
comparators = {
'text': function (obj, text) {
if (text.indexOf('!') === 0) {
return !obj.toLowerCase().includes(text.substr(1).toLowerCase());
} else {
return obj.toLowerCase().includes(text.toLowerCase());
}
},
'date': function (obj, text) {
var obDate = moment(obj, 'DD-MMM-YYYY'),
op = operatorLength(text),
operator = op ? text.substr(0, op) : '==',
textDate = op ? moment(text.substr(op).trim(), 'DD-MMM-YYYY') : moment(text, 'DD-MMM-YYYY');
return !obDate.isValid() || !textDate.isValid() || operators[operator](obDate.valueOf(), textDate.valueOf());
},
'boolean': function (obj, text) {
return obj === isTrue(text);
},
'numeric': function (obj, text) {
var op = operatorLength(text);
if (op) {
return operators[text.substr(0, op)](obj, Number(text.substr(op).trim()));
} else {
return obj.toString().indexOf(text) > -1;
}
},
'true': function () {
return true;
}
};
function isTrue(value) {
return !_.any(['f', 'fa', 'fal', 'fals', 'false', 'n', 'no', '0'], function (item) {
return item === value;
});
}
function is(ch, chars) {
return chars.indexOf(ch) !== -1;
}
function pushObject(comparator, value) {
return {'Col': comparator.Col, 'Comparator': comparators[comparator.Comparator], 'Value': value};
}
function operatorLength(operator) {
var i,
ops = ['<=', '<', '>=', '>', '==', '!='];
for (i = 0; i < ops.length; i++) {
if (operator.indexOf(ops[i]) === 0) {
return ops[i].length;
}
}
return 0;
}
_(q.match(re))
.reduce(function (accumulator, item) {
var key,
value;
if (item.indexOf(':') === -1) {
key = '';
value = item;
} else {
key = item.substr(0, item.indexOf(':')).trim();
value = item.substr(item.indexOf(':') + 1, item.length).trim();
}
if (key.indexOf("'") !== -1 || key.indexOf('"') !== -1) {
key = key.substring(1, key.length - 1).trim();
}
if (value.indexOf("'") !== -1 || value.indexOf('"') !== -1) {
value = value.substring(1, value.length - 1).trim();
}
if (value !== '') {
accumulator.push({Key: key, Value: value});
}
return accumulator;
}, [])
.forEach(function (item) {
var key = item.Key,
value = item.Value;
if (key === '' && value.length > 1 && is(value.charAt(0), '+-') && value.substr(1) in sorter) {
sorting.push(value.charAt(0) + sorter[value.substr(1).toLowerCase()]);
} else {
key = key || defaultKey;
if (key in comparator) {
matches.push(pushObject(comparator[key], value));
} else if (key in flagger) {
flags[key] = value;
}
}
});
return {'q': matches, 'o': sorting, 'f': flags};
};
var doFilter = function (q, array, matches) {
var filterExpressions = matches.q,
sortPredicates = matches.o,
filterCount = filterExpressions.length;
var arrayCopy = filterCount === 0 ? array : _.filter(array, function (item) {
return _.every(filterExpressions, function (expression) {
return expression.Comparator(item[expression.Col], expression.Value);
});
});
arrayCopy = $filter('orderBy')(arrayCopy, sortPredicates);
return arrayCopy;
};
return {parseFilterString: parseFilterString, doFilter: doFilter};
}

View File

@ -0,0 +1,52 @@
import * as angular from 'angular';
import * as _ from 'lodash';
export function UploadedImageResizer($q, ReaderPromise) {
function resizeImage(file, MAX_WIDTH, MAX_HEIGHT) {
var image = file,
canvas = document.createElement('canvas'),
ctx = canvas.getContext("2d"),
img = document.createElement("img"),
ratio = 1;
img.src = image;
var width = img.width,
height = img.height;
if (width > MAX_WIDTH) {
ratio = MAX_WIDTH / width;
}
if (height > MAX_HEIGHT && MAX_HEIGHT / height < ratio) {
ratio = MAX_HEIGHT / height;
}
if (ratio === 1) {
return file;
}
width *= ratio;
height *= ratio;
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
return canvas.toDataURL("image/jpeg", 0.95);
}
var ProcessUpload = function (uploadedFile, oldFiles) {
var file:any = {File: uploadedFile.file},
exists = _.some(oldFiles, function (value) {
return angular.equals(value.File, file.File);
});
if (exists) {
return;
}
ReaderPromise.readAsDataURL(uploadedFile.file).then(function (result) {
file.Original = result;
file.Thumbnail = resizeImage(result, 100, 150);
file.Resized = resizeImage(result, 825, 1170);
});
oldFiles.push(file);
};
return ProcessUpload;
}

View File

@ -0,0 +1,44 @@
import * as angular from 'angular';
export function Voucher($resource) {
return $resource('/api/Voucher/:id',
{id: '@VoucherID'}, {
post: {method: 'POST', params: {post: true}},
save: {
method: 'POST',
headers: {'Content-Type': undefined},
transformRequest: function (orgData, headers) {
var data = angular.copy(orgData);
function dataURLtoBlob(dataURL) {
var re = /^data:([\w/\-\.]+);\w+,(.*)$/,
m = dataURL.match(re),
mimeString = m[1],
byteString = atob(m[2]),
ab = new ArrayBuffer(byteString.length),
dw = new DataView(ab),
i;
for (i = 0; i < byteString.length; i++) {
dw.setUint8(i, byteString.charCodeAt(i));
}
return new Blob([ab], {type: mimeString});
}
let fd = new FormData(),
files = [],
i;
for (i = data.Files.length - 1; i >= 0; i--) {
let item = data.Files[i];
if (!item.ID) {
fd.append('f' + i, dataURLtoBlob(item.Resized));
fd.append('t' + i, dataURLtoBlob(item.Thumbnail));
data.Files.splice(i, 1);
}
}
fd.append('model', angular.toJson(data));
return fd;
}
}
});
}

View File

@ -5,12 +5,12 @@
<label for="txtName" class="col-md-2 control-label">Name</label>
<div class="col-md-10">
<input type="text" id="txtName" class="form-control" ng-model="costCentre.Name" focus-on="foName"/>
<input type="text" id="txtName" class="form-control" ng-model="vm.costCentre.Name" focus-on="vm.foName"/>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button class="btn btn-primary" ng-click="save()">Save</button>
<button class="btn btn-primary" ng-click="vm.save()">Save</button>
</div>
</div>
</form>

View File

@ -0,0 +1,7 @@
import {CostCentreListController} from './cost-centre-list.controller';
export const CostCentreListComponent = {
templateUrl: '/app/cost-centre/cost-centre-list.html',
controller: CostCentreListController,
controllerAs: 'vm'
};

View File

@ -1,14 +0,0 @@
angular
.module('overlord')
.controller('CostCentreListController', CostCentreListController);
CostCentreListController.$inject = ['$scope', 'costCentres'];
function CostCentreListController($scope, costCentres) {
$scope.info = costCentres;
}
CostCentreListController.resolve = {
costCentres: ['CostCentre', function (CostCentre) {
return CostCentre.query({}).$promise;
}]
};

View File

@ -0,0 +1,10 @@
export class CostCentreListController {
static $inject = ['$scope'];
info: any;
costCentres: any;
constructor(public $scope) {
this.costCentres = $scope.$parent.res.costCentres;
this.info = this.costCentres;
}
}

View File

@ -6,7 +6,7 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="item in info">
<tr ng-repeat="item in vm.info">
<td><a href="{{item.Url}}">{{item.Name}}</a></td>
</tr>
</tbody>

View File

@ -0,0 +1,3 @@
export function CostCentreListResolver(CostCentre) {
return CostCentre.query({}).$promise;
}

View File

@ -0,0 +1,7 @@
import {CostCentreController} from './cost-centre.controller';
export const CostCentreComponent = {
templateUrl: '/app/cost-centre/cost-centre-detail.html',
controller: CostCentreController,
controllerAs: 'vm'
};

View File

@ -1,34 +0,0 @@
angular
.module('overlord')
.controller('CostCentreController', CostCentreController);
CostCentreController.$inject = ['$scope', '$routeParams', '$location', 'costCentre'];
function CostCentreController($scope, $routeParams, $location, costCentre) {
$scope.costCentre = costCentre;
$scope.save = function () {
$scope.costCentre.$save(function (u, putResponseHeaders) {
$scope.toasts.push({Type: 'Success', Message: ''});
$location.path('/CostCentres')
}, function (data, status) {
$scope.toasts.push({Type: 'Danger', Message: data.data});
});
};
$scope.delete = function () {
$scope.costCentre.$delete(function (u, putResponseHeaders) {
$scope.toasts.push({Type: 'Success', Message: ''});
$location.path('/CostCentres')
}, function (data, status) {
$scope.toasts.push({Type: 'Danger', Message: data.data});
});
};
$scope.foName = true;
}
CostCentreController.resolve = {
costCentre: ['$route', 'CostCentre', function ($route, CostCentre) {
var id = $route.current.params.id;
return CostCentre.get({id: id}).$promise;
}]
};

View File

@ -0,0 +1,28 @@
export class CostCentreController {
static $inject = ['$scope', '$routeParams', '$location', 'Messages'];
foName: any;
costCentre: any;
constructor(public $scope, public $routeParams, public $location, public Messages) {
this.costCentre = $scope.$parent.res.costCentre;
this.foName = true;
}
save() {
this.costCentre.$save((u, putResponseHeaders) => {
this.Messages.push({Type: 'Success', Message: ''});
this.$location.path('/CostCentres')
}, (data, status) => {
this.Messages.push({Type: 'Danger', Message: data.data});
});
}
delete() {
this.costCentre.$delete((u, putResponseHeaders) => {
this.Messages.push({Type: 'Success', Message: ''});
this.$location.path('/CostCentres')
}, (data, status) => {
this.Messages.push({Type: 'Danger', Message: data.data});
});
}
}

View File

@ -0,0 +1,4 @@
export function CostCentreResolver($route, CostCentre) {
const id = $route.current.params.id;
return CostCentre.get({id: id}).$promise;
}

View File

@ -0,0 +1,6 @@
export function CostCentre($resource) {
return $resource('/api/CostCentre/:id',
{id: '@CostCentreID'}, {
query: {method: 'GET', params: {list: true}, isArray: true}
});
}

View File

@ -0,0 +1,7 @@
import {DaybookController} from './daybook.controller';
export const DaybookComponent = {
templateUrl: '/app/daybook/daybook.html',
controller: DaybookController,
controllerAs: 'vm'
};

View File

@ -1,40 +0,0 @@
angular
.module('overlord')
.controller('DaybookController', DaybookController);
DaybookController.$inject = ['$scope', '$location', 'asDateFilter', 'info', 'uibDateParser'];
function DaybookController($scope, $location, asDate, info, dateParser) {
var _info_StartDate = dateParser.parse(info.StartDate, "dd-MMM-yyyy"),
_info_FinishDate = dateParser.parse(info.FinishDate, "dd-MMM-yyyy");
$scope.info_StartDate = function (value) {
if (arguments.length) {
$scope.info.StartDate = asDate(value);
_info_StartDate = value;
}
return _info_StartDate;
};
$scope.info_FinishDate = function (value) {
if (arguments.length) {
$scope.info.FinishDate = asDate(value);
_info_FinishDate = value;
}
return _info_FinishDate;
};
$scope.info = info;
$scope.show = function () {
$location.path('/Daybook').search({StartDate: $scope.info.StartDate, FinishDate: $scope.info.FinishDate});
};
$scope.foDate = true;
}
DaybookController.resolve = {
info: ['$route', 'Daybook', function ($route, Daybook) {
var startDate = $route.current.params.StartDate,
finishDate = $route.current.params.FinishDate;
if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) {
return Daybook.get({}).$promise;
} else {
return Daybook.get({StartDate: startDate, FinishDate: finishDate}).$promise;
}
}]
};

View File

@ -0,0 +1,36 @@
import * as angular from 'angular';
export class DaybookController {
static $inject = ['$scope', '$location', 'asDateFilter', 'uibDateParser'];
_info_StartDate:any;
_info_FinishDate:any;
foDate:boolean;
info:any;
constructor(public $scope, public $location, public asDate, public dateParser) {
this.info = $scope.$parent.res.info;
this._info_StartDate = dateParser.parse(this.info.StartDate, "dd-MMM-yyyy");
this._info_FinishDate = dateParser.parse(this.info.FinishDate, "dd-MMM-yyyy");
this.foDate = true;
}
info_StartDate(value) {
if (arguments.length) {
this.info.StartDate = this.asDate(value);
this._info_StartDate = value;
}
return this._info_StartDate;
}
info_FinishDate(value) {
if (arguments.length) {
this.info.FinishDate = this.asDate(value);
this. _info_FinishDate = value;
}
return this._info_FinishDate;
}
show() {
this.$location.path('/Daybook').search({StartDate: this.info.StartDate, FinishDate: this.info.FinishDate});
}
}

View File

@ -7,7 +7,7 @@
<div class="col-md-4">
<div class="input-group">
<input class="form-control" id="txtStartDate" type="text" uib-datepicker-popup="dd-MMM-yyyy"
is-open="sdOpen" ng-focus="sdOpen = true" ng-model="info_StartDate" focus-on="foDate"
is-open="vm.sdOpen" ng-focus="vm.sdOpen = true" ng-model="vm.info_StartDate" focus-on="vm.foDate"
ng-model-options="{getterSetter: true}"/>
<span class="input-group-btn">
<button class="btn btn-default"><i class="glyphicon glyphicon-calendar"></i></button>
@ -17,7 +17,7 @@
<div class="col-md-4">
<div class="input-group">
<input type="text" id="txtFinishDate" class="form-control" uib-datepicker-popup="dd-MMM-yyyy"
is-open="fdOpen" ng-focus="fdOpen = true" ng-model="info_FinishDate"
is-open="vm.fdOpen" ng-focus="vm.fdOpen = true" ng-model="vm.info_FinishDate"
ng-model-options="{getterSetter: true}"/>
<span class="input-group-btn">
<button class="btn btn-default"><i class="glyphicon glyphicon-calendar"></i></button>
@ -25,7 +25,7 @@
</div>
</div>
<div class="col-md-2">
<button class="btn btn-info" ng-click="show()">Show <i class="glyphicon glyphicon-eye-open"></i></button>
<button class="btn btn-info" ng-click="vm.show()">Show <i class="glyphicon glyphicon-eye-open"></i></button>
</div>
</div>
<table id="gvGrid" class="table table-condensed table-bordered table-striped">
@ -41,7 +41,7 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="item in info.Body" ng-class="{true:'', false:'error'}[item.Posted]">
<tr ng-repeat="item in vm.info.Body" ng-class="{true:'', false:'error'}[item.Posted]">
<td><a href="{{item.Url}}">{{item.Date}}</a></td>
<td>{{item.Type}}</td>
<td>{{item.Narration}}</td>

Some files were not shown because too many files have changed in this diff Show More