Compare commits

..

7 Commits

Author SHA1 Message Date
Patrick Nagurny
b0c129c980 Merge pull request #65 from alokmenghrajani/alok/fix_form_group_bug
Fixes <label> for attribute
2025-01-21 18:59:52 -07:00
Alok Menghrajani
62ec4a21fa Fixes <label> for attribute
The current for attribute is incorrect when creating a new organization. As a
result, clicking on the label does not select the proper radio button.
2025-01-20 13:53:39 +01:00
Patrick Nagurny
e093e0cdbe Merge pull request #64 from alokmenghrajani/dashboard_recent_transactions_account_name
Show account name on the dashboard's recent transactions
2023-11-20 12:44:02 -07:00
Alok Menghrajani
7a3deb4006 Show account name on the dashboard's recent transactions
If a transaction description is brief, it is useful to provide context by showing
the account name.

Note: this commit isn't ideal since it doesn't show all the accounts involved for
a given transaction. This might however be good enough for now.
2023-11-20 18:19:32 +01:00
Patrick Nagurny
9a6eef2fcc Merge pull request #63 from alokmenghrajani/main
Add currency when calling currencyFormat
2023-09-28 08:57:22 -06:00
Alok Menghrajani
7cf5c4a392 Tweak currencyFormat to display currency when it's not USD 2023-09-28 12:12:53 +02:00
Alok Menghrajani
bb93ac6bb5 Add currency when calling currencyFormat 2023-09-21 02:04:15 +02:00
8 changed files with 360 additions and 441 deletions

709
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@
<h5>Current spending</h5> <h5>Current spending</h5>
</div> </div>
<div class="col-4 amount"> <div class="col-4 amount">
<h5>{{expenseAmount | currencyFormat:org.precision}}</h5> <h5>{{expenseAmount | currencyFormat:org.precision:org.currency}}</h5>
</div> </div>
</div> </div>
<div class="row" *ngFor="let expense of expenseAccounts" [routerLink]="'/accounts/'+expense.id+'/transactions'" [ngClass]="{hidden: hiddenExpenses[expense.id]}"> <div class="row" *ngFor="let expense of expenseAccounts" [routerLink]="'/accounts/'+expense.id+'/transactions'" [ngClass]="{hidden: hiddenExpenses[expense.id]}">
@@ -28,7 +28,7 @@
{{expense.fullName | accountName:2}} {{expense.fullName | accountName:2}}
</div> </div>
<div class="col-4 amount"> <div class="col-4 amount">
{{expense.nativeBalanceCost | currencyFormat:org.precision}} {{expense.nativeBalanceCost | currencyFormat:org.precision:org.currency}}
</div> </div>
</div> </div>
<div class="row"> <div class="row">
@@ -59,10 +59,11 @@
{{recentTx.tx.date | datetz:"M/D":org.timezone}} {{recentTx.tx.date | datetz:"M/D":org.timezone}}
</div> </div>
<div class="col-5 col-md-6 description"> <div class="col-5 col-md-6 description">
{{recentTx.tx.description}} <div class="primary">{{recentTx.tx.description}}</div>
<div class="additional">{{recentTx.account.fullName}}</div>
</div> </div>
<div class="col-4 col-md-4 amount" [ngClass]="{'negative': recentTx.split.amount > 0}"> <div class="col-4 col-md-4 amount" [ngClass]="{'negative': recentTx.split.amount > 0}">
{{-recentTx.split.amount | currencyFormat:recentTx.account.precision}} {{-recentTx.split.amount | currencyFormat:recentTx.account.precision:recentTx.account.currency}}
</div> </div>
</div> </div>
<div class="row"> <div class="row">

View File

