Migrate categories backend calls to promise api

This commit is contained in:
William Brawner 2022-11-09 22:15:44 -07:00
parent 87092be0f9
commit ec47fc130d
9 changed files with 92 additions and 105 deletions

View file

@ -4,8 +4,6 @@ import { ActivatedRoute, Router } from '@angular/router';
import { AppComponent } from 'src/app/app.component'; import { AppComponent } from 'src/app/app.component';
import { Transaction } from 'src/app/transactions/transaction'; import { Transaction } from 'src/app/transactions/transaction';
import { Category } from 'src/app/categories/category'; import { Category } from 'src/app/categories/category';
import { Observable } from 'rxjs';
// import { Label } from 'ng2-charts';
import { ChartDataset } from 'chart.js'; import { ChartDataset } from 'chart.js';
import { TWIGS_SERVICE, TwigsService } from 'src/app/shared/twigs.service'; import { TWIGS_SERVICE, TwigsService } from 'src/app/shared/twigs.service';
import { Actionable } from '../../shared/actionable'; import { Actionable } from '../../shared/actionable';
@ -16,7 +14,6 @@ import { Actionable } from '../../shared/actionable';
styleUrls: ['./budget-details.component.css'] styleUrls: ['./budget-details.component.css']
}) })
export class BudgetDetailsComponent implements OnInit, OnDestroy, Actionable { export class BudgetDetailsComponent implements OnInit, OnDestroy, Actionable {
budget: Budget; budget: Budget;
public budgetBalance: number; public budgetBalance: number;
public transactions: Transaction[]; public transactions: Transaction[];
@ -132,43 +129,38 @@ export class BudgetDetailsComponent implements OnInit, OnDestroy, Actionable {
.subscribe(transactions => this.transactions = <Transaction[]>transactions); .subscribe(transactions => this.transactions = <Transaction[]>transactions);
} }
getCategories(): void { async getCategories() {
this.twigsService.getCategories(this.budget.id).subscribe(categories => { const categories = await this.twigsService.getCategories(this.budget.id)
const categoryBalances = new Map<string, number>(); const categoryBalances = new Map<string, number>();
let categoryBalancesCount = 0; let categoryBalancesCount = 0;
console.log(categories); for (const category of categories) {
for (const category of categories) { if (category.expense) {
if (category.expense) { this.expenses.push(category);
this.expenses.push(category); this.expectedExpenses += category.amount;
this.expectedExpenses += category.amount; } else {
} else { this.income.push(category);
this.income.push(category); this.expectedIncome += category.amount;
this.expectedIncome += category.amount;
}
this.twigsService.getCategoryBalance(category.id, this.from, this.to).subscribe(
balance => {
console.log(balance);
if (category.expense) {
this.actualExpenses += balance * -1;
} else {
this.actualIncome += balance;
}
categoryBalances.set(category.id, balance);
categoryBalancesCount++;
},
error => { categoryBalancesCount++; },
() => {
// This weird workaround is to force the OnChanges callback to be fired.
// Angular needs the reference to the object to change in order for it to
// work.
if (categoryBalancesCount === categories.length) {
this.categoryBalances = categoryBalances;
this.updateBarChart();
}
}
);
} }
}); try {
const balance = await this.twigsService.getCategoryBalance(category.id, this.from, this.to)
console.log(balance);
if (category.expense) {
this.actualExpenses += balance * -1;
} else {
this.actualIncome += balance;
}
categoryBalances.set(category.id, balance);
if (categoryBalancesCount === categories.length - 1) {
// This weird workaround is to force the OnChanges callback to be fired.
// Angular needs the reference to the object to change in order for it to
// work.
this.categoryBalances = categoryBalances;
this.updateBarChart();
}
} finally {
categoryBalancesCount++;
}
}
} }
doAction(): void { doAction(): void {

View file

@ -33,7 +33,7 @@ export class CategoriesComponent implements OnInit {
} }
getCategories(): void { getCategories(): void {
this.twigsService.getCategories(this.budgetId).subscribe(categories => { this.twigsService.getCategories(this.budgetId).then(categories => {
this.categories = categories; this.categories = categories;
for (const category of this.categories) { for (const category of this.categories) {
this.getCategoryBalance(category).subscribe(balance => this.categoryBalances.set(category.id, balance)); this.getCategoryBalance(category).subscribe(balance => this.categoryBalances.set(category.id, balance));

View file

@ -28,7 +28,7 @@ export class CategoryDetailsComponent implements OnInit, OnDestroy, Actionable {
this.router.navigateByUrl(this.router.routerState.snapshot.url + "/edit") this.router.navigateByUrl(this.router.routerState.snapshot.url + "/edit")
} }
getActionLabel(): string { getActionLabel(): string {
return "Edit"; return "Edit";
} }
@ -45,7 +45,7 @@ export class CategoryDetailsComponent implements OnInit, OnDestroy, Actionable {
getCategory(): void { getCategory(): void {
const id = this.route.snapshot.paramMap.get('id'); const id = this.route.snapshot.paramMap.get('id');
this.twigsService.getCategory(id) this.twigsService.getCategory(id)
.subscribe(category => { .then(category => {
category.amount /= 100; category.amount /= 100;
this.app.setTitle(category.title) this.app.setTitle(category.title)
this.category = category; this.category = category;

View file

@ -26,10 +26,10 @@ export class CategoryFormComponent implements OnInit {
} }
save(): void { save(): void {
let observable; let promise;
if (this.create) { if (this.create) {
// This is a new category, save it // This is a new category, save it
observable = this.twigsService.createCategory( promise = this.twigsService.createCategory(
this.currentCategory.id, this.currentCategory.id,
this.budgetId, this.budgetId,
this.currentCategory.title, this.currentCategory.title,
@ -39,7 +39,7 @@ export class CategoryFormComponent implements OnInit {
); );
} else { } else {
// This is an existing category, update it // This is an existing category, update it
observable = this.twigsService.updateCategory( promise = this.twigsService.updateCategory(
this.currentCategory.id, this.currentCategory.id,
{ {
name: this.currentCategory.title, name: this.currentCategory.title,
@ -50,13 +50,13 @@ export class CategoryFormComponent implements OnInit {
} }
); );
} }
observable.subscribe(val => { promise.then(_ => {
this.app.goBack(); this.app.goBack();
}); });
} }
delete(): void { delete(): void {
this.twigsService.deleteCategory(this.currentCategory.id).subscribe(() => { this.twigsService.deleteCategory(this.currentCategory.id).then(() => {
this.app.goBack(); this.app.goBack();
}); });
} }

View file

@ -28,7 +28,7 @@ export class EditCategoryComponent implements OnInit {
getCategory(): void { getCategory(): void {
const id = this.route.snapshot.paramMap.get('id'); const id = this.route.snapshot.paramMap.get('id');
this.twigsService.getCategory(id) this.twigsService.getCategory(id)
.subscribe(category => { .then(category => {
category.amount /= 100; category.amount /= 100;
this.app.setTitle(category.title) this.app.setTitle(category.title)
this.category = category; this.category = category;

View file

@ -122,38 +122,38 @@ export class TwigsHttpService implements TwigsService {
} }
// Categories // Categories
getCategories(budgetId: string, count?: number): Observable<Category[]> { getCategories(budgetId: string, count?: number): Promise<Category[]> {
const params = { const url = new URL(`/api/categories`, this.apiUrl)
params: new HttpParams() url.searchParams.set('budgetIds', budgetId)
.set('budgetIds', `${budgetId}`) url.searchParams.set('archived', 'false')
.set('archived', false) return this.request(url, HttpMethod.GET);
};
return this.http.get<Category[]>(`${this.apiUrl}/categories`, Object.assign(params, this.options));
} }
getCategory(id: string): Observable<Category> { getCategory(id: string): Promise<Category> {
return this.http.get<Category>(`${this.apiUrl}/categories/${id}`, this.options); const url = new URL(`/api/categories/${id}`, this.apiUrl)
return this.request(url, HttpMethod.GET);
} }
getCategoryBalance( async getCategoryBalance(
id: string, id: string,
from?: Date, from?: Date,
to?: Date to?: Date
): Observable<number> { ): Promise<number> {
let httpParams = new HttpParams(); const url = new URL(`/api/transactions/sum`, this.apiUrl)
url.searchParams.set('categoryId', id)
if (from) { if (from) {
httpParams = httpParams.set('from', from.toISOString()); url.searchParams.set('from', from.toISOString());
} }
if (to) { if (to) {
httpParams = httpParams.set('to', to.toISOString()); url.searchParams.set('to', to.toISOString());
} }
const params = { params: httpParams }; const res: any = await this.request(url, HttpMethod.GET);
return this.http.get<any>(`${this.apiUrl}/transactions/sum?categoryId=${id}`, { ...this.options, ...params }) return res.balance;
.pipe(map(obj => obj.balance));
} }
createCategory(id: string, budgetId: string, name: string, description: string, amount: number, isExpense: boolean): Observable<Category> { createCategory(id: string, budgetId: string, name: string, description: string, amount: number, isExpense: boolean): Promise<Category> {
const params = { const url = new URL(`/api/categories`, this.apiUrl)
const body = {
'id': id, 'id': id,
'title': name, 'title': name,
'description': description, 'description': description,
@ -161,15 +161,17 @@ export class TwigsHttpService implements TwigsService {
'expense': isExpense, 'expense': isExpense,
'budgetId': budgetId 'budgetId': budgetId
}; };
return this.http.post<Category>(this.apiUrl + '/categories', params, this.options); return this.request(url, HttpMethod.POST, body);
} }
updateCategory(id: string, changes: object): Observable<Category> { updateCategory(id: string, changes: object): Promise<Category> {
return this.http.put<Category>(`${this.apiUrl}/categories/${id}`, changes, this.options); const url = new URL(`/api/categories/${id}`, this.apiUrl)
return this.request(url, HttpMethod.PUT, changes);
} }
deleteCategory(id: string): Observable<void> { deleteCategory(id: string): Promise<void> {
return this.http.delete<void>(`${this.apiUrl}/categories/${id}`, this.options); const url = new URL(`/api/categories/${id}`, this.apiUrl)
return this.request(url, HttpMethod.DELETE);
} }
// Transactions // Transactions

View file

@ -134,31 +134,26 @@ export class TwigsLocalService implements TwigsService {
} }
// Categories // Categories
getCategories(budgetId: string, count?: number): Observable<Category[]> { getCategories(budgetId: string, count?: number): Promise<Category[]> {
return new Observable(subscriber => { return new Promise((resolve, reject) => {
subscriber.next(this.categories.filter(category => { resolve(this.categories.filter(category => {
return category.budgetId === budgetId; return category.budgetId === budgetId;
})); }));
subscriber.complete();
}); });
} }
getCategory(id: string): Observable<Category> { getCategory(id: string): Promise<Category> {
return new Observable(subscriber => { return new Promise((resolve, reject) => {
subscriber.next(this.findById(this.categories, id)); resolve(this.findById(this.categories, id));
subscriber.complete();
}); });
} }
getCategoryBalance(id: string, from?: Date, to?: Date): Observable<number> { getCategoryBalance(id: string, from?: Date, to?: Date): Promise<number> {
return new Observable(emitter => { return Promise.resolve(20);
emitter.next(20);
emitter.complete()
})
} }
createCategory(id: string, budgetId: string, name: string, description: string, amount: number, isExpense: boolean): Observable<Category> { createCategory(id: string, budgetId: string, name: string, description: string, amount: number, isExpense: boolean): Promise<Category> {
return Observable.create(subscriber => { return new Promise((resolve, reject) => {
const category = new Category(); const category = new Category();
category.title = name; category.title = name;
category.description = description; category.description = description;
@ -167,13 +162,12 @@ export class TwigsLocalService implements TwigsService {
category.budgetId = budgetId; category.budgetId = budgetId;
category.id = id; category.id = id;
this.categories.push(category); this.categories.push(category);
subscriber.next(category); resolve(category);
subscriber.complete();
}); });
} }
updateCategory(id: string, changes: object): Observable<Category> { updateCategory(id: string, changes: object): Promise<Category> {
return new Observable(subscriber => { return new Promise((resolve, reject) => {
const category = this.findById(this.categories, id); const category = this.findById(this.categories, id);
if (category) { if (category) {
const index = this.categories.indexOf(category); const index = this.categories.indexOf(category);
@ -188,23 +182,22 @@ export class TwigsLocalService implements TwigsService {
] ]
); );
this.categories[index] = category; this.categories[index] = category;
subscriber.next(category); resolve(category);
} else { } else {
subscriber.error('No category found for given id'); reject('No category found for given id');
} }
subscriber.complete();
}); });
} }
deleteCategory(id: string): Observable<void> { deleteCategory(id: string): Promise<void> {
return new Observable(subscriber => { return new Promise((resolve, reject) => {
const category = this.findById(this.categories, id); const category = this.findById(this.categories, id);
if (category) { if (category) {
const index = this.categories.indexOf(category); const index = this.categories.indexOf(category);
delete this.transactions[index]; delete this.transactions[index];
subscriber.complete(); resolve();
} else { } else {
subscriber.error('No category found for given id'); reject('No category found for given id');
} }
}); });
} }

View file

@ -25,12 +25,12 @@ export interface TwigsService {
deleteBudget(id: string): Promise<void>; deleteBudget(id: string): Promise<void>;
// Categories // Categories
getCategories(budgetId?: string, count?: number): Observable<Category[]>; getCategories(budgetId?: string, count?: number): Promise<Category[]>;
getCategory(id: string): Observable<Category>; getCategory(id: string): Promise<Category>;
getCategoryBalance(id: string, from?: Date, to?: Date): Observable<number>; getCategoryBalance(id: string, from?: Date, to?: Date): Promise<number>;
createCategory(id: string, budgetId: string, name: string, description: string, amount: number, isExpense: boolean): Observable<Category>; createCategory(id: string, budgetId: string, name: string, description: string, amount: number, isExpense: boolean): Promise<Category>;
updateCategory(id: string, changes: object): Observable<Category>; updateCategory(id: string, changes: object): Promise<Category>;
deleteCategory(id: string): Observable<void>; deleteCategory(id: string): Promise<void>;
// Transactions // Transactions
getTransactions( getTransactions(

View file

@ -54,7 +54,7 @@ export class AddEditTransactionComponent implements OnInit, OnChanges {
updateCategories(change: MatRadioChange) { updateCategories(change: MatRadioChange) {
this.twigsService.getCategories(this.budgetId) this.twigsService.getCategories(this.budgetId)
.subscribe(newCategories => { .then(newCategories => {
this.categories = newCategories.filter(category => category.expense === change.value) this.categories = newCategories.filter(category => category.expense === change.value)
}) })
} }