Skip to content

Commit a3befe1

Browse files
chore: upgrade to Angular v20 + deps (#292)
* chore(deps): upgrade to angular v20 * chore: automatically migrate to control flow syntax in tpl * chore: automatically migrate to inject instead of using costructor * chore: fix warning about autocomplete attribute on login pages * chore(deps): update dependencies in package.json - upgraded bootstrap from 5.3.3 to 5.3.7 - upgraded dotenv from 16.4.7 to 16.5.0 - upgraded mongoose from 8.9.5 to 8.16.0 - upgraded @types/express from 4.17.21 to 4.17.23 - upgraded @types/jsonwebtoken from 9.0.7 to 9.0.10 - upgraded @types/morgan from 1.9.9 to 1.9.10 - upgraded @types/node from 20.9.0 to 22.15.29 - upgraded @types/supertest from 6.0.2 to 6.0.3 - upgraded htmlhint from 1.1.4 to 1.6.3 - upgraded nodemon from 3.1.9 to 3.1.10 - upgraded supertest from 7.0.0 to 7.1.1 - upgraded ts-jest from 29.2.5 to 29.4.0 * chore: update project version * chore: copilot suggestion, rename autocomplete to current-password for login
1 parent 64a8ed9 commit a3befe1

24 files changed

+2476
-6865
lines changed

angular.json

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"prefix": "app",
1616
"architect": {
1717
"build": {
18-
"builder": "@angular-devkit/build-angular:application",
18+
"builder": "@angular/build:application",
1919
"options": {
2020
"outputPath": "dist/public",
2121
"index": "client/index.html",
@@ -62,7 +62,7 @@
6262
"defaultConfiguration": "production"
6363
},
6464
"serve": {
65-
"builder": "@angular-devkit/build-angular:dev-server",
65+
"builder": "@angular/build:dev-server",
6666
"configurations": {
6767
"production": {
6868
"buildTarget": "angular2-full-stack:build:production"
@@ -75,10 +75,10 @@
7575
"defaultConfiguration": "development"
7676
},
7777
"extract-i18n": {
78-
"builder": "@angular-devkit/build-angular:extract-i18n"
78+
"builder": "@angular/build:extract-i18n"
7979
},
8080
"test": {
81-
"builder": "@angular-devkit/build-angular:karma",
81+
"builder": "@angular/build:karma",
8282
"options": {
8383
"polyfills": [
8484
"zone.js",
@@ -116,5 +116,31 @@
116116
"schematicCollections": [
117117
"angular-eslint"
118118
]
119+
},
120+
"schematics": {
121+
"@schematics/angular:component": {
122+
"type": "component"
123+
},
124+
"@schematics/angular:directive": {
125+
"type": "directive"
126+
},
127+
"@schematics/angular:service": {
128+
"type": "service"
129+
},
130+
"@schematics/angular:guard": {
131+
"typeSeparator": "."
132+
},
133+
"@schematics/angular:interceptor": {
134+
"typeSeparator": "."
135+
},
136+
"@schematics/angular:module": {
137+
"typeSeparator": "."
138+
},
139+
"@schematics/angular:pipe": {
140+
"typeSeparator": "."
141+
},
142+
"@schematics/angular:resolver": {
143+
"typeSeparator": "."
144+
}
119145
}
120146
}

client/app/account/account.component.html

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,39 @@
22

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

5-
<div class="card" *ngIf="!isLoading">
6-
<h4 class="card-header">Account settings</h4>
7-
<div class="card-body">
8-
<form #accountForm="ngForm" (ngSubmit)="save(user)">
9-
<div class="input-group">
10-
<span class="input-group-text">
11-
<i class="fa fa-user"></i>
12-
</span>
13-
<input class="form-control" type="text" name="username"
14-
[(ngModel)]="user.username" placeholder="Username" required>
15-
</div>
16-
<div class="input-group">
17-
<span class="input-group-text">
18-
<i class="fa fa-envelope"></i>
19-
</span>
20-
<input class="form-control" type="email" name="email"
21-
[(ngModel)]="user.email" placeholder="Email" required>
22-
</div>
23-
<div class="input-group">
24-
<span class="input-group-text">
25-
<i class="fa fa-black-tie"></i>
26-
</span>
27-
<select class="form-control" name="role" [(ngModel)]="user.role">
28-
<option value="" disabled>Role</option>
29-
<option value="user">User</option>
30-
<option value="admin">Admin</option>
31-
</select>
32-
</div>
33-
<button class="btn btn-primary" type="submit" [disabled]="!accountForm.form.valid">
34-
<i class="fa fa-save"></i> Save
35-
</button>
36-
</form>
5+
@if (!isLoading) {
6+
<div class="card">
7+
<h4 class="card-header">Account settings</h4>
8+
<div class="card-body">
9+
<form #accountForm="ngForm" (ngSubmit)="save(user)">
10+
<div class="input-group">
11+
<span class="input-group-text">
12+
<i class="fa fa-user"></i>
13+
</span>
14+
<input class="form-control" type="text" name="username"
15+
[(ngModel)]="user.username" placeholder="Username" required>
16+
</div>
17+
<div class="input-group">
18+
<span class="input-group-text">
19+
<i class="fa fa-envelope"></i>
20+
</span>
21+
<input class="form-control" type="email" name="email"
22+
[(ngModel)]="user.email" placeholder="Email" required>
23+
</div>
24+
<div class="input-group">
25+
<span class="input-group-text">
26+
<i class="fa fa-black-tie"></i>
27+
</span>
28+
<select class="form-control" name="role" [(ngModel)]="user.role">
29+
<option value="" disabled>Role</option>
30+
<option value="user">User</option>
31+
<option value="admin">Admin</option>
32+
</select>
33+
</div>
34+
<button class="btn btn-primary" type="submit" [disabled]="!accountForm.form.valid">
35+
<i class="fa fa-save"></i> Save
36+
</button>
37+
</form>
38+
</div>
3739
</div>
38-
</div>
40+
}

client/app/account/account.component.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, OnInit } from '@angular/core';
1+
import { Component, OnInit, inject } from '@angular/core';
22
import { ToastComponent } from '../shared/toast/toast.component';
33
import { AuthService } from '../services/auth.service';
44
import { UserService } from '../services/user.service';
@@ -10,14 +10,14 @@ import { User } from '../shared/models/user.model';
1010
standalone: false
1111
})
1212
export class AccountComponent implements OnInit {
13+
private auth = inject(AuthService);
14+
toast = inject(ToastComponent);
15+
private userService = inject(UserService);
16+
1317

1418
user: User = new User();
1519
isLoading = true;
1620

17-
constructor(private auth: AuthService,
18-
public toast: ToastComponent,
19-
private userService: UserService) { }
20-
2121
ngOnInit(): void {
2222
this.getUser();
2323
}

client/app/add-cat-form/add-cat-form.component.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, Input } from '@angular/core';
1+
import { Component, Input, inject } from '@angular/core';
22
import { UntypedFormGroup, UntypedFormControl, Validators, UntypedFormBuilder } from '@angular/forms';
33
import { CatService } from '../services/cat.service';
44
import { ToastComponent } from '../shared/toast/toast.component';
@@ -12,16 +12,18 @@ import { Cat } from '../shared/models/cat.model';
1212
})
1313

1414
export class AddCatFormComponent {
15+
private catService = inject(CatService);
16+
private formBuilder = inject(UntypedFormBuilder);
17+
toast = inject(ToastComponent);
18+
1519
@Input() cats: Cat[] = [];
1620

1721
addCatForm: UntypedFormGroup;
1822
name = new UntypedFormControl('', Validators.required);
1923
age = new UntypedFormControl('', Validators.required);
2024
weight = new UntypedFormControl('', Validators.required);
2125

22-
constructor(private catService: CatService,
23-
private formBuilder: UntypedFormBuilder,
24-
public toast: ToastComponent) {
26+
constructor() {
2527
this.addCatForm = this.formBuilder.group({
2628
name: this.name,
2729
age: this.age,

client/app/admin/admin.component.html

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,42 @@
22

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

5-
<div class="card" *ngIf="!isLoading">
6-
<h4 class="card-header">Registered users ({{users.length}})</h4>
7-
<div class="card-body">
8-
<table class="table table-bordered">
9-
<thead class="table-secondary">
10-
<tr>
11-
<th scope="col">Username</th>
12-
<th scope="col">Email</th>
13-
<th scope="col">Role</th>
14-
<th scope="col">Actions</th>
15-
</tr>
16-
</thead>
17-
<tbody *ngIf="users.length === 0">
18-
<tr>
19-
<td colspan="4">There are no registered users.</td>
20-
</tr>
21-
</tbody>
22-
<tbody>
23-
<tr *ngFor="let user of users">
24-
<td>{{user.username}}</td>
25-
<td>{{user.email}}</td>
26-
<td>{{user.role}}</td>
27-
<td>
28-
<button class="btn btn-sm btn-danger" (click)="deleteUser(user)"
29-
[disabled]="auth.currentUser._id === user._id">
30-
<i class="fa fa-trash"></i> Delete
31-
</button>
32-
</td>
33-
</tr>
34-
</tbody>
35-
</table>
5+
@if (!isLoading) {
6+
<div class="card">
7+
<h4 class="card-header">Registered users ({{users.length}})</h4>
8+
<div class="card-body">
9+
<table class="table table-bordered">
10+
<thead class="table-secondary">
11+
<tr>
12+
<th scope="col">Username</th>
13+
<th scope="col">Email</th>
14+
<th scope="col">Role</th>
15+
<th scope="col">Actions</th>
16+
</tr>
17+
</thead>
18+
@if (users.length === 0) {
19+
<tbody>
20+
<tr>
21+
<td colspan="4">There are no registered users.</td>
22+
</tr>
23+
</tbody>
24+
}
25+
<tbody>
26+
@for (user of users; track user) {
27+
<tr>
28+
<td>{{user.username}}</td>
29+
<td>{{user.email}}</td>
30+
<td>{{user.role}}</td>
31+
<td>
32+
<button class="btn btn-sm btn-danger" (click)="deleteUser(user)"
33+
[disabled]="auth.currentUser._id === user._id">
34+
<i class="fa fa-trash"></i> Delete
35+
</button>
36+
</td>
37+
</tr>
38+
}
39+
</tbody>
40+
</table>
41+
</div>
3642
</div>
37-
</div>
43+
}

client/app/admin/admin.component.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, OnInit } from '@angular/core';
1+
import { Component, OnInit, inject } from '@angular/core';
22

33
import { ToastComponent } from '../shared/toast/toast.component';
44
import { AuthService } from '../services/auth.service';
@@ -11,14 +11,14 @@ import { User } from '../shared/models/user.model';
1111
standalone: false
1212
})
1313
export class AdminComponent implements OnInit {
14+
auth = inject(AuthService);
15+
toast = inject(ToastComponent);
16+
private userService = inject(UserService);
17+
1418

1519
users: User[] = [];
1620
isLoading = true;
1721

18-
constructor(public auth: AuthService,
19-
public toast: ToastComponent,
20-
private userService: UserService) { }
21-
2222
ngOnInit(): void {
2323
this.getUsers();
2424
}

client/app/app.component.html

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
44
<button class="navbar-toggler" type="button"
5-
data-bs-toggle="collapse" data-bs-target="#navbar-supported-content"
6-
aria-controls="navbar-supported-content" aria-expanded="false" aria-label="Toggle navigation">
5+
data-bs-toggle="collapse" data-bs-target="#navbar-supported-content"
6+
aria-controls="navbar-supported-content" aria-expanded="false" aria-label="Toggle navigation">
77
<span class="navbar-toggler-icon"></span>
88
</button>
99
<div class="collapse navbar-collapse" id="navbar-supported-content">
@@ -19,29 +19,39 @@
1919
</a>
2020
</li>
2121
<li class="nav-item">
22-
<a routerLink="/login" class="nav-link" routerLinkActive="active" *ngIf="!auth.loggedIn">
23-
<i class="fa fa-sign-in"></i> Login
24-
</a>
22+
@if (!auth.loggedIn) {
23+
<a routerLink="/login" class="nav-link" routerLinkActive="active">
24+
<i class="fa fa-sign-in"></i> Login
25+
</a>
26+
}
2527
</li>
2628
<li class="nav-item">
27-
<a routerLink="/register" class="nav-link" routerLinkActive="active" *ngIf="!auth.loggedIn">
28-
<i class="fa fa-user-plus"></i> Register
29-
</a>
29+
@if (!auth.loggedIn) {
30+
<a routerLink="/register" class="nav-link" routerLinkActive="active">
31+
<i class="fa fa-user-plus"></i> Register
32+
</a>
33+
}
3034
</li>
3135
<li class="nav-item">
32-
<a routerLink="/account" class="nav-link" routerLinkActive="active" *ngIf="auth.loggedIn">
33-
<i class="fa fa-user"></i> Account ({{auth.currentUser.username}})
34-
</a>
36+
@if (auth.loggedIn) {
37+
<a routerLink="/account" class="nav-link" routerLinkActive="active">
38+
<i class="fa fa-user"></i> Account ({{auth.currentUser.username}})
39+
</a>
40+
}
3541
</li>
3642
<li class="nav-item">
37-
<a routerLink="/admin" class="nav-link" routerLinkActive="active" *ngIf="auth.loggedIn && auth.isAdmin">
38-
<i class="fa fa-lock"></i> Admin
39-
</a>
43+
@if (auth.loggedIn && auth.isAdmin) {
44+
<a routerLink="/admin" class="nav-link" routerLinkActive="active">
45+
<i class="fa fa-lock"></i> Admin
46+
</a>
47+
}
4048
</li>
4149
<li class="nav-item">
42-
<a routerLink="/logout" class="nav-link" routerLinkActive="active" *ngIf="auth.loggedIn">
43-
<i class="fa fa-sign-out"></i> Logout
44-
</a>
50+
@if (auth.loggedIn) {
51+
<a routerLink="/logout" class="nav-link" routerLinkActive="active">
52+
<i class="fa fa-sign-out"></i> Logout
53+
</a>
54+
}
4555
</li>
4656
</ul>
4757
</div>

client/app/app.component.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { AfterViewChecked, ChangeDetectorRef, Component } from '@angular/core';
1+
import { AfterViewChecked, ChangeDetectorRef, Component, inject } from '@angular/core';
22
import { AuthService } from './services/auth.service';
33

44
@Component({
@@ -7,9 +7,9 @@ import { AuthService } from './services/auth.service';
77
standalone: false
88
})
99
export class AppComponent implements AfterViewChecked {
10+
auth = inject(AuthService);
11+
private changeDetector = inject(ChangeDetectorRef);
1012

11-
constructor(public auth: AuthService,
12-
private changeDetector: ChangeDetectorRef) { }
1313

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

0 commit comments

Comments
 (0)