From 6cc063f776bea56a1d20b85a5b9e0646d1936827 Mon Sep 17 00:00:00 2001 From: William Brawner Date: Thu, 10 Nov 2022 21:01:12 -0700 Subject: [PATCH] Migrate transactions backend calls to promise api --- .../budget-details.component.ts | 2 +- src/app/categories/categories.component.ts | 36 +++++----- .../category-form/category-form.component.ts | 14 ++-- src/app/shared/twigs.http.service.ts | 67 ++++++++++--------- src/app/shared/twigs.local.service.ts | 41 +++++------- src/app/shared/twigs.service.ts | 13 ++-- .../add-edit-transaction.component.ts | 23 +++---- .../transaction-details.component.ts | 2 +- .../transaction-list.component.ts | 3 +- 9 files changed, 95 insertions(+), 106 deletions(-) diff --git a/src/app/budgets/budget-details/budget-details.component.ts b/src/app/budgets/budget-details/budget-details.component.ts index 91ed695..48a6566 100644 --- a/src/app/budgets/budget-details/budget-details.component.ts +++ b/src/app/budgets/budget-details/budget-details.component.ts @@ -126,7 +126,7 @@ export class BudgetDetailsComponent implements OnInit, OnDestroy, Actionable { date.setMilliseconds(0); date.setDate(1); this.twigsService.getTransactions(this.budget.id, null, 5, date) - .subscribe(transactions => this.transactions = transactions); + .then(transactions => this.transactions = transactions); } async getCategories() { diff --git a/src/app/categories/categories.component.ts b/src/app/categories/categories.component.ts index 3cced26..2c120bc 100644 --- a/src/app/categories/categories.component.ts +++ b/src/app/categories/categories.component.ts @@ -1,11 +1,9 @@ -import { Component, OnInit, Input, Inject } from '@angular/core'; +import { Component, OnInit, Inject } from '@angular/core'; import { Category } from './category'; import { AppComponent } from '../app.component'; -import { Observable } from 'rxjs'; -import { TransactionType } from '../transactions/transaction.type'; -import { Budget } from '../budgets/budget'; import { ActivatedRoute } from '@angular/router'; import { TWIGS_SERVICE, TwigsService } from '../shared/twigs.service'; +import { Transaction } from '../transactions/transaction'; @Component({ selector: 'app-categories', @@ -36,24 +34,28 @@ export class CategoriesComponent implements OnInit { this.twigsService.getCategories(this.budgetId).then(categories => { this.categories = categories; for (const category of this.categories) { - this.getCategoryBalance(category).subscribe(balance => this.categoryBalances.set(category.id, balance)); + this.getCategoryBalance(category).then(balance => this.categoryBalances.set(category.id, balance)); } }); } - getCategoryBalance(category: Category): Observable { - return Observable.create(subscriber => { - this.twigsService.getTransactions(this.budgetId, category.id).subscribe(transactions => { - let balance = 0; - for (const transaction of transactions) { - if (transaction.expense) { - balance -= transaction.amount; - } else { - balance += transaction.amount; - } + getCategoryBalance(category: Category): Promise { + return new Promise(async (resolve, reject) => { + let transactions: Transaction[] + try { + transactions = await this.twigsService.getTransactions(this.budgetId, category.id) + } catch(e) { + reject(e) + } + let balance = 0; + for (const transaction of transactions) { + if (transaction.expense) { + balance -= transaction.amount; + } else { + balance += transaction.amount; } - subscriber.next(balance); - }); + } + resolve(balance); }); } } diff --git a/src/app/categories/category-form/category-form.component.ts b/src/app/categories/category-form/category-form.component.ts index 336ae0d..f6ebd8b 100644 --- a/src/app/categories/category-form/category-form.component.ts +++ b/src/app/categories/category-form/category-form.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, Input, OnDestroy, Inject } from '@angular/core'; +import { Component, OnInit, Input, Inject } from '@angular/core'; import { Category } from '../category'; import { AppComponent } from 'src/app/app.component'; import { TWIGS_SERVICE, TwigsService } from 'src/app/shared/twigs.service'; @@ -39,15 +39,13 @@ export class CategoryFormComponent implements OnInit { ); } else { // This is an existing category, update it + const updatedCategory: Category = { + ...this.currentCategory, + amount: this.currentCategory.amount * 100 + } promise = this.twigsService.updateCategory( this.currentCategory.id, - { - name: this.currentCategory.title, - description: this.currentCategory.description, - amount: this.currentCategory.amount * 100, - expense: this.currentCategory.expense, - archived: this.currentCategory.archived - } + this.currentCategory ); } promise.then(_ => { diff --git a/src/app/shared/twigs.http.service.ts b/src/app/shared/twigs.http.service.ts index d118cd6..fc74d06 100644 --- a/src/app/shared/twigs.http.service.ts +++ b/src/app/shared/twigs.http.service.ts @@ -1,13 +1,10 @@ import { Injectable } from '@angular/core'; -import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http'; -import { BehaviorSubject, Observable, pipe, Subscriber } from 'rxjs'; import { User, UserPermission, Permission, AuthToken } from '../users/user'; import { TwigsService } from './twigs.service'; import { Budget } from '../budgets/budget'; import { Category } from '../categories/category'; import { Transaction } from '../transactions/transaction'; import { environment } from '../../environments/environment'; -import { map } from 'rxjs/operators'; @Injectable({ providedIn: 'root' @@ -20,7 +17,6 @@ export class TwigsHttpService implements TwigsService { private apiUrl = environment.apiUrl; constructor( - private http: HttpClient, private storage: Storage ) { } @@ -175,45 +171,41 @@ export class TwigsHttpService implements TwigsService { } // Transactions - getTransactions( + async getTransactions( budgetId?: string, categoryId?: string, count?: number, from?: Date, to?: Date - ): Observable { - let httpParams = new HttpParams(); + ): Promise { + const url = new URL(`/api/transactions`, this.apiUrl) if (budgetId) { - httpParams = httpParams.set('budgetIds', `${budgetId}`); + url.searchParams.set('budgetIds', budgetId); } if (categoryId) { - httpParams = httpParams.set('categoryIds', `${categoryId}`); + url.searchParams.set('categoryIds', categoryId); } if (from) { - httpParams = httpParams.set('from', from.toISOString()); + url.searchParams.set('from', from.toISOString()); } if (to) { - httpParams = httpParams.set('to', to.toISOString()); + url.searchParams.set('to', to.toISOString()); } - const params = { params: httpParams }; - return this.http.get(`${this.apiUrl}/transactions`, Object.assign(params, this.options)) - .pipe(map(transactions => { - transactions.forEach(transaction => { - transaction.date = new Date(transaction.date); - }); - return transactions; - })); + const transactions: Transaction[] = await this.request(url, HttpMethod.GET) + transactions.forEach(transaction => { + transaction.date = new Date(transaction.date); + }) + return transactions } - getTransaction(id: string): Observable { - return this.http.get(`${this.apiUrl}/transactions/${id}`, this.options) - .pipe(map(transaction => { - transaction.date = new Date(transaction.date); - return transaction; - })); + async getTransaction(id: string): Promise { + const url = new URL(`/api/transactions/${id}`, this.apiUrl) + const transaction: Transaction = await this.request(url, HttpMethod.GET) + transaction.date = new Date(transaction.date) + return transaction } - createTransaction( + async createTransaction( id: string, budgetId: string, name: string, @@ -222,8 +214,9 @@ export class TwigsHttpService implements TwigsService { date: Date, expense: boolean, category: string - ): Observable { - const params = { + ): Promise { + const url = new URL(`/api/transactions`, this.apiUrl) + const body = { 'id': id, 'title': name, 'description': description, @@ -233,15 +226,23 @@ export class TwigsHttpService implements TwigsService { 'categoryId': category, 'budgetId': budgetId }; - return this.http.post(this.apiUrl + '/transactions', params, this.options); + const transaction: Transaction = await this.request(url, HttpMethod.POST, body) + transaction.date = new Date(transaction.date) + return transaction } - updateTransaction(id: string, changes: object): Observable { - return this.http.put(`${this.apiUrl}/transactions/${id}`, changes, this.options); + async updateTransaction(id: string, transaction: Transaction): Promise { + const body: any = transaction; + body.date = transaction.date.toISOString() + const url = new URL(`/api/transactions/${id}`, this.apiUrl) + const updatedTransaction: Transaction = await this.request(url, HttpMethod.PUT, body) + updatedTransaction.date = new Date(updatedTransaction.date) + return updatedTransaction } - deleteTransaction(id: string): Observable { - return this.http.delete(`${this.apiUrl}/transactions/${id}`, this.options); + deleteTransaction(id: string): Promise { + const url = new URL(`/api/transactions/${id}`, this.apiUrl) + return this.request(url, HttpMethod.DELETE) } // Users diff --git a/src/app/shared/twigs.local.service.ts b/src/app/shared/twigs.local.service.ts index c0f632a..89db219 100644 --- a/src/app/shared/twigs.local.service.ts +++ b/src/app/shared/twigs.local.service.ts @@ -1,6 +1,4 @@ import { Injectable } from '@angular/core'; -import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http'; -import { Observable, Subscriber } from 'rxjs'; import { User, UserPermission } from '../users/user'; import { TwigsService } from './twigs.service'; import { Budget } from '../budgets/budget'; @@ -18,7 +16,6 @@ import { randomId } from '../shared/utils'; export class TwigsLocalService implements TwigsService { constructor( - private http: HttpClient ) { } private users: User[] = [new User(randomId(), 'test', 'test@example.com')]; @@ -203,9 +200,9 @@ export class TwigsLocalService implements TwigsService { } // Transactions - getTransactions(budgetId?: string, categoryId?: string, count?: number): Observable { - return new Observable(subscriber => { - subscriber.next(this.transactions.filter(transaction => { + getTransactions(budgetId?: string, categoryId?: string, count?: number): Promise { + return new Promise((resolve, reject) => { + resolve(this.transactions.filter(transaction => { let include = true; if (budgetId) { include = transaction.budgetId === budgetId; @@ -215,15 +212,11 @@ export class TwigsLocalService implements TwigsService { } return include; })); - subscriber.complete(); }); } - getTransaction(id: string): Observable { - return new Observable(subscriber => { - subscriber.next(this.findById(this.transactions, id)); - subscriber.complete(); - }); + getTransaction(id: string): Promise { + return Promise.resolve(this.findById(this.transactions, id)); } createTransaction( @@ -235,8 +228,8 @@ export class TwigsLocalService implements TwigsService { date: Date, isExpense: boolean, category: string - ): Observable { - return new Observable(subscriber => { + ): Promise { + return new Promise((resolve, reject) => { const transaction = new Transaction(); transaction.title = name; transaction.description = description; @@ -247,13 +240,12 @@ export class TwigsLocalService implements TwigsService { transaction.budgetId = budgetId; transaction.id = randomId(); this.transactions.push(transaction); - subscriber.next(transaction); - subscriber.complete(); + resolve(transaction); }); } - updateTransaction(id: string, changes: object): Observable { - return new Observable(subscriber => { + updateTransaction(id: string, changes: object): Promise { + return new Promise((resolve, reject) => { const transaction = this.findById(this.transactions, id); if (transaction) { const index = this.transactions.indexOf(transaction); @@ -272,23 +264,22 @@ export class TwigsLocalService implements TwigsService { ] ); this.transactions[index] = transaction; - subscriber.next(transaction); + resolve(transaction); } else { - subscriber.error('No transaction found for given id'); + reject('No transaction found for given id'); } - subscriber.complete(); }); } - deleteTransaction(id: string): Observable { - return new Observable(subscriber => { + deleteTransaction(id: string): Promise { + return new Promise((resolve, reject) => { const transaction = this.findById(this.transactions, id); if (transaction) { const index = this.transactions.indexOf(transaction); delete this.transactions[index]; - subscriber.complete(); + resolve(); } else { - subscriber.error('No transaction found for given id'); + reject('No transaction found for given id'); } }); } diff --git a/src/app/shared/twigs.service.ts b/src/app/shared/twigs.service.ts index 4b4fb91..a88e830 100644 --- a/src/app/shared/twigs.service.ts +++ b/src/app/shared/twigs.service.ts @@ -1,5 +1,4 @@ import { InjectionToken } from '@angular/core'; -import { Observable } from 'rxjs'; import { User, UserPermission } from '../users/user'; import { Budget } from '../budgets/budget'; import { Category } from '../categories/category'; @@ -29,7 +28,7 @@ export interface TwigsService { getCategory(id: string): Promise; getCategoryBalance(id: string, from?: Date, to?: Date): Promise; createCategory(id: string, budgetId: string, name: string, description: string, amount: number, isExpense: boolean): Promise; - updateCategory(id: string, changes: object): Promise; + updateCategory(id: string, category: Category): Promise; deleteCategory(id: string): Promise; // Transactions @@ -39,8 +38,8 @@ export interface TwigsService { count?: number, from?: Date, to?: Date - ): Observable; - getTransaction(id: string): Observable; + ): Promise; + getTransaction(id: string): Promise; createTransaction( id: string, budgetId: string, @@ -50,9 +49,9 @@ export interface TwigsService { date: Date, isExpense: boolean, category: string - ): Observable; - updateTransaction(id: string, changes: object): Observable; - deleteTransaction(id: string): Observable; + ): Promise; + updateTransaction(id: string, transaction: Transaction): Promise; + deleteTransaction(id: string): Promise; getProfile(id: string): Promise; getUsersByUsername(username: string): Promise; diff --git a/src/app/transactions/add-edit-transaction/add-edit-transaction.component.ts b/src/app/transactions/add-edit-transaction/add-edit-transaction.component.ts index 67a8ee9..93282b2 100644 --- a/src/app/transactions/add-edit-transaction/add-edit-transaction.component.ts +++ b/src/app/transactions/add-edit-transaction/add-edit-transaction.component.ts @@ -62,7 +62,7 @@ export class AddEditTransactionComponent implements OnInit, OnChanges { save(): void { // The amount will be input as a decimal value so we need to convert it // to an integer - let observable; + let promise; this.currentTransaction.date = new Date(); const dateParts = this.transactionDate.split('-'); this.currentTransaction.date.setFullYear(parseInt(dateParts[0], 10)); @@ -73,7 +73,7 @@ export class AddEditTransactionComponent implements OnInit, OnChanges { this.currentTransaction.date.setMinutes(parseInt(timeParts[1], 10)); if (this.create) { // This is a new transaction, save it - observable = this.twigsService.createTransaction( + promise = this.twigsService.createTransaction( this.currentTransaction.id, this.budgetId, this.currentTransaction.title, @@ -85,26 +85,23 @@ export class AddEditTransactionComponent implements OnInit, OnChanges { ); } else { // This is an existing transaction, update it - observable = this.twigsService.updateTransaction( + const updatedTransaction: Transaction = { + ...this.currentTransaction, + amount: Math.round(this.currentTransaction.amount * 100) + } + promise = this.twigsService.updateTransaction( this.currentTransaction.id, - { - title: this.currentTransaction.title, - description: this.currentTransaction.description, - amount: Math.round(this.currentTransaction.amount * 100), - date: this.currentTransaction.date, - categoryId: this.currentTransaction.categoryId, - expense: this.currentTransaction.expense - } + updatedTransaction ); } - observable.subscribe(val => { + promise.then(() => { this.app.goBack(); }); } delete(): void { - this.twigsService.deleteTransaction(this.currentTransaction.id).subscribe(() => { + this.twigsService.deleteTransaction(this.currentTransaction.id).then(() => { this.app.goBack(); }); } diff --git a/src/app/transactions/transaction-details/transaction-details.component.ts b/src/app/transactions/transaction-details/transaction-details.component.ts index cb69186..7d8c488 100644 --- a/src/app/transactions/transaction-details/transaction-details.component.ts +++ b/src/app/transactions/transaction-details/transaction-details.component.ts @@ -25,7 +25,7 @@ export class TransactionDetailsComponent implements OnInit { getTransaction(): void { const id = this.route.snapshot.paramMap.get('id'); this.twigsService.getTransaction(id) - .subscribe(transaction => { + .then(transaction => { transaction.amount /= 100; this.transaction = transaction; this.budgetId = transaction.budgetId; diff --git a/src/app/transactions/transaction-list/transaction-list.component.ts b/src/app/transactions/transaction-list/transaction-list.component.ts index 11fc365..261b19d 100644 --- a/src/app/transactions/transaction-list/transaction-list.component.ts +++ b/src/app/transactions/transaction-list/transaction-list.component.ts @@ -52,7 +52,8 @@ export class TransactionListComponent implements OnInit { } } - this.twigsService.getTransactions(this.budgetIds.join(','), this.categoryIds?.join(','), null, from, to).subscribe(transactions => { + this.twigsService.getTransactions(this.budgetIds.join(','), this.categoryIds?.join(','), null, from, to) + .then(transactions => { this.transactions = transactions; }); }