Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 30 additions & 4 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"builder": "@angular/build:application",
"options": {
"outputPath": "dist/public",
"index": "client/index.html",
Expand Down Expand Up @@ -62,7 +62,7 @@
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"builder": "@angular/build:dev-server",
"configurations": {
"production": {
"buildTarget": "angular2-full-stack:build:production"
Expand All @@ -75,10 +75,10 @@
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n"
"builder": "@angular/build:extract-i18n"
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"builder": "@angular/build:karma",
"options": {
"polyfills": [
"zone.js",
Expand Down Expand Up @@ -116,5 +116,31 @@
"schematicCollections": [
"angular-eslint"
]
},
"schematics": {
"@schematics/angular:component": {
"type": "component"
},
"@schematics/angular:directive": {
"type": "directive"
},
"@schematics/angular:service": {
"type": "service"
},
"@schematics/angular:guard": {
"typeSeparator": "."
},
"@schematics/angular:interceptor": {
"typeSeparator": "."
},
"@schematics/angular:module": {
"typeSeparator": "."
},
"@schematics/angular:pipe": {
"typeSeparator": "."
},
"@schematics/angular:resolver": {
"typeSeparator": "."
}
}
}
68 changes: 35 additions & 33 deletions client/app/account/account.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,39 @@

<app-toast [message]="toast.message"></app-toast>

<div class="card" *ngIf="!isLoading">
<h4 class="card-header">Account settings</h4>
<div class="card-body">
<form #accountForm="ngForm" (ngSubmit)="save(user)">
<div class="input-group">
<span class="input-group-text">
<i class="fa fa-user"></i>
</span>
<input class="form-control" type="text" name="username"
[(ngModel)]="user.username" placeholder="Username" required>
</div>
<div class="input-group">
<span class="input-group-text">
<i class="fa fa-envelope"></i>
</span>
<input class="form-control" type="email" name="email"
[(ngModel)]="user.email" placeholder="Email" required>
</div>
<div class="input-group">
<span class="input-group-text">
<i class="fa fa-black-tie"></i>
</span>
<select class="form-control" name="role" [(ngModel)]="user.role">
<option value="" disabled>Role</option>
<option value="user">User</option>
<option value="admin">Admin</option>
</select>
</div>
<button class="btn btn-primary" type="submit" [disabled]="!accountForm.form.valid">
<i class="fa fa-save"></i> Save
</button>
</form>
@if (!isLoading) {
<div class="card">
<h4 class="card-header">Account settings</h4>
<div class="card-body">
<form #accountForm="ngForm" (ngSubmit)="save(user)">
<div class="input-group">
<span class="input-group-text">
<i class="fa fa-user"></i>
</span>
<input class="form-control" type="text" name="username"
[(ngModel)]="user.username" placeholder="Username" required>
</div>
<div class="input-group">
<span class="input-group-text">
<i class="fa fa-envelope"></i>
</span>
<input class="form-control" type="email" name="email"
[(ngModel)]="user.email" placeholder="Email" required>
</div>
<div class="input-group">
<span class="input-group-text">
<i class="fa fa-black-tie"></i>
</span>
<select class="form-control" name="role" [(ngModel)]="user.role">
<option value="" disabled>Role</option>
<option value="user">User</option>
<option value="admin">Admin</option>
</select>
</div>
<button class="btn btn-primary" type="submit" [disabled]="!accountForm.form.valid">
<i class="fa fa-save"></i> Save
</button>
</form>
</div>
</div>
</div>
}
10 changes: 5 additions & 5 deletions client/app/account/account.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { ToastComponent } from '../shared/toast/toast.component';
import { AuthService } from '../services/auth.service';
import { UserService } from '../services/user.service';
Expand All @@ -10,14 +10,14 @@ import { User } from '../shared/models/user.model';
standalone: false
})
export class AccountComponent implements OnInit {
private auth = inject(AuthService);
toast = inject(ToastComponent);
private userService = inject(UserService);


user: User = new User();
isLoading = true;

constructor(private auth: AuthService,
public toast: ToastComponent,
private userService: UserService) { }

ngOnInit(): void {
this.getUser();
}
Expand Down
10 changes: 6 additions & 4 deletions client/app/add-cat-form/add-cat-form.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, Input } from '@angular/core';
import { Component, Input, inject } from '@angular/core';
import { UntypedFormGroup, UntypedFormControl, Validators, UntypedFormBuilder } from '@angular/forms';
import { CatService } from '../services/cat.service';
import { ToastComponent } from '../shared/toast/toast.component';
Expand All @@ -12,16 +12,18 @@ import { Cat } from '../shared/models/cat.model';
})