@@ -41,6 +41,19 @@
.expanded .hidden { .expanded .hidden {
display: flex display: flex
} }
.row {
padding-bottom: 1em;
.description {
.primary:empty::after {
content: ".";
visibility: hidden;
}
.additional {
font-size: small;
color: $black;
}
}
}
} }
@media (max-width: 767px) { @media (max-width: 767px) {

View File

@@ -53,7 +53,7 @@
</div> </div>
<div class="form-check"> <div class="form-check">
<input formControlName="createDefaultAccounts" id="createDefaultAccounts3" type="radio" class="form-check-input" value="personal" /> <input formControlName="createDefaultAccounts" id="createDefaultAccounts3" type="radio" class="form-check-input" value="personal" />
<label for="createDefaultAccounts2" class="form-check-label">Personal accounts</label> <label for="createDefaultAccounts3" class="form-check-label">Personal accounts</label>
</div> </div>
</div> </div>
<p *ngIf="error" class="error"> <p *ngIf="error" class="error">

View File

@@ -160,7 +160,7 @@
</div> </div>
<div class="form-check"> <div class="form-check">
<input formControlName="createDefaultAccounts" id="createDefaultAccounts3" type="radio" class="form-check-input" value="personal" /> <input formControlName="createDefaultAccounts" id="createDefaultAccounts3" type="radio" class="form-check-input" value="personal" />
<label for="createDefaultAccounts2" class="form-check-label">Personal accounts</label> <label for="createDefaultAccounts3" class="form-check-label">Personal accounts</label>
</div> </div>
</div> </div>
<p *ngIf="newOrgError" class="error">{{newOrgError.message}}</p> <p *ngIf="newOrgError" class="error">{{newOrgError.message}}</p>

View File

@@ -29,8 +29,8 @@
<h4>Assets</h4> <h4>Assets</h4>
</div> </div>
<div class="col-4 amount"> <div class="col-4 amount">
<h4 *ngIf="priceSource === 'price'">{{+assetAccount.totalNativeBalancePrice | currencyFormat:org.precision}}</h4> <h4 *ngIf="priceSource === 'price'">{{+assetAccount.totalNativeBalancePrice | currencyFormat:org.precision:org.currency}}</h4>
<h4 *ngIf="priceSource === 'cost'">{{+assetAccount.totalNativeBalanceCost | currencyFormat:org.precision}}</h4> <h4 *ngIf="priceSource === 'cost'">{{+assetAccount.totalNativeBalanceCost | currencyFormat:org.precision:org.currency}}</h4>
</div> </div>
</div> </div>
<div class="row" *ngFor="let account of assetAccounts" [attr.depth]="account.depth"> <div class="row" *ngFor="let account of assetAccounts" [attr.depth]="account.depth">
@@ -39,10 +39,10 @@
<span *ngIf="!account.children.length"><a [routerLink]="'/accounts/' + account.id + '/transactions'">{{account.name | slice:0:30}}</a></span> <span *ngIf="!account.children.length"><a [routerLink]="'/accounts/' + account.id + '/transactions'">{{account.name | slice:0:30}}</a></span>
</div> </div>
<div class="col-4 amount" *ngIf="priceSource === 'price' && account.totalNativeBalancePrice"> <div class="col-4 amount" *ngIf="priceSource === 'price' && account.totalNativeBalancePrice">
{{+account.totalNativeBalancePrice | currencyFormat:org.precision}} {{+account.totalNativeBalancePrice | currencyFormat:org.precision:org.currency}}
</div> </div>
<div class="col-4 amount" *ngIf="priceSource === 'cost' && account.totalNativeBalanceCost"> <div class="col-4 amount" *ngIf="priceSource === 'cost' && account.totalNativeBalanceCost">
{{+account.totalNativeBalanceCost | currencyFormat:org.precision}} {{+account.totalNativeBalanceCost | currencyFormat:org.precision:org.currency}}
</div> </div>
</div> </div>
<div class="row"> <div class="row">
@@ -55,8 +55,8 @@
<h4>Liabilities</h4> <h4>Liabilities</h4>
</div> </div>
<div class="col-4 amount"> <div class="col-4 amount">
<h4 *ngIf="priceSource === 'price'">{{-liabilityAccount.totalNativeBalancePrice | currencyFormat:org.precision}}</h4> <h4 *ngIf="priceSource === 'price'">{{-liabilityAccount.totalNativeBalancePrice | currencyFormat:org.precision:org.currency}}</h4>
<h4 *ngIf="priceSource === 'cost'">{{-liabilityAccount.totalNativeBalanceCost | currencyFormat:org.precision}}</h4> <h4 *ngIf="priceSource === 'cost'">{{-liabilityAccount.totalNativeBalanceCost | currencyFormat:org.precision:org.currency}}</h4>
</div> </div>
</div> </div>
<div class="row" *ngFor="let account of liabilityAccounts" [attr.depth]="account.depth"> <div class="row" *ngFor="let account of liabilityAccounts" [attr.depth]="account.depth">
@@ -65,10 +65,10 @@
<span *ngIf="!account.children.length"><a [routerLink]="'/accounts/' + account.id + '/transactions'">{{account.name | slice:0:30}}</a></span> <span *ngIf="!account.children.length"><a [routerLink]="'/accounts/' + account.id + '/transactions'">{{account.name | slice:0:30}}</a></span>
</div> </div>
<div class="col-4 amount" *ngIf="priceSource === 'price' && account.totalNativeBalancePrice"> <div class="col-4 amount" *ngIf="priceSource === 'price' && account.totalNativeBalancePrice">
{{-account.totalNativeBalancePrice | currencyFormat:org.precision}} {{-account.totalNativeBalancePrice | currencyFormat:org.precision:org.currency}}
</div> </div>
<div class="col-4 amount" *ngIf="priceSource === 'cost' && account.totalNativeBalanceCost"> <div class="col-4 amount" *ngIf="priceSource === 'cost' && account.totalNativeBalanceCost">
{{-account.totalNativeBalanceCost | currencyFormat:org.precision}} {{-account.totalNativeBalanceCost | currencyFormat:org.precision:org.currency}}
</div> </div>
</div> </div>
<div class="row" depth="1"> <div class="row" depth="1">
@@ -76,8 +76,8 @@
<h4>Equity</h4> <h4>Equity</h4>
</div> </div>
<div class="col-4 amount"> <div class="col-4 amount">
<h4 *ngIf="priceSource === 'price'">{{-equityAccount.totalNativeBalancePrice | currencyFormat:org.precision}}</h4> <h4 *ngIf="priceSource === 'price'">{{-equityAccount.totalNativeBalancePrice | currencyFormat:org.precision:org.currency}}</h4>
<h4 *ngIf="priceSource === 'cost'">{{-equityAccount.totalNativeBalanceCost | currencyFormat:org.precision}}</h4> <h4 *ngIf="priceSource === 'cost'">{{-equityAccount.totalNativeBalanceCost | currencyFormat:org.precision:org.currency}}</h4>
</div> </div>
</div> </div>
<div class="row" *ngFor="let account of equityAccounts" [attr.depth]="account.depth"> <div class="row" *ngFor="let account of equityAccounts" [attr.depth]="account.depth">
@@ -86,10 +86,10 @@
<span *ngIf="!account.children.length"><a [routerLink]="'/accounts/' + account.id + '/transactions'">{{account.name | slice:0:30}}</a></span> <span *ngIf="!account.children.length"><a [routerLink]="'/accounts/' + account.id + '/transactions'">{{account.name | slice:0:30}}</a></span>
</div> </div>
<div class="col-4 amount" *ngIf="priceSource === 'price' && account.totalNativeBalancePrice"> <div class="col-4 amount" *ngIf="priceSource === 'price' && account.totalNativeBalancePrice">
{{-account.totalNativeBalancePrice | currencyFormat:org.precision}} {{-account.totalNativeBalancePrice | currencyFormat:org.precision:org.currency}}
</div> </div>
<div class="col-4 amount" *ngIf="priceSource === 'cost' && account.totalNativeBalanceCost"> <div class="col-4 amount" *ngIf="priceSource === 'cost' && account.totalNativeBalanceCost">
{{-account.totalNativeBalanceCost | currencyFormat:org.precision}} {{-account.totalNativeBalanceCost | currencyFormat:org.precision:org.currency}}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -24,7 +24,7 @@
<h4>Income</h4> <h4>Income</h4>
</div> </div>
<div class="col-4 amount"> <div class="col-4 amount">
<h4>{{-incomeAccount.totalNativeBalanceCost | currencyFormat:org.precision}}</h4> <h4>{{-incomeAccount.totalNativeBalanceCost | currencyFormat:org.precision:org.currency}}</h4>
</div> </div>
</div> </div>
<div class="row" *ngFor="let account of incomeAccounts" [attr.depth]="account.depth"> <div class="row" *ngFor="let account of incomeAccounts" [attr.depth]="account.depth">
@@ -33,7 +33,7 @@
<span *ngIf="!account.children.length"><a [routerLink]="'/accounts/' + account.id + '/transactions'">{{account.name | slice:0:30}}</a></span> <span *ngIf="!account.children.length"><a [routerLink]="'/accounts/' + account.id + '/transactions'">{{account.name | slice:0:30}}</a></span>
</div> </div>
<div class="col-4 amount" *ngIf="account.totalNativeBalanceCost"> <div class="col-4 amount" *ngIf="account.totalNativeBalanceCost">
{{-account.totalNativeBalanceCost | currencyFormat:org.precision}} {{-account.totalNativeBalanceCost | currencyFormat:org.precision:org.currency}}
</div> </div>
</div> </div>
<div class="row" depth="1"> <div class="row" depth="1">
@@ -41,7 +41,7 @@
<h4>Expenses</h4> <h4>Expenses</h4>
</div> </div>
<div class="col-4 amount"> <div class="col-4 amount">
<h4>{{expenseAccount.totalNativeBalanceCost | currencyFormat:org.precision}}</h4> <h4>{{expenseAccount.totalNativeBalanceCost | currencyFormat:org.precision:org.currency}}</h4>
</div> </div>
</div> </div>
<div class="row" *ngFor="let account of expenseAccounts" [attr.depth]="account.depth"> <div class="row" *ngFor="let account of expenseAccounts" [attr.depth]="account.depth">
@@ -50,7 +50,7 @@
<span *ngIf="!account.children.length"><a [routerLink]="'/accounts/' + account.id + '/transactions'">{{account.name | slice:0:30}}</a></span> <span *ngIf="!account.children.length"><a [routerLink]="'/accounts/' + account.id + '/transactions'">{{account.name | slice:0:30}}</a></span>
</div> </div>
<div class="col-4 amount" *ngIf="account.totalNativeBalanceCost"> <div class="col-4 amount" *ngIf="account.totalNativeBalanceCost">
{{account.totalNativeBalanceCost | currencyFormat:org.precision}} {{account.totalNativeBalanceCost | currencyFormat:org.precision:org.currency}}
</div> </div>
</div> </div>
<div class="row" depth="1"> <div class="row" depth="1">
@@ -58,7 +58,7 @@
<h4>Net Income</h4> <h4>Net Income</h4>
</div> </div>
<div class="col-4 amount"> <div class="col-4 amount">
<h4>{{-incomeAccount.totalNativeBalanceCost - expenseAccount.totalNativeBalanceCost | currencyFormat:org.precision}}</h4> <h4>{{-incomeAccount.totalNativeBalanceCost - expenseAccount.totalNativeBalanceCost | currencyFormat:org.precision:org.currency}}</h4>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,6 +1,15 @@
import { Pipe, PipeTransform } from '@angular/core'; import { Pipe, PipeTransform } from '@angular/core';
import { DecimalPipe } from '@angular/common'; import { DecimalPipe } from '@angular/common';
// Format the currency according to the user's browser locale.
//
// Some currencies share the same symbol (e.g. $ is used for USD and CAN).
// Ideally, the user experience should not be confusing if different accounts
// have conflicting symbols. One solution might be to always show the ISO
// currency code for accounts with mixes currencies. Another solution would be
// to let the user configure how the currency is displayed on a per-currency
// or per-account basis.
@Pipe({ name: 'currencyFormat' }) @Pipe({ name: 'currencyFormat' })
export class CurrencyFormatPipe implements PipeTransform { export class CurrencyFormatPipe implements PipeTransform {
constructor(private decimalPipe: DecimalPipe) { constructor(private decimalPipe: DecimalPipe) {
@@ -11,17 +20,12 @@ export class CurrencyFormatPipe implements PipeTransform {
return ''; return '';
} }
let prefix = amount < 0 ? '-' : ''; // note: we can drop the cast to any if we change the ts target from es5 to es2020 or newer.
return Intl.NumberFormat(navigator.language, {
if(currency === 'USD') { style: "currency",
prefix += '$'; currency,
} minimumFractionDigits: precision,
signDisplay: "negative",
let minDigits = Math.min(2, precision); } as any).format(amount / Math.pow(10, precision));
return prefix +
this.decimalPipe.transform(
Math.abs(amount) / Math.pow(10, precision),
'1.' + minDigits + '-' + precision);
} }
} }