29 Commits

Author SHA1 Message Date
1496dca1bc Add materialize in webpack configuration. 2017-10-28 22:28:25 +02:00
4982931457 Add jquery and materialize-css in tsconfig. 2017-10-28 22:28:25 +02:00
13d79ae567 Concat jquery and materialize in separated bundle. 2017-10-28 22:28:25 +02:00
a20e481f08 Add materialize in webpack provide plugin. 2017-10-28 22:26:02 +02:00
a283651eae Try to use materialize for login popup. 2017-10-28 22:26:02 +02:00
3216be85ef Remove requirejs. 2017-10-28 22:26:02 +02:00
5cab9fa5e4 Remove require. 2017-10-28 22:26:02 +02:00
116b61e509 Improve webpack configuration. 2017-10-28 22:26:02 +02:00
49482eab9f Remove unused old login.config module. 2017-10-28 22:26:02 +02:00
7021cff9d9 Fix JQuery provide for materialize. 2017-10-28 22:26:02 +02:00
926acd18ae Add TS linting. 2017-10-28 22:26:02 +02:00
a650f52fe2 Fix add button style. 2017-10-28 22:24:26 +02:00
fe2d539812 Use ng2-materialize in schedule module. 2017-10-28 22:24:26 +02:00
fbcec48038 Use ng2-materialize in operations module. 2017-10-28 22:24:26 +02:00
4a1c246e00 Use ng2-materialize in app component. 2017-10-28 22:24:26 +02:00
8fcbef9b5a Use ng2-materialize in account module. 2017-10-28 22:24:26 +02:00
b5abe44bd9 Fix operation row action buttons. 2017-10-28 22:24:26 +02:00
e592efd25d Fix operation table styles. 2017-10-28 22:24:26 +02:00
6a4523aceb Remove button groups. 2017-10-28 22:24:26 +02:00
9b6ae093a4 Fix text and table row styles. 2017-10-28 22:24:26 +02:00
34ade59d4c Fix button styles. 2017-10-28 22:24:26 +02:00
7a0b7837da Fix table row style. 2017-10-28 22:24:26 +02:00
fdef99085a Fix table and add button styles. 2017-10-28 22:24:26 +02:00
bf82f2a4ea Update index to remove useless style. 2017-10-28 22:24:26 +02:00
acdbe3ab48 Update account list component template to use Materialize. 2017-10-28 22:24:26 +02:00
674411a1e2 Update operation list component template to use Materialize. 2017-10-28 22:24:26 +02:00
5e7b2167c1 Update app component template to use Materialize. 2017-10-28 22:24:26 +02:00
d3295d8a96 Bootstrap Materialize module. 2017-10-28 22:24:26 +02:00
7e378fd86a Fix SASS loading. 2017-10-28 22:22:28 +02:00
20 changed files with 249 additions and 255 deletions

View File