export class AddCatFormComponent {
private catService = inject(CatService);
private formBuilder = inject(UntypedFormBuilder);
toast = inject(ToastComponent);

@Input() cats: Cat[] = [];

addCatForm: UntypedFormGroup;
name = new UntypedFormControl('', Validators.required);
age = new UntypedFormControl('', Validators.required);
weight = new UntypedFormControl('', Validators.required);

constructor(private catService: CatService,
private formBuilder: UntypedFormBuilder,
public toast: ToastComponent) {
constructor() {
this.addCatForm = this.formBuilder.group({
name: this.name,
age: this.age,
Expand Down
70 changes: 38 additions & 32 deletions client/app/admin/admin.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,42 @@

<app-toast [message]="toast.message"></app-toast>

<div class="card" *ngIf="!isLoading">
<h4 class="card-header">Registered users ({{users.length}})</h4>
<div class="card-body">
<table class="table table-bordered">
<thead class="table-secondary">
<tr>
<th scope="col">Username</th>
<th scope="col">Email</th>
<th scope="col">Role</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody *ngIf="users.length === 0">
<tr>
<td colspan="4">There are no registered users.</td>
</tr>
</tbody>
<tbody>
<tr *ngFor="let user of users">
<td>{{user.username}}</td>
<td>{{user.email}}</td>
<td>{{user.role}}</td>
<td>
<button class="btn btn-sm btn-danger" (click)="deleteUser(user)"
[disabled]="auth.currentUser._id === user._id">
<i class="fa fa-trash"></i> Delete
</button>
</td>
</tr>
</tbody>
</table>
@if (!isLoading) {
<div class="card">
<h4 class="card-header">Registered users ({{users.length}})</h4>
<div class="card-body">
<table class="table table-bordered">
<thead class="table-secondary">
<tr>
<th scope="col">Username</th>
<th scope="col">Email</th>
<th scope="col">Role</th>
<th scope="col">Actions</th>
</tr>
</thead>
@if (users.length === 0) {
<tbody>
<tr>
<td colspan="4">There are no registered users.</td>
</tr>
</tbody>
}
<tbody>
@for (user of users; track user) {
<tr>
<td>{{user.username}}</td>
<td>{{user.email}}</td>
<td>{{user.role}}</td>
<td>
<button class="btn btn-sm btn-danger" (click)="deleteUser(user)"
[disabled]="auth.currentUser._id === user._id">
<i class="fa fa-trash"></i> Delete
</button>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
}
10 changes: 5 additions & 5 deletions client/app/admin/admin.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';

import { ToastComponent } from '../shared/toast/toast.component';
import { AuthService } from '../services/auth.service';
Expand All @@ -11,14 +11,14 @@ import { User } from '../shared/models/user.model';
standalone: false
})
export class AdminComponent implements OnInit {
auth = inject(AuthService);
toast = inject(ToastComponent);
private userService = inject(UserService);


users: User[] = [];
isLoading = true;

constructor(public auth: AuthService,
public toast: ToastComponent,
private userService: UserService) { }

ngOnInit(): void {
this.getUsers();
}
Expand Down
44 changes: 27 additions & 17 deletions client/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<button class="navbar-toggler" type="button"
data-bs-toggle="collapse" data-bs-target="#navbar-supported-content"
aria-controls="navbar-supported-content" aria-expanded="false" aria-label="Toggle navigation">
data-bs-toggle="collapse" data-bs-target="#navbar-supported-content"
aria-controls="navbar-supported-content" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar-supported-content">
Expand All @@ -19,29 +19,39 @@
</a>
</li>
<li class="nav-item">
<a routerLink="/login" class="nav-link" routerLinkActive="active" *ngIf="!auth.loggedIn">
<i class="fa fa-sign-in"></i> Login
</a>
@if (!auth.loggedIn) {
<a routerLink="/login" class="nav-link" routerLinkActive="active">
<i class="fa fa-sign-in"></i> Login
</a>
}
</li>
<li class="nav-item">
<a routerLink="/register" class="nav-link" routerLinkActive="active" *ngIf="!auth.loggedIn">
<i class="fa fa-user-plus"></i> Register
</a>
@if (!auth.loggedIn) {
<a routerLink="/register" class="nav-link" routerLinkActive="active">
<i class="fa fa-user-plus"></i> Register
</a>
}
</li>
<li class="nav-item">
<a routerLink="/account" class="nav-link" routerLinkActive="active" *ngIf="auth.loggedIn">
<i class="fa fa-user"></i> Account ({{auth.currentUser.username}})
</a>
@if (auth.loggedIn) {
<a routerLink="/account" class="nav-link" routerLinkActive="active">
<i class="fa fa-user"></i> Account ({{auth.currentUser.username}})
</a>
}
</li>
<li class="nav-item">
<a routerLink="/admin" class="nav-link" routerLinkActive="active" *ngIf="auth.loggedIn && auth.isAdmin">
<i class="fa fa-lock"></i> Admin
</a>
@if (auth.loggedIn && auth.isAdmin) {
<a routerLink="/admin" class="nav-link" routerLinkActive="active">
<i class="fa fa-lock"></i> Admin
</a>
}
</li>
<li class="nav-item">
<a routerLink="/logout" class="nav-link" routerLinkActive="active" *ngIf="auth.loggedIn">
<i class="fa fa-sign-out"></i> Logout
</a>
@if (auth.loggedIn) {
<a routerLink="/logout" class="nav-link" routerLinkActive="active">
<i class="fa fa-sign-out"></i> Logout
</a>
}
</li>
</ul>
</div>
Expand Down
6 changes: 3 additions & 3 deletions client/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AfterViewChecked, ChangeDetectorRef, Component } from '@angular/core';
import { AfterViewChecked, ChangeDetectorRef, Component, inject } from '@angular/core';
import { AuthService } from './services/auth.service';

@Component({
Expand All @@ -7,9 +7,9 @@ import { AuthService } from './services/auth.service';
standalone: false
})
export class AppComponent implements AfterViewChecked {
auth = inject(AuthService);
private changeDetector = inject(ChangeDetectorRef);

constructor(public auth: AuthService,
private changeDetector: ChangeDetectorRef) { }

// This fixes: https://github.com/DavideViolante/Angular-Full-Stack/issues/105
ngAfterViewChecked(): void {
Expand Down
Loading