Begin conversion to typescript.

This commit is contained in:
Alexis Lahouze 2017-07-10 00:52:39 +02:00
parent cae86d3014
commit 5df62de278
10 changed files with 138 additions and 66 deletions

View File

@ -4,6 +4,11 @@
"repository": "https://git.lahouze.org/xals/accountant", "repository": "https://git.lahouze.org/xals/accountant",
"license": "AGPL-1.0", "license": "AGPL-1.0",
"devDependencies": { "devDependencies": {
"@types/angular": "^1.6.25",
"@types/angular-resource": "^1.5.9",
"@types/angular-strap": "^2.2.32",
"@types/angular-ui-notification": "^0.0.4",
"angular-tslint-rules": "^1.0.3",
"babel-core": "^6.25.0", "babel-core": "^6.25.0",
"babel-eslint": "^7.2.3", "babel-eslint": "^7.2.3",
"babel-loader": "^7.0.0", "babel-loader": "^7.0.0",
@ -29,6 +34,9 @@
"less-loader": "^4.0.4", "less-loader": "^4.0.4",
"ngtemplate-loader": "^2.0.0", "ngtemplate-loader": "^2.0.0",
"style-loader": "^0.18.2", "style-loader": "^0.18.2",
"ts-loader": "^2.2.2",
"tslint": "^5.5.0",
"tslint-loader": "^3.5.3",
"url-loader": "^0.5.8", "url-loader": "^0.5.8",
"webpack": "^2.6.1", "webpack": "^2.6.1",
"webpack-dev-server": "2.4.5" "webpack-dev-server": "2.4.5"

View File

@ -1,4 +0,0 @@
module.exports = function($resourceProvider) {
// Keep trailing slashes to avoid redirect by flask.
$resourceProvider.defaults.stripTrailingSlashes = false;
};

View File

@ -0,0 +1,7 @@
/// <reference path="../../node_modules/@types/angular/index.d.ts" />
/// <reference path="../../node_modules/@types/angular-resource/index.d.ts" />
export default function AccountConfig ($resourceProvider) {
// Keep trailing slashes to avoid redirect by flask.
$resourceProvider.defaults.stripTrailingSlashes = false;
};

View File

@ -1,20 +1,44 @@
var accountFormTmpl = require('./account.form.tmpl.html'), /// <reference types="angular" />
accountDeleteTmpl = require('./account.delete.tmpl.html'); /// <reference types="angular-ui-notification" />
module.exports = function(Account, Notification, $log, $modal) { //import accountFormTmpl from './account.form.tmpl.html';
var vm = this; //import accountDeleteTmpl from './account.delete.tmpl.html';
import IAccount from './account.factory';
export interface IAccountController {
rowClass(account: IAccount) : string;
valueClass(account: IAccount, value: number) : string;
add() : void;
save(account: IAccount) : void;
confirmDelete(account: IAccount): void;
delete(account: IAccount): void;
modify(account: IAccount): void;
};
export default class AccountController {
static $inject = ['AccountResource', 'Notification', '$log', '$modal'];
private accounts: IAccount[];
constructor(
public AccountResource: AccountResource,
public Notification: angular.uiNotification.INotificationService,
public $modal: mgcrea.ngStrap.modal.IModalService) {
// Load accounts.
this.accounts = Account.query();
};
/* /*
* Return the class for an account current value compared to authorized * Return the class for an account current value compared to authorized
* overdraft. * overdraft.
*/ */
vm.rowClass = function(account) { rowClass(account : IAccount): string {
// eslint-disable-next-line camelcase
if (!account || !account.authorized_overdraft || !account.current) { if (!account || !account.authorized_overdraft || !account.current) {
return; return '';
} }
// eslint-disable-next-line camelcase
if (account.current < account.authorized_overdraft) { if (account.current < account.authorized_overdraft) {
return 'danger'; return 'danger';
} else if (account.current < 0) { } else if (account.current < 0) {
@ -25,12 +49,11 @@ module.exports = function(Account, Notification, $log, $modal) {
/* /*
* Return the class for a value compared to account authorized overdraft. * Return the class for a value compared to account authorized overdraft.
*/ */
vm.valueClass = function(account, value) { valueClass (account: IAccount, value: number): string {
if (!account || !value) { if (!account || !value) {
return; return '';
} }
// eslint-disable-next-line camelcase
if (value < account.authorized_overdraft) { if (value < account.authorized_overdraft) {
return 'text-danger'; return 'text-danger';
} else if (value < 0) { } else if (value < 0) {
@ -41,36 +64,34 @@ module.exports = function(Account, Notification, $log, $modal) {
/* /*
* Add an empty account. * Add an empty account.
*/ */
vm.add = function() { add(): void {
var account = new Account({ var account = new Account({
// eslint-disable-next-line camelcase // eslint-disable-next-line camelcase
authorized_overdraft: 0 authorized_overdraft: 0
}); });
// Insert account at the begining of the array. // Insert account at the begining of the array.
return vm.modify(account); this.modify(account);
}; };
/* /*
* Save account. * Save account.
*/ */
vm.save = function(account) { save(account: IAccount): void {
return account.$save().then(function(data) { return account.$save().then(function(data) {
Notification.success('Account #' + data.id + ' saved.'); this.Notification.success('Account #' + data.id + ' saved.');
vm.accounts = Account.query(); this.accounts = Account.query();
return data;
}, function(result){ }, function(result){
$log.error('Error while saving account', account, result); $log.error('Error while saving account', account, result);
Notification.error( this.Notification.error(
'Error while saving account: ' + result.message 'Error while saving account: ' + result.message
); );
}); });
}; };
vm.confirmDelete = function(account) { confirmDelete(account: IAccount): void {
var title = "Delete account #" + account.id; var title = "Delete account #" + account.id;
$modal({ $modal({
@ -86,7 +107,7 @@ module.exports = function(Account, Notification, $log, $modal) {
locals: { locals: {
title: title, title: title,
account: account, account: account,
$delete: vm.delete $delete: this.delete
} }
}); });
}; };
@ -94,17 +115,15 @@ module.exports = function(Account, Notification, $log, $modal) {
/* /*
* Delete an account. * Delete an account.
*/ */
vm.delete = function(account) { delete(account: IAccount): void {
var id = account.id; var id = account.id;
return account.$delete().then(function() { account.$delete().then(function() {
Notification.success('account #' + id + ' deleted.'); this.Notification.success('account #' + id + ' deleted.');
vm.accounts = Account.query(); this.accounts = Account.query();
return account;
}, function(result) { }, function(result) {
Notification.error( this.Notification.error(
'An error occurred while trying to delete account #' + 'An error occurred while trying to delete account #' +
id + ':<br />' + result id + ':<br />' + result
); );
@ -114,7 +133,7 @@ module.exports = function(Account, Notification, $log, $modal) {
/* /*
* Open the popup to modify the account, save it on confirm. * Open the popup to modify the account, save it on confirm.
*/ */
vm.modify = function(account) { modify(account: IAccount): void {
// FIXME Alexis Lahouze 2017-06-15 i18n // FIXME Alexis Lahouze 2017-06-15 i18n
var title = "Account"; var title = "Account";
@ -137,11 +156,8 @@ module.exports = function(Account, Notification, $log, $modal) {
locals: { locals: {
title: title, title: title,
account: account, account: account,
$save: vm.save $save: this.save
} }
}); });
}; };
// Load accounts.
vm.accounts = Account.query();
}; };

View File

@ -1,26 +0,0 @@
module.exports = function($resource) {
var Account = $resource(
'/api/account/:id', {
id: '@id'
}
);
Account.prototype.getBalances = function() {
var Balances = $resource('/api/account/:id/balances', {id: this.id});
this.balances = Balances.get();
};
Account.prototype.getBalance = function(begin, end) {
var Balance = $resource(
'/api/account/:id/balance', {
id: this.id,
begin: begin.format('YYYY-MM-DD'),
end: end.format('YYYY-MM-DD')
});
this.balance = Balance.get();
};
return Account;
};

View File

@ -0,0 +1,19 @@
/// <reference types="angular" />
/// <reference types="angular-resource" />
export interface IAccount extends ng.resource.IResource<IAccount> {
id: number;
name: string;
authorized_overdraft: number;
};
export interface IAccountResource extends ng.resource.IResourceClass<IAccount> {
};
export default function AccountResource($resource) {
return <IAccountResource> $resource(
'/api/account/:id', {
id: '@id'
}
);
};

View File

@ -0,0 +1,21 @@
import * as angular from 'angular';
import 'angular-resource';
export interface IAccountBalances
extends ng.resource.IResource<IAccountBalances> {
current: number;
pointed: number;
future: number;
};
export interface IAccountBalancesResource
extends ng.resource.IResourceClass<IAccountBalances> {
};
export default function AccountBalancesResource($resource) {
return <IAccountBalancesResource> $resource(
'/api/account/:id/balances', {
id: '@id'
}
);
};

View File

@ -25,9 +25,10 @@ var ngResource = require('angular-resource'),
ngUiNotification = require('angular-ui-notification'), ngUiNotification = require('angular-ui-notification'),
ngStrap = require('angular-strap'); ngStrap = require('angular-strap');
var AccountFactory = require('./account.factory.js'); var AccountBalancesFactory = require('./accountBalances.factory');
var AccountConfig = require('./account.config.js'); var AccountFactory = require('./account.factory');
var AccountController = require('./account.controller.js'); var AccountConfig = require('./account.config');
var AccountController = require('./account.controller');
module.exports = angular.module('accountant.accounts', [ module.exports = angular.module('accountant.accounts', [
ngResource, ngResource,
@ -39,6 +40,7 @@ module.exports = angular.module('accountant.accounts', [
.config(AccountConfig) .config(AccountConfig)
.factory('Account', AccountFactory) .factory('Account', AccountFactory)
.factory('AccountBalances', AccountBalancesFactory)
.controller('AccountController', AccountController) .controller('AccountController', AccountController)

0
tsconfig.json Normal file
View File

View File

@ -7,6 +7,10 @@ module.exports = {
context: path.resolve(__dirname, 'src'), context: path.resolve(__dirname, 'src'),
entry: './app.js', entry: './app.js',
devtool: 'source-map', devtool: 'source-map',
resolve: {
// Add '.ts' and '.tsx' as a resolvable extension.
extensions: ['.webpack.js', '.web.js', '.ts', '.tsx', '.js', '.html']
},
module: { module: {
rules: [{ rules: [{
enforce: 'pre', enforce: 'pre',
@ -24,6 +28,31 @@ module.exports = {
indent: ['error', 4] indent: ['error', 4]
}, },
}, },
}, {
// typescript linting
enforce: 'pre',
test: /\.tsx?$/,
exclude: /(node_modules|bootstrap)/,
loader: 'tslint-loader',
options: {
configFile: false,
emitErrors: true,
baseConfig: 'angular',
allowJs: true,
configuration: {
extends: ["angular-tslint-rules"],
include: [
'src/**/*'
],
rules: {
indent: ['error', 4]
},
},
},
}, {
test: /\.tsx?$/,
exclude: /node_modules/,
loader: 'ts-loader'
}, { }, {
// Javascript // Javascript
enforce: 'pre', enforce: 'pre',