Move actionable buttons from app component to specific components

Signed-off-by: William Brawner <me@wbrawner.com>
This commit is contained in:
William Brawner 2020-02-24 19:34:35 -06:00
parent b73c59deca
commit 3ab5413c43
17 changed files with 48 additions and 82 deletions

View file

@ -1,4 +0,0 @@
export interface Actionable {
doAction(): void;
getActionLabel(): string;
}

View file

@ -1,4 +1,7 @@
<mat-sidenav-container class="sidenav-container">
<p *ngIf="!online" class="error-offline">
You appear to be offline. Twigs unfortunately doesn't currently support offline use at the moment though it may be implemented in a future release!
</p>
<mat-sidenav-container *ngIf="online" class="sidenav-container">
<mat-sidenav #sidenav mode="over" closed>
<mat-nav-list (click)="sidenav.close()">
<a mat-list-item *ngIf="isLoggedIn()" routerLink="">{{ getUsername() }}</a>
@ -21,9 +24,6 @@
<span>
{{ title }}
</span>
<span class="action-item">
<a mat-button *ngIf="actionable" (click)="actionable.doAction()">{{ actionable.getActionLabel() }}</a>
</span>
</mat-toolbar>
<router-outlet></router-outlet>
</mat-sidenav-content>

View file

@ -1,6 +1,5 @@
import { Component, Inject } from '@angular/core';
import { Location } from '@angular/common';
import { Actionable } from './actionable';
import { User } from './users/user';
import { TWIGS_SERVICE, TwigsService } from './shared/twigs.service';
@ -12,8 +11,8 @@ import { TWIGS_SERVICE, TwigsService } from './shared/twigs.service';
export class AppComponent {
public title = 'Twigs';
public backEnabled = false;
public actionable: Actionable;
public user: User;
public online = window.navigator.onLine;
constructor(
@Inject(TWIGS_SERVICE) private twigsService: TwigsService,

View file

@ -14,6 +14,7 @@ import {
MatSelectModule,
MatToolbarModule,
MatSidenavModule,
MatProgressSpinnerModule,
} from '@angular/material';
import { AppComponent } from './app.component';
@ -92,6 +93,7 @@ export const CustomCurrencyMaskConfig: CurrencyMaskConfig = {
MatSelectModule,
MatToolbarModule,
MatSidenavModule,
MatProgressSpinnerModule,
AppRoutingModule,
FormsModule,
ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }),

View file

@ -8,5 +8,6 @@
<mat-form-field>
<textarea matInput [(ngModel)]="budget.description" placeholder="Description"></textarea>
</mat-form-field>
<button mat-button color="accent" (click)="save()">Save</button>
<button class="button-delete" mat-button color="warn" *ngIf="budget.id" (click)="delete()">Delete</button>
</div>

View file

@ -1,7 +1,6 @@
import { Component, OnInit, Input, Inject, OnDestroy } from '@angular/core';
import { Budget } from '../budget';
import { AppComponent } from 'src/app/app.component';
import { Actionable } from 'src/app/actionable';
import { User } from 'src/app/users/user';
import { TWIGS_SERVICE, TwigsService } from 'src/app/shared/twigs.service';
@ -10,7 +9,7 @@ import { TWIGS_SERVICE, TwigsService } from 'src/app/shared/twigs.service';
templateUrl: './add-edit-budget.component.html',
styleUrls: ['./add-edit-budget.component.css']
})
export class AddEditBudgetComponent implements OnInit, OnDestroy, Actionable {
export class AddEditBudgetComponent {
@Input() title: string;
@Input() budget: Budget;
public userIds: number[];
@ -22,18 +21,10 @@ export class AddEditBudgetComponent implements OnInit, OnDestroy, Actionable {
) {
this.app.title = this.title;
this.app.backEnabled = true;
this.app.actionable = this;
this.userIds = [this.app.user.id];
}
ngOnInit() {
}
ngOnDestroy(): void {
this.app.actionable = null;
}
doAction(): void {
save(): void {
let observable;
if (this.budget.id) {
// This is an existing transaction, update it
@ -52,10 +43,6 @@ export class AddEditBudgetComponent implements OnInit, OnDestroy, Actionable {
});
}
getActionLabel(): string {
return 'Save';
}
delete(): void {
this.twigsService.deleteBudget(this.budget.id);
this.app.goBack();

View file

@ -1,4 +1,5 @@
<div class="dashboard" *ngIf="!isLoggedIn()">
<mat-progress-spinner *ngIf="loading" diameter="50" mode="indeterminate"></mat-progress-spinner>
<div class="dashboard" *ngIf="!loading && !isLoggedIn()">
<h2 class="log-in">Welcome to Twigs!</h2>
<p>To begin tracking your finances, login or create an account!</p>
<div class="auth-button-container">
@ -6,7 +7,7 @@
<a routerLink="/login" mat-raised-button color="accent">Login</a>
</div>
</div>
<mat-nav-list class="budgets" *ngIf="isLoggedIn()">
<mat-nav-list class="budgets" *ngIf="!loading && isLoggedIn()">
<a mat-list-item *ngFor="let budget of budgets" routerLink="/budgets/{{ budget.id }}">
<p matLine class="budget-list-title">
{{ budget.name }}
@ -16,12 +17,12 @@
</p>
</a>
</mat-nav-list>
<div class="no-budgets" *ngIf="isLoggedIn() && (!budgets || budgets.length === 0)">
<div class="no-budgets" *ngIf="!loading && isLoggedIn() && (!budgets || budgets.length === 0)">
<a mat-button routerLink="/budgets/new">
<mat-icon>add</mat-icon>
<p>Add budgets to begin tracking your finances.</p>
</a>
</div>
<a mat-fab routerLink="/budgets/new" *ngIf="isLoggedIn()">
<a mat-fab routerLink="/budgets/new" *ngIf="!loading && isLoggedIn()">
<mat-icon aria-label="Add">add</mat-icon>
</a>

View file

@ -12,6 +12,7 @@ export class BudgetsComponent implements OnInit {
@Input() budgetId: string;
public budgets: Budget[];
public loading = true;
constructor(
private app: AppComponent,
@ -21,9 +22,15 @@ export class BudgetsComponent implements OnInit {
ngOnInit() {
this.app.backEnabled = this.isLoggedIn();
this.app.title = 'Budgets';
this.twigsService.getBudgets().subscribe(budgets => {
this.budgets = budgets;
});
this.twigsService.getBudgets().subscribe(
budgets => {
this.budgets = budgets;
this.loading = false;
},
error => {
this.loading = false;
}
);
}
isLoggedIn(): boolean {

View file

@ -17,5 +17,6 @@
<input type="color" matInput [(ngModel)]="currentCategory.color" placeholder="Color">
</mat-form-field>
-->
<button mat-button color="accent" (click)="save()">Save</button>
<button class="button-delete" mat-button color="warn" *ngIf="currentCategory.id" (click)="delete()">Delete</button>
</div>

View file

@ -1,6 +1,5 @@
import { Component, OnInit, Input, OnDestroy, Inject } from '@angular/core';
import { Category } from '../category';
import { Actionable } from 'src/app/actionable';
import { AppComponent } from 'src/app/app.component';
import { TWIGS_SERVICE, TwigsService } from 'src/app/shared/twigs.service';
@ -9,7 +8,7 @@ import { TWIGS_SERVICE, TwigsService } from 'src/app/shared/twigs.service';
templateUrl: './add-edit-category.component.html',
styleUrls: ['./add-edit-category.component.css']
})
export class AddEditCategoryComponent implements OnInit, Actionable, OnDestroy {
export class AddEditCategoryComponent implements OnInit {
@Input() budgetId: number;
@Input() title: string;
@ -21,16 +20,11 @@ export class AddEditCategoryComponent implements OnInit, Actionable, OnDestroy {
) { }
ngOnInit() {
this.app.actionable = this;
this.app.backEnabled = true;
this.app.title = this.title;
}
ngOnDestroy() {
this.app.actionable = null;
}
doAction(): void {
save(): void {
let observable;
if (this.currentCategory.id) {
// This is an existing category, update it
@ -57,10 +51,6 @@ export class AddEditCategoryComponent implements OnInit, Actionable, OnDestroy {
});
}
getActionLabel(): string {
return 'Save';
}
delete(): void {
this.twigsService.deleteCategory(this.budgetId, this.currentCategory.id).subscribe(() => {
this.app.goBack();

View file

@ -28,5 +28,6 @@
<mat-radio-button [value]="true">Expense</mat-radio-button>
<mat-radio-button [value]="false">Income</mat-radio-button>
</mat-radio-group>
<button mat-button color="accent" (click)="save()">Save</button>
<button class="button-delete" mat-button color="warn" *ngIf="currentTransaction.id" (click)="delete()">Delete</button>
</div>

View file

@ -2,7 +2,6 @@ import { Component, OnInit, Input, OnChanges, OnDestroy, Inject, SimpleChanges }
import { Transaction } from '../transaction';
import { TransactionType } from '../transaction.type';
import { Category } from 'src/app/categories/category';
import { Actionable } from 'src/app/actionable';
import { AppComponent } from 'src/app/app.component';
import { TWIGS_SERVICE, TwigsService } from 'src/app/shared/twigs.service';
@ -11,7 +10,7 @@ import { TWIGS_SERVICE, TwigsService } from 'src/app/shared/twigs.service';
templateUrl: './add-edit-transaction.component.html',
styleUrls: ['./add-edit-transaction.component.css']
})
export class AddEditTransactionComponent implements OnInit, OnChanges, OnDestroy, Actionable {
export class AddEditTransactionComponent implements OnInit, OnChanges {
@Input() title: string;
@Input() currentTransaction: Transaction;
@Input() budgetId: number;
@ -29,7 +28,6 @@ export class AddEditTransactionComponent implements OnInit, OnChanges, OnDestroy
ngOnInit() {
this.app.title = this.title;
this.app.backEnabled = true;
this.app.actionable = this;
this.getCategories();
let d: Date;
if (this.currentTransaction) {
@ -51,11 +49,7 @@ export class AddEditTransactionComponent implements OnInit, OnChanges, OnDestroy
this.currentTime = `${d.getHours()}:${d.getMinutes()}`;
}
ngOnDestroy() {
this.app.actionable = null;
}
doAction(): void {
save(): void {
// The amount will be input as a decimal value so we need to convert it
// to an integer
let observable;
@ -98,10 +92,6 @@ export class AddEditTransactionComponent implements OnInit, OnChanges, OnDestroy
});
}
getActionLabel(): string {
return 'Save';
}
delete(): void {
this.twigsService.deleteTransaction(this.budgetId, this.currentTransaction.id).subscribe(() => {
this.app.goBack();

View file

@ -5,4 +5,5 @@
<mat-form-field>
<input matInput type="password" placeholder="Password" [(ngModel)]="password" (keyup.enter)="doAction()"/>
</mat-form-field>
<button mat-raised-button color="accent" (click)="login()">Login</button>
</div>

View file

@ -1,7 +1,6 @@
import { Component, OnInit, OnDestroy, Inject, ChangeDetectorRef } from '@angular/core';
import { TwigsService, TWIGS_SERVICE } from '../../shared/twigs.service';
import { User } from '../user';
import { Actionable } from 'src/app/actionable';
import { AppComponent } from 'src/app/app.component';
import { Router } from '@angular/router';
@ -10,7 +9,7 @@ import { Router } from '@angular/router';
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit, OnDestroy, Actionable {
export class LoginComponent implements OnInit {
public email: string;
public password: string;
@ -23,15 +22,10 @@ export class LoginComponent implements OnInit, OnDestroy, Actionable {
ngOnInit() {
this.app.title = 'Login';
this.app.actionable = this;
this.app.backEnabled = true;
}
ngOnDestroy() {
this.app.actionable = null;
}
doAction(): void {
login(): void {
this.twigsService.login(this.email, this.password)
.subscribe(user => {
this.app.user = user;
@ -42,8 +36,4 @@ export class LoginComponent implements OnInit, OnDestroy, Actionable {
alert("Login failed. Please verify you have the correct credentials");
})
}
getActionLabel() {
return 'Submit';
}
}

View file

@ -1,4 +1,5 @@
<div class="form register-form">
<mat-progress-spinner *ngIf="isLoading" mode="indeterminate" diameter="50"></mat-progress-spinner>
<div *ngIf="!isLoading" class="form register-form">
<mat-form-field>
<input matInput placeholder="Username" [(ngModel)]="username" />
</mat-form-field>
@ -11,4 +12,5 @@
<mat-form-field>
<input matInput type="password" placeholder="Confirm Password" [(ngModel)]="confirmedPassword" />
</mat-form-field>
</div>
<button mat-raised-button color="accent" (click)="register()">Register</button>
</div>

View file

@ -1,6 +1,5 @@
import { Component, OnInit, OnDestroy, Inject } from '@angular/core';
import { TwigsService, TWIGS_SERVICE } from '../../shared/twigs.service';
import { Actionable } from 'src/app/actionable';
import { AppComponent } from 'src/app/app.component';
import { Router } from '@angular/router';
@ -9,12 +8,13 @@ import { Router } from '@angular/router';
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent implements OnInit, OnDestroy, Actionable {
export class RegisterComponent implements OnInit {
public username: string;
public email: string;
public password: string;
public confirmedPassword: string;
public isLoading = false;
constructor(
private app: AppComponent,
@ -24,29 +24,22 @@ export class RegisterComponent implements OnInit, OnDestroy, Actionable {
ngOnInit() {
this.app.title = 'Register';
this.app.actionable = this;
this.app.backEnabled = true;
}
ngOnDestroy() {
this.app.actionable = null;
}
doAction(): void {
register(): void {
if (this.password !== this.confirmedPassword) {
alert('Passwords don\'t match');
return;
}
this.isLoading = true;
this.twigsService.register(this.username, this.email, this.password).subscribe(user => {
console.log(user);
this.router.navigate(['/'])
}, error => {
console.error(error);
alert("Registration failed!")
this.isLoading = false;
})
}
getActionLabel() {
return 'Submit';
}
}

View file

@ -94,6 +94,11 @@ mat-sidenav {
min-width: 300px;
}
.mat-progress-spinner {
top: 5em;
left: calc(50% - 25px);
}
.income {
color: #81C784;
}