@ -4,9 +4,12 @@
"repository": "https://git.lahouze.org/xals/accountant",
"license": "AGPL-1.0",
"devDependencies": {
"angular2-template-loader": "^0.6.2",
"awesome-typescript-loader": "^3.2.3",
"babel-core": "^6.26.0",
"babel-eslint": "^8.0.1",
"babel-loader": "^7.1.2",
"codelyzer": "^3.1.2",
"css-loader": "^0.28.5",
"ejs-loader": "^0.3.0",
"eslint": "^4.10.0",
@ -30,12 +33,17 @@
"loglevel": "^1.5.1",
"ngtemplate-loader": "^2.0.1",
"node-sass": "^4.5.3",
"resolve-url-loader": "^2.1.0",
"sass-loader": "^6.0.6",
"style-loader": "^0.19.0",
"ts-loader": "^3.1.0",
"tslint": "^5.7.0",
"tslint-config-prettier": "^1.4.0",
"tslint-loader": "^3.5.3",
"typescript": "^2.4.2",
"url-loader": "^0.6.2",
"webpack": "^3.8.1",
"webpack-concat-plugin": "^1.4.1",
"webpack-dev-server": "^2.9.3"
},
"dependencies": {
@ -59,6 +67,7 @@
"font-awesome": "^4.7.0",
"jquery": "^3.2.1",
"moment": "^2.19.1",
"ng2-materialize": "^1.5.1",
"ngx-toastr": "^6.5.0",
"reflect-metadata": "^0.1.10",
"rxjs": "^5.5.2",

View File

@ -9,6 +9,7 @@ import { RouterModule } from '@angular/router';
import { NgLoggerModule, Level } from '@nsalaun/ng-logger';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { ToastrModule } from 'ngx-toastr';
import { MaterializeModule } from 'ng2-materialize';
import { AccountService } from './account.service';
import { AccountBalancesService } from './accountBalances.service';
@ -30,7 +31,8 @@ import { AccountListState } from './account.states'
]),
NgLoggerModule,
ToastrModule,
NgbModule
NgbModule,
MaterializeModule,
],
providers: [
AccountService,

View File

@ -15,7 +15,8 @@ import { AccountEditModalComponent } from './accountEditModal.component';
selector: 'account-list',
template: `
<div class="row">
<table class="table table-sm table-striped table-condensed table-hover">
<div class="col s12">
<table class="bordered highlight responsive-table">
<thead>
<tr>
<th>Nom du compte</th>
@ -29,7 +30,7 @@ import { AccountEditModalComponent } from './accountEditModal.component';
<tbody>
<tr>
<td colspan="5">
<button class="btn btn-success" (click)="add()">
<button mz-button class="green" (click)="add()">
Ajouter
</button>
</td>
@ -40,6 +41,7 @@ import { AccountEditModalComponent } from './accountEditModal.component';
</tr>
</tbody>
</table>
</div>
</div>
`,
})

View File

@ -17,8 +17,9 @@ import { AccountEditModalComponent } from './accountEditModal.component';
selector: 'tr[account-row]',
host: {
"[id]": "account.id",
"[class.warning]": "warning",
"[class.danger]": "danger"
"class": "lighten-5",
"[class.orange]": "account.authorized_overdraft < 0 && accountBalances?.current < 0",
"[class.red]": "accountBalances?.current < account.authorized_overdraft",
},
template: `
<td>
@ -26,13 +27,17 @@ import { AccountEditModalComponent } from './accountEditModal.component';
</td>
<td>
<span (ngClass)="valueClass(account, accountBalances?.current)">
<span class="text-lighten-2"
[class.orange-text]="account.authorized_overdraft < 0 && accountBalances?.current < 0"
[class.red-text]="accountBalances?.current < account.authorized_overdraft">
{{ accountBalances?.current | currency:"EUR":true }}
</span>
</td>
<td>
<span (ngClass)="valueClass(account, accountBalances?.pointed)">
<span class="text-lighten-2"
[class.orange-text]="account.authorized_overdraft < 0 && accountBalances?.pointed < 0"
[class.red-text]="accountBalances?.pointed < account.authorized_overdraft">
{{ accountBalances?.pointed | currency:"EUR":true }}
</span>
</td>
@ -40,26 +45,24 @@ import { AccountEditModalComponent } from './accountEditModal.component';
<td>{{ account.authorized_overdraft | currency:"EUR":true }}</td>
<td>
<div class="btn-group btn-group-sm">
<!-- Edit account. -->
<button type="button" class="btn btn-success"
<button mz-button [float]="true" class="green"
(click)="modify()">
<span class="fa fa-pencil-square-o"></span>
</button>
<!-- Delete account, with confirm. -->
<button type="button" class="btn btn-secondary"
<button mz-button [float]="true" class="red"
(click)="confirmDelete()">
<span class="fa fa-trash-o"></span>
</button>
<!-- Open account scheduler. -->
<a class="btn btn-secondary"
<button mz-button [float]="true"
[hidden]="!account.id"
[routerLink]="['/account', account.id, 'scheduler']">
<span class="fa fa-clock-o"></span>
</a>
</div>
</button>
</td>
`
})
@ -88,32 +91,6 @@ export class AccountRowComponent implements OnInit {
})
}
get warning() {
return this.account && this.accountBalances
&& this.account.authorized_overdraft < this.accountBalances.current
&& this.accountBalances.current < 0;
};
get error() {
return this.account && this.accountBalances
&& this.accountBalances.current < this.account.authorized_overdraft;
};
/*
* Return the class for a value compared to account authorized overdraft.
*/
valueClass(value: number) {
if (!value) {
return;
}
if (value < this.account.authorized_overdraft) {
return 'text-danger';
} else if (value < 0) {
return 'text-warning';
}
};
confirmDelete() {
const modal = this.ngbModal.open(AccountDeleteModalComponent);

View File

@ -6,13 +6,13 @@ import { Component } from '@angular/core';
selector: 'accountant',
template: `
<!-- Navbar -->
<nav class="navbar fixed-top navbar-dark bg-dark">
<a class="navbar-brand" routerLink="/accounts">&nbsp;Accountant</a>
</nav>
<div class="container-fluid">
<router-outlet></router-outlet>
<div class="navbar-fixed">
<mz-navbar>
<a class="brand-logo" routerLink="/accounts">&nbsp;Accountant</a>
</mz-navbar>
</div>
<router-outlet></router-outlet>
`
})
export class AppComponent { }

View File

@ -10,6 +10,7 @@ import { RouterModule } from '@angular/router';
import { NgLoggerModule } from '@nsalaun/ng-logger';
import { ToastrModule } from 'ngx-toastr';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { MaterializeModule } from 'ng2-materialize'
import { LoginModule } from './login/login.module';
import { AccountModule } from './accounts/account.module';
@ -38,6 +39,7 @@ import { ApiBaseURL, LogLevel } from './app.config';
NgLoggerModule.forRoot(LogLevel),
ToastrModule.forRoot(),
NgbModule.forRoot(),
MaterializeModule.forRoot(),
AccountModule,
ScheduleModule,
OperationModule,

View File

@ -9,9 +9,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<!-- htmllint attr-bans="false" -->
<body style="padding-bottom: 50px; padding-top: 70px">
<!-- htmllint attr-bans="$previous" -->
<body>
<accountant></accountant>
</body>
</html>

View File

@ -1,31 +0,0 @@
module.exports = function($httpProvider, $storageProvider) {
// Define interceptors.
$httpProvider.interceptors.push(function($storage) {
return {
request: function(config) {
var access_token = $storage.session.get('access_token');
if (access_token) {
//var tokenType = $storage.get('token_type');
var tokenType = 'Bearer';
var authorization = tokenType + ' ' + access_token;
config.headers.authorization = authorization;
}
return config;
},
};
});
// Configure storage
// Set global prefix for stored keys
$storageProvider.setPrefix('accountant');
// Change the default storage engine
// Defaults to 'local'
$storageProvider.setDefaultStorageEngine('session');
// Change the enabled storage engines
// Defaults to ['memory', 'cookie', 'session', 'local']
$storageProvider.setEnabledStorageEngines(['local', 'session']);
};

View File

@ -5,6 +5,7 @@ import { CommonModule } from '@angular/common';
import { ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { MaterializeModule } from 'ng2-materialize';
import { NgLoggerModule } from '@nsalaun/ng-logger';
@ -18,6 +19,7 @@ import { LoginModalComponent } from './loginModal.component';
HttpClientModule,
CommonModule,
ReactiveFormsModule,
MaterializeModule,
NgLoggerModule,
],
providers: [

View File

@ -6,7 +6,7 @@ import { Observable} from 'rxjs/Rx';
import * as base64 from 'base64util';
import { Logger } from '@nsalaun/ng-logger';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { MzModalService } from 'ng2-materialize';
import { Token } from './token';
import { LoginModalComponent } from './loginModal.component';
@ -18,24 +18,25 @@ export class LoginService {
constructor(
private httpClient: HttpClient,
private logger: Logger,
private ngbModal: NgbModal,
private mzModalService: MzModalService,
) {}
public readonly url: string = '/api/user/login';
login(): Observable<Token> {
let modal = this.ngbModal.open(LoginModalComponent);
let modal = this.mzModalService.open(LoginModalComponent);
sessionStorage.clear();
let observable: Observable<any> = Observable.fromPromise(modal.result);
//let observable: Observable<any> = Observable.fromPromise(modal.result);
return observable.flatMap((login: Login) =>
this.doLogin(login)
).map((token: Token): Token => {
this.accessToken = token.access_token;
return token;
});
//return observable.flatMap((login: Login) =>
// this.doLogin(login)
//).map((token: Token): Token => {
// this.accessToken = token.access_token;
// return token;
//});
return null;
}
logout() {

View File

@ -1,7 +1,7 @@
// vim: set tw=80 ts=2 sw=2 sts=2:
import { Component, Input, ViewChild } from '@angular/core';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { MzBaseModal } from 'ng2-materialize';
import { Login } from './login';
import { LoginFormComponent } from './loginForm.component';
@ -9,15 +9,16 @@ import { LoginFormComponent } from './loginForm.component';
@Component({
selector: 'login-modal',
template: `
<div class="modal-header">
<h3 class="modal-title" id="modal-title">Authentification requise</h3>
</div>
<mz-modal>
<mz-modal-header>
Authentification requise
</mz-modal-header>
<div class="modal-body" id="modal-body">
<mz-modal-content>
<login-form (submit)="submit()" #loginForm="loginForm"></login-form>
</div>
</mz-modal-content>
<div class="modal-footer">
<mz-modal-footer>
<button class="btn btn-primary" [disabled]="!loginForm.form.valid" (click)="submit()">
Login
</button>
@ -25,27 +26,24 @@ import { LoginFormComponent } from './loginForm.component';
<button class="btn btn-default" (click)="cancel()">
Cancel
</button>
</div>
</mz-modal-footer>
</mz-modal>
`
})
export class LoginModalComponent {
export class LoginModalComponent extends MzBaseModal {
@ViewChild('loginForm') loginForm: LoginFormComponent;
constructor(private activeModal: NgbActiveModal) {
//submit(): void {
// let formModel = this.loginForm.form.value;
// let login: Login = new Login();
}
// login.email = formModel.email;
// login.password = formModel.password;
submit(): void {
let formModel = this.loginForm.form.value;
let login: Login = new Login();
// this.activeModal.close(login);
//}
login.email = formModel.email;
login.password = formModel.password;
this.activeModal.close(login);
}
cancel(): void {
this.activeModal.dismiss("closed");
}
//cancel(): void {
// this.activeModal.dismiss("closed");
//}
}

View File

@ -2,7 +2,7 @@ $fa-font-path: '~font-awesome/fonts';
@import '~font-awesome/scss/font-awesome';
@import '~bootstrap/scss/bootstrap';
@import '~materialize-css/sass/materialize.scss';
@import '~c3/c3';

View File

@ -10,6 +10,7 @@ import { NgLoggerModule, Level } from '@nsalaun/ng-logger';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { ToastrModule } from 'ngx-toastr';
import { TextMaskModule } from 'angular2-text-mask';
import { MaterializeModule } from 'ng2-materialize';
import { BalanceChartComponent } from './balanceChart.component';
import { CategoryChartComponent } from './categoryChart.component';
@ -33,7 +34,8 @@ import { OperationListState } from './operation.states'
NgLoggerModule,
ToastrModule,
NgbModule,
TextMaskModule
TextMaskModule,
MaterializeModule,
],
providers: [
CategoryService,

View File

@ -19,12 +19,12 @@ import { OperationEditModalComponent } from './operationEditModal.component';
template: `
<div>
<div class="row">
<div class="col-md-9">
<div class="col s9">
<balance-chart (onUpdate)="onUpdate($event)"
[account]="account"></balance-chart>
</div>
<div class="col-md-3">
<div class="col s3">
<category-chart
[minDate]="minDate"
[maxDate]="maxDate"
@ -33,7 +33,8 @@ import { OperationEditModalComponent } from './operationEditModal.component';
</div>
<div class="row">
<table class="table table-striped table-condensed table-hover">
<div class="col s12">
<table class="bordered highlight responsive-table">
<thead>
<tr>
<th>#</th>
@ -48,8 +49,8 @@ import { OperationEditModalComponent } from './operationEditModal.component';
<tbody>
<tr>
<td colspan="6">
<button class="btn btn-success" (click)="add()">
<td colspan="7">
<button mz-button class="green" (click)="add()">
Ajouter
</button>
</td>
@ -63,6 +64,7 @@ import { OperationEditModalComponent } from './operationEditModal.component';
</tbody>
</table>
</div>
</div>
</div>
`
})

View File

@ -17,8 +17,9 @@ import { OperationEditModalComponent } from './operationEditModal.component';
"[id]": "operation.id",
"[class.stroke]": "operation.canceled",
"[class.italic]": "!operation.confirmed",
"[class.warning]": "operation.balance < 0",
"[class.danger]": "operation.balance < account.authorized_overdraft"
"class": "lighten-5",
"[class.orange]": "account.authorized_overdraft < 0 && operation.balance < 0",
"[class.red]": "operation.balance < account.authorized_overdraft"
},
template: `
<td>{{ operation.id }}</td>
@ -29,24 +30,24 @@ import { OperationEditModalComponent } from './operationEditModal.component';
<td>{{ operation.value | currency:'EUR':true }}</td>
<td [class.text-warning]="operation.balance < 0"
[class.text-danger]="operation.balance < account.authorized_overdraft">
<td class="test-lighten-2"
[class.orange-text]="account.authorized_overdraft < 0 && operation.balance < 0"
[class.red-text]="operation.balance < account.authorized_overdraft">
{{ operation.balance | currency:'EUR':true }}
</td>
<td>{{ operation.category }}</td>
<td>
<div class="btn-group btn-group-sm">
<!-- Edit operation, for non-canceled operation. -->
<button type="button" class="btn btn-success"
<button mz-button [float]="true" class="green"
*ngIf="!operation.canceled"
(click)="modify(operation)" title="edit">
<span class="fa fa-pencil-square-o"></span>
</button>
<!-- Toggle pointed operation, for non-canceled operations. -->
<button type="button" class="btn btn-secondary"
<button mz-button [float]="true" class="blue"
*ngIf="!operation.canceled"
(click)="togglePointed(operation)"
[class.active]="operation.pointed" title="point">
@ -55,7 +56,7 @@ import { OperationEditModalComponent } from './operationEditModal.component';
</button>
<!-- Toggle canceled operation. -->
<button type="button" class="btn btn-warning"
<button mz-button [float]="true" class="orange"
(click)="toggleCanceled(operation)"
*ngIf="operation.scheduled_operation_id"
[class.active]="operation.canceled" title="cancel">
@ -63,12 +64,11 @@ import { OperationEditModalComponent } from './operationEditModal.component';
</button>
<!-- Delete operation, with confirm. -->
<button type="button" class="btn btn-danger"
<button mz-button [float]="true" class="red"
(click)="confirmDelete(operation)"
*ngIf="operation.id && !operation.scheduled_operation_id">
<span class="fa fa-trash-o"></span>
</button>
</div>
</td>
`
})

View File

@ -10,6 +10,7 @@ import { NgLoggerModule, Level } from '@nsalaun/ng-logger';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { ToastrModule } from 'ngx-toastr';
import { TextMaskModule } from 'angular2-text-mask';
import { MaterializeModule } from 'ng2-materialize';
import { ScheduleService } from './schedule.service';
import { ScheduleDeleteModalComponent } from './scheduleDeleteModal.component';
@ -30,7 +31,8 @@ import { ScheduleListState } from './schedule.states';
NgLoggerModule,
ToastrModule,
NgbModule,
TextMaskModule
TextMaskModule,
MaterializeModule,
],
providers: [
ScheduleService,

View File

@ -16,7 +16,7 @@ import { Schedule } from './schedule';
selector: 'schedule-list',
template: `
<div class="row">
<table class="table table-sm table-striped table-condensed table-hover">
<table class="bordered highlight responsive-table">
<thead>
<tr>
<th>Date de d&eacute;but</th>
@ -33,7 +33,7 @@ import { Schedule } from './schedule';
<tbody>
<tr>
<td colspan="8">
<button class="btn btn-success" (click)="add()">
<button mz-button class="green" (click)="add()">
Ajouter
</button>
</td>

View File

@ -33,21 +33,19 @@ import { Schedule } from './schedule';
<td>{{ schedule.category }}</td>
<td>
<div class="btn-group btn-group-sm">
<!-- Edit operation. -->
<button type="button" class="btn btn-success"
<button mz-button [float]="true" class="green"
(click)="modify()" title="edit">
<span class="fa fa-pencil-square-o"></span>
</button>
<!-- Remove operation. -->
<button type="button" class="btn btn-danger"
<button mz-button [float]="true" class="red"
[hidden]="!schedule.id"
(click)="confirmDelete()"
title="remove">
<span class="fa fa-trash"></span>
</button>
</div>
</td>
`
})

View File

@ -8,6 +8,10 @@
"experimentalDecorators": true,
"lib": [ "es2015", "dom" ],
"noImplicitAny": false,
"suppressImplicitAnyIndexErrors": true
"suppressImplicitAnyIndexErrors": true,
"types": [
"jquery",
"materialize-css"
]
}
}

View File

@ -6,16 +6,20 @@ const webpack = require('webpack');
module.exports = {
context: path.resolve(__dirname, 'src'),
entry: {
"main": [
main: [
'./main.ts'
],
"styles": [
styles: [
'./main.scss'
],
vendor: [
'jquery',
'materialize-css'
]
},
devtool: 'source-map',
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx', '.html'],
extensions: ['.js', '.ts', '.html'],
},
module: {
rules: [{
@ -37,7 +41,7 @@ module.exports = {
}, {
// Javascript
enforce: 'pre',
test: /\.jsx?$/,
test: /\.js$/,
//include: path.resolve(__dirname, 'src'),
loader: 'eslint-loader',
options: {
@ -60,38 +64,53 @@ module.exports = {
]
},
}, {
test: /\.jsx?$/,
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}, {
test: /\.tsx?$/,
// Typescript linting
enforce: 'pre',
test: /\.ts$/,
loader: 'tslint-loader',
options: {
configuration: {
extends: [
"tslint:latest",
"codelyzer"
],
rules: {
//quotemark: [true, 'single']
}
},
configFile: 'tslint-custom.json',
emitErrors: true,
failOnHint: true,
typeCheck: true,
tsConfigFile: 'tsconfig.json',
formatter: 'verbose',
formattersDirectory: 'node_modules/tslint/lib/formatters/',
}
}, {
test: /\.ts$/,
exclude: /node_modules/,
loader: 'ts-loader'
loaders: ['awesome-typescript-loader', 'angular2-template-loader?keepUrl=true']
}, {
test: /\.html$/,
use: [
'ngtemplate-loader?relativeTo=/accountant-ui/src',
'html-loader'
]
}, {
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader',
]
loader: 'raw-loader'
}, {
test: /\.css$/,
use: [
loaders: [
'style-loader',
'css-loader',
]
}, {
test: /\.scss$/,
use: [
loaders: [
'style-loader',
'css-loader',
'sass-loader',
'resolve-url-loader',
'sass-loader?sourceMap'
]
}, {
test: /\.(png|woff|woff2|eot|ttf|svg)$/,
@ -99,8 +118,15 @@ module.exports = {
}]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: "vendor"
}),
new webpack.ProvidePlugin({
"window.jQuery": "jquery"
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
"window.Materialize": "materialize-css",
"Materialize": "materialize-css"
}),
new webpack.ContextReplacementPlugin(
/angular(\\|\/)core(\\|\/)@angular/,