From 5f8534884398463908ff91e746f1962a041544e1 Mon Sep 17 00:00:00 2001 From: elisabethroys <125894666+elisabethroys@users.noreply.github.com> Date: Mon, 8 Sep 2025 10:42:58 +0200 Subject: [PATCH 1/8] Generated the contacts module, and imported the right modules in app.module --- src/app/app.module.ts | 4 +++- src/app/contacts/contacts.module.ts | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/app/contacts/contacts.module.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 8207184c..545e28c0 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,13 +1,15 @@ import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; +import { CommonModule } from '@angular/common'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { LayoutModule } from './layout/layout.module'; +import { ContactsModule } from './contacts/contacts.module'; @NgModule({ declarations: [AppComponent], - imports: [BrowserModule, AppRoutingModule, LayoutModule], + imports: [BrowserModule, AppRoutingModule, CommonModule, ContactsModule, LayoutModule], bootstrap: [AppComponent], }) export class AppModule {} diff --git a/src/app/contacts/contacts.module.ts b/src/app/contacts/contacts.module.ts new file mode 100644 index 00000000..942de8c0 --- /dev/null +++ b/src/app/contacts/contacts.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + + + +@NgModule({ + declarations: [], + imports: [ + CommonModule + ] +}) +export class ContactsModule { } From 71c9de1d8bef4d524a179ba640fc24421ca19579 Mon Sep 17 00:00:00 2001 From: elisabethroys <125894666+elisabethroys@users.noreply.github.com> Date: Mon, 8 Sep 2025 11:12:49 +0200 Subject: [PATCH 2/8] Added three modules to contacts, and set up routing to add and list --- package-lock.json | 664 +++++++++++-------- package.json | 4 +- src/app/app-routing.module.ts | 8 +- src/app/contacts/add/add.component.css | 0 src/app/contacts/add/add.component.html | 1 + src/app/contacts/add/add.component.ts | 12 + src/app/contacts/contacts-service.service.ts | 9 + src/app/contacts/list/list.component.css | 0 src/app/contacts/list/list.component.html | 1 + src/app/contacts/list/list.component.ts | 12 + src/app/contacts/view/view.component.css | 0 src/app/contacts/view/view.component.html | 1 + src/app/contacts/view/view.component.ts | 12 + src/app/layout/menu/menu.component.html | 4 +- 14 files changed, 455 insertions(+), 273 deletions(-) create mode 100644 src/app/contacts/add/add.component.css create mode 100644 src/app/contacts/add/add.component.html create mode 100644 src/app/contacts/add/add.component.ts create mode 100644 src/app/contacts/contacts-service.service.ts create mode 100644 src/app/contacts/list/list.component.css create mode 100644 src/app/contacts/list/list.component.html create mode 100644 src/app/contacts/list/list.component.ts create mode 100644 src/app/contacts/view/view.component.css create mode 100644 src/app/contacts/view/view.component.html create mode 100644 src/app/contacts/view/view.component.ts diff --git a/package-lock.json b/package-lock.json index d74dbf3b..7465c637 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@angular/forms": "^18.2.6", "@angular/platform-browser": "^18.2.6", "@angular/platform-browser-dynamic": "^18.2.6", - "@angular/router": "^18.2.6", + "@angular/router": "^18.2.13", "rxjs": "~7.8.0", "tslib": "^2.3.0", "zone.js": "~0.14.10" @@ -294,12 +294,13 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.6.tgz", - "integrity": "sha512-uIttrQ2cQ2PWAFFVPeCoNR8xvs7tPJ2i8gzqsIwYdge107xDC6u9CqfgmBqPDSFpWj+IiC2Jwcm8Z4HYKU4+7A==", + "version": "18.2.20", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.20.tgz", + "integrity": "sha512-eKoFeWOxwheaGK+aguyTs9utxxmFsrI/aHQttiyhBy+HzmgX/E0grzx6ZpuipUpBA8lYMtxfTJ7AC12fGJMvFA==", "dev": true, + "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.6", + "@angular-devkit/core": "18.2.20", "jsonc-parser": "3.3.1", "magic-string": "0.30.11", "ora": "5.4.1", @@ -311,6 +312,65 @@ "yarn": ">= 1.13.0" } }, + "node_modules/@angular-devkit/schematics/node_modules/@angular-devkit/core": { + "version": "18.2.20", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.20.tgz", + "integrity": "sha512-VNxI2e9EZQNqKYtUJ4u43QRJ9kObeyG9f69caxnj28cg4qim3H1vX/sglnodP8EsTIRbzwBKc884ebHWFdQJkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "8.17.1", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.2", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/schematics/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/schematics/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@angular/animations": { "version": "18.2.6", "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.2.6.tgz", @@ -655,17 +715,18 @@ } }, "node_modules/@angular/cli": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.6.tgz", - "integrity": "sha512-tdXsnV/w+Rgu8q0zFsLU5L9ImTVqrTol1vppHaQkJ/vuoHy+s8ZEbBqhVrO/ffosNb2xseUybGYvqMS4zkNQjg==", + "version": "18.2.20", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.20.tgz", + "integrity": "sha512-uu8XM+vvVQxTgCJAAQtCu6aLErbdCh/xqYpawgTaoOjiDkyWonTC+iGUUy0AEk5no/pbg2TCoZZx0AXWM1yLVA==", "dev": true, + "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1802.6", - "@angular-devkit/core": "18.2.6", - "@angular-devkit/schematics": "18.2.6", + "@angular-devkit/architect": "0.1802.20", + "@angular-devkit/core": "18.2.20", + "@angular-devkit/schematics": "18.2.20", "@inquirer/prompts": "5.3.8", "@listr2/prompt-adapter-inquirer": "2.0.15", - "@schematics/angular": "18.2.6", + "@schematics/angular": "18.2.20", "@yarnpkg/lockfile": "1.1.0", "ini": "4.1.3", "jsonc-parser": "3.3.1", @@ -687,6 +748,81 @@ "yarn": ">= 1.13.0" } }, + "node_modules/@angular/cli/node_modules/@angular-devkit/architect": { + "version": "0.1802.20", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.20.tgz", + "integrity": "sha512-nNUv2541/X4V0vtT2F6wCT+/GAY8v+J8MRMh8kGBVdyV9EdtSTWxHAvE1WhX5uE7VUCNegDfElxvAR9Vq8qSig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "18.2.20", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/cli/node_modules/@angular-devkit/core": { + "version": "18.2.20", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.20.tgz", + "integrity": "sha512-VNxI2e9EZQNqKYtUJ4u43QRJ9kObeyG9f69caxnj28cg4qim3H1vX/sglnodP8EsTIRbzwBKc884ebHWFdQJkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "8.17.1", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.2", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular/cli/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@angular/cli/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@angular/common": { "version": "18.2.6", "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.2.6.tgz", @@ -820,9 +956,10 @@ } }, "node_modules/@angular/router": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.2.6.tgz", - "integrity": "sha512-t57Sqja8unHhZlPr+4CWnQacuox2M4p2pMHps+31wt337qH6mKf4jqDmK0dE/MFdRyKjT2a2E/2NwtxXxcWNuw==", + "version": "18.2.13", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.2.13.tgz", + "integrity": "sha512-VKmfgi/r/CkyBq9nChQ/ptmfu0JT/8ONnLVJ5H+SkFLRYJcIRyHLKjRihMCyVm6xM5yktOdCaW73NTQrFz7+bg==", + "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, @@ -830,20 +967,22 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.6", - "@angular/core": "18.2.6", - "@angular/platform-browser": "18.2.6", + "@angular/common": "18.2.13", + "@angular/core": "18.2.13", + "@angular/platform-browser": "18.2.13", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" @@ -1178,19 +1317,21 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -1219,40 +1360,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", - "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", - "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.25.6" + "@babel/types": "^7.28.4" }, "bin": { "parser": "bin/babel-parser.js" @@ -2540,14 +2668,15 @@ } }, "node_modules/@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -2587,14 +2716,14 @@ } }, "node_modules/@babel/types": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", - "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -4082,13 +4211,14 @@ ] }, "node_modules/@schematics/angular": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.6.tgz", - "integrity": "sha512-Y988EoOEQDLEyHu3414T6AeVUyx21AexBHQNbUNQkK8cxlxyB6m1eH1cx6vFgLRFUTsLVv+C6Ln/ICNTfLcG4A==", + "version": "18.2.20", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.20.tgz", + "integrity": "sha512-32bJycGtePm8X994hGl9PChBVgw9bbc+ehDpxeeaIZzcFHWlM06+cJu8Jr2FA8SASg3TwdnEybxFiYS14884OQ==", "dev": true, + "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.6", - "@angular-devkit/schematics": "18.2.6", + "@angular-devkit/core": "18.2.20", + "@angular-devkit/schematics": "18.2.20", "jsonc-parser": "3.3.1" }, "engines": { @@ -4097,6 +4227,65 @@ "yarn": ">= 1.13.0" } }, + "node_modules/@schematics/angular/node_modules/@angular-devkit/core": { + "version": "18.2.20", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.20.tgz", + "integrity": "sha512-VNxI2e9EZQNqKYtUJ4u43QRJ9kObeyG9f69caxnj28cg4qim3H1vX/sglnodP8EsTIRbzwBKc884ebHWFdQJkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "8.17.1", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.2", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@schematics/angular/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@schematics/angular/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@sigstore/bundle": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.3.2.tgz", @@ -4249,17 +4438,12 @@ "@types/node": "*" } }, - "node_modules/@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", - "dev": true - }, "node_modules/@types/cors": { - "version": "2.8.13", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", - "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -4799,18 +4983,6 @@ "node": ">=8" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -4963,6 +5135,7 @@ "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", "dev": true, + "license": "MIT", "engines": { "node": "^4.5.0 || >= 5.9" } @@ -5058,10 +5231,11 @@ "dev": true }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -5241,20 +5415,6 @@ } ] }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -5448,21 +5608,6 @@ "node": ">=6" } }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -5494,32 +5639,24 @@ } }, "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "dev": true, + "license": "MIT", "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", + "bytes": "3.1.2", + "compressible": "~2.0.18", "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", "vary": "~1.1.2" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/compression/node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/compression/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -5535,11 +5672,15 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, - "node_modules/compression/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } }, "node_modules/concat-map": { "version": "0.0.1", @@ -5614,10 +5755,11 @@ "dev": true }, "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -5700,6 +5842,7 @@ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "dev": true, + "license": "MIT", "dependencies": { "object-assign": "^4", "vary": "^1" @@ -5838,10 +5981,11 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -6239,31 +6383,32 @@ } }, "node_modules/engine.io": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.0.tgz", - "integrity": "sha512-UlfoK1iD62Hkedw2TmuHdhDsZCGaAyp+LZ/AvnImjYBeWagA3qIEETum90d6shMeFZiDuGT66zVCdx1wKYKGGg==", + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", + "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", "dev": true, + "license": "MIT", "dependencies": { - "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", - "cookie": "~0.4.1", + "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.3.1", - "engine.io-parser": "~5.1.0", - "ws": "~8.11.0" + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1" }, "engines": { - "node": ">=10.0.0" + "node": ">=10.2.0" } }, "node_modules/engine.io-parser": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.1.0.tgz", - "integrity": "sha512-enySgNiK5tyZFynt3z7iqBR+Bto9EVVVvDFuTT0ioHCGbzirZVGDGiQjZzEp8hWl6hd5FSVytJGuScX1C1C35w==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" } @@ -6441,15 +6586,6 @@ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "dev": true }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -6562,17 +6698,18 @@ "dev": true }, "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dev": true, + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -6586,7 +6723,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -6601,13 +6738,18 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -6827,9 +6969,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", "dev": true, "funding": [ { @@ -6837,6 +6979,7 @@ "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -7100,15 +7243,6 @@ "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "dev": true }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/has-property-descriptors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", @@ -7810,10 +7944,11 @@ } }, "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -7961,7 +8096,8 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jsbn": { "version": "1.1.0", @@ -8106,10 +8242,11 @@ } }, "node_modules/karma-coverage/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -8163,10 +8300,11 @@ } }, "node_modules/karma/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -8225,15 +8363,13 @@ } }, "node_modules/karma/node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, + "license": "MIT", "engines": { - "node": ">=8.17.0" + "node": ">=14.14" } }, "node_modules/karma/node_modules/yargs": { @@ -8362,10 +8498,11 @@ } }, "node_modules/less/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "optional": true, "bin": { "semver": "bin/semver" @@ -8887,10 +9024,11 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -9336,9 +9474,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, "funding": [ { @@ -9346,6 +9484,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -9672,6 +9811,7 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -9707,10 +9847,11 @@ } }, "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -10076,10 +10217,11 @@ "dev": true }, "node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", - "dev": true + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "dev": true, + "license": "MIT" }, "node_modules/path-type": { "version": "5.0.0", @@ -10094,10 +10236,11 @@ } }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", @@ -10756,10 +10899,11 @@ } }, "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -11358,30 +11502,33 @@ } }, "node_modules/socket.io": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.0.tgz", - "integrity": "sha512-eOpu7oCNiPGBHn9Falg0cAGivp6TpDI3Yt596fbsf+vln8kRLFWxXKrecFrybn/xNYVn9HcdJNAkYToCmTjsyg==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", "dev": true, + "license": "MIT", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.5.0", + "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" }, "engines": { - "node": ">=10.0.0" + "node": ">=10.2.0" } }, "node_modules/socket.io-adapter": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", - "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", "dev": true, + "license": "MIT", "dependencies": { - "ws": "~8.11.0" + "debug": "~4.3.4", + "ws": "~8.17.1" } }, "node_modules/socket.io-parser": { @@ -11680,18 +11827,6 @@ "node": ">=6" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -11921,15 +12056,6 @@ "node": ">=0.6.0" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -12923,10 +13049,11 @@ } }, "node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", + "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", "dev": true, + "license": "MIT", "dependencies": { "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", @@ -13249,16 +13376,17 @@ "dev": true }, "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { diff --git a/package.json b/package.json index d9b273ed..bd6d647d 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "@angular/forms": "^18.2.6", "@angular/platform-browser": "^18.2.6", "@angular/platform-browser-dynamic": "^18.2.6", - "@angular/router": "^18.2.6", + "@angular/router": "^18.2.13", "rxjs": "~7.8.0", "tslib": "^2.3.0", "zone.js": "~0.14.10" @@ -35,4 +35,4 @@ "karma-jasmine-html-reporter": "~2.0.0", "typescript": "~5.4.5" } -} \ No newline at end of file +} diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 02972627..e9e63ee7 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,7 +1,13 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; -const routes: Routes = []; +import { ListComponent } from './contacts/list/list.component'; +import { AddComponent } from './contacts/add/add.component'; + +const routes: Routes = [ + { path: 'contacts', component: ListComponent}, + { path: 'contacts/add', component: AddComponent} +]; @NgModule({ imports: [RouterModule.forRoot(routes)], diff --git a/src/app/contacts/add/add.component.css b/src/app/contacts/add/add.component.css new file mode 100644 index 00000000..e69de29b diff --git a/src/app/contacts/add/add.component.html b/src/app/contacts/add/add.component.html new file mode 100644 index 00000000..fa723f3a --- /dev/null +++ b/src/app/contacts/add/add.component.html @@ -0,0 +1 @@ +

add works!

diff --git a/src/app/contacts/add/add.component.ts b/src/app/contacts/add/add.component.ts new file mode 100644 index 00000000..385416f1 --- /dev/null +++ b/src/app/contacts/add/add.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-add', + standalone: true, + imports: [], + templateUrl: './add.component.html', + styleUrl: './add.component.css' +}) +export class AddComponent { + +} diff --git a/src/app/contacts/contacts-service.service.ts b/src/app/contacts/contacts-service.service.ts new file mode 100644 index 00000000..3f15143d --- /dev/null +++ b/src/app/contacts/contacts-service.service.ts @@ -0,0 +1,9 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class ContactsServiceService { + + constructor() { } +} diff --git a/src/app/contacts/list/list.component.css b/src/app/contacts/list/list.component.css new file mode 100644 index 00000000..e69de29b diff --git a/src/app/contacts/list/list.component.html b/src/app/contacts/list/list.component.html new file mode 100644 index 00000000..7c1fe159 --- /dev/null +++ b/src/app/contacts/list/list.component.html @@ -0,0 +1 @@ +

list works!

diff --git a/src/app/contacts/list/list.component.ts b/src/app/contacts/list/list.component.ts new file mode 100644 index 00000000..789f6d75 --- /dev/null +++ b/src/app/contacts/list/list.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-list', + standalone: true, + imports: [], + templateUrl: './list.component.html', + styleUrl: './list.component.css' +}) +export class ListComponent { + +} diff --git a/src/app/contacts/view/view.component.css b/src/app/contacts/view/view.component.css new file mode 100644 index 00000000..e69de29b diff --git a/src/app/contacts/view/view.component.html b/src/app/contacts/view/view.component.html new file mode 100644 index 00000000..48dbfee6 --- /dev/null +++ b/src/app/contacts/view/view.component.html @@ -0,0 +1 @@ +

view works!

diff --git a/src/app/contacts/view/view.component.ts b/src/app/contacts/view/view.component.ts new file mode 100644 index 00000000..b9d123db --- /dev/null +++ b/src/app/contacts/view/view.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-view', + standalone: true, + imports: [], + templateUrl: './view.component.html', + styleUrl: './view.component.css' +}) +export class ViewComponent { + +} diff --git a/src/app/layout/menu/menu.component.html b/src/app/layout/menu/menu.component.html index 7c5ec7a2..aed3259d 100644 --- a/src/app/layout/menu/menu.component.html +++ b/src/app/layout/menu/menu.component.html @@ -1,5 +1,5 @@

Menu

From 99330a6cf288548ea2a589bc57f167c34a0100ff Mon Sep 17 00:00:00 2001 From: elisabethroys <125894666+elisabethroys@users.noreply.github.com> Date: Mon, 8 Sep 2025 12:52:57 +0200 Subject: [PATCH 3/8] Made the contact list page work properly --- src/app/app-routing.module.ts | 4 +++- src/app/app.component.ts | 1 + src/app/contacts/contacts-service.service.ts | 9 --------- src/app/contacts/contacts.module.ts | 14 ++++++++++++-- src/app/contacts/contacts.service.ts | 10 ++++++++++ src/app/contacts/list/list.component.css | 10 ++++++++++ src/app/contacts/list/list.component.html | 9 ++++++++- src/app/contacts/list/list.component.ts | 10 ++++++++-- src/app/data/contacts.ts | 18 ++++++++++++++++++ src/app/models/contact.ts | 7 +++++++ 10 files changed, 77 insertions(+), 15 deletions(-) delete mode 100644 src/app/contacts/contacts-service.service.ts create mode 100644 src/app/contacts/contacts.service.ts create mode 100644 src/app/data/contacts.ts create mode 100644 src/app/models/contact.ts diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index e9e63ee7..09ba59d8 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -3,10 +3,12 @@ import { RouterModule, Routes } from '@angular/router'; import { ListComponent } from './contacts/list/list.component'; import { AddComponent } from './contacts/add/add.component'; +import { ViewComponent } from './contacts/view/view.component'; const routes: Routes = [ { path: 'contacts', component: ListComponent}, - { path: 'contacts/add', component: AddComponent} + { path: 'contacts/add', component: AddComponent}, + { path: 'contacts/:id', component: ViewComponent} ]; @NgModule({ diff --git a/src/app/app.component.ts b/src/app/app.component.ts index b82791ab..d4aebfc2 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -3,6 +3,7 @@ import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', + standalone: false, styleUrls: ['./app.component.css'] }) export class AppComponent { diff --git a/src/app/contacts/contacts-service.service.ts b/src/app/contacts/contacts-service.service.ts deleted file mode 100644 index 3f15143d..00000000 --- a/src/app/contacts/contacts-service.service.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Injectable } from '@angular/core'; - -@Injectable({ - providedIn: 'root' -}) -export class ContactsServiceService { - - constructor() { } -} diff --git a/src/app/contacts/contacts.module.ts b/src/app/contacts/contacts.module.ts index 942de8c0..8d7853e3 100644 --- a/src/app/contacts/contacts.module.ts +++ b/src/app/contacts/contacts.module.ts @@ -1,12 +1,22 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { RouterModule } from '@angular/router'; + +import { ListComponent } from './list/list.component'; +import { AddComponent } from './add/add.component'; +import { ViewComponent } from './view/view.component'; @NgModule({ declarations: [], imports: [ - CommonModule - ] + CommonModule, + RouterModule, + ListComponent, + AddComponent, + ViewComponent + ], + exports: [ListComponent, AddComponent, ViewComponent] }) export class ContactsModule { } diff --git a/src/app/contacts/contacts.service.ts b/src/app/contacts/contacts.service.ts new file mode 100644 index 00000000..7f6e82b7 --- /dev/null +++ b/src/app/contacts/contacts.service.ts @@ -0,0 +1,10 @@ +import { Injectable } from '@angular/core'; +import { Contact } from '../models/contact'; +import { CONTACTS } from '../data/contacts'; + +@Injectable({ + providedIn: 'root' +}) +export class ContactsService { + public contacts: Contact[] = CONTACTS; +} diff --git a/src/app/contacts/list/list.component.css b/src/app/contacts/list/list.component.css index e69de29b..e9f2e16c 100644 --- a/src/app/contacts/list/list.component.css +++ b/src/app/contacts/list/list.component.css @@ -0,0 +1,10 @@ +.contact { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; +} + +.view { + margin-left: 150px; +} diff --git a/src/app/contacts/list/list.component.html b/src/app/contacts/list/list.component.html index 7c1fe159..f633054e 100644 --- a/src/app/contacts/list/list.component.html +++ b/src/app/contacts/list/list.component.html @@ -1 +1,8 @@ -

list works!

+

Contacts

+
+
+

{{ contact.firstname }} {{contact.lastname}}

+

View

+
+
+
diff --git a/src/app/contacts/list/list.component.ts b/src/app/contacts/list/list.component.ts index 789f6d75..41b57073 100644 --- a/src/app/contacts/list/list.component.ts +++ b/src/app/contacts/list/list.component.ts @@ -1,12 +1,18 @@ import { Component } from '@angular/core'; +import { Contact } from '../../models/contact' +import { ContactsService } from '../contacts.service'; +import { CommonModule } from '@angular/common'; @Component({ selector: 'app-list', standalone: true, - imports: [], + imports: [CommonModule ], templateUrl: './list.component.html', styleUrl: './list.component.css' }) export class ListComponent { - + contacts: Contact[] = []; + constructor(private readonly contactService: ContactsService){ + this.contacts = this.contactService.contacts; + } } diff --git a/src/app/data/contacts.ts b/src/app/data/contacts.ts new file mode 100644 index 00000000..0d48b64c --- /dev/null +++ b/src/app/data/contacts.ts @@ -0,0 +1,18 @@ +import { Contact } from "../models/contact"; + +export const CONTACTS: Contact[] = [ + { + id: 1, + firstname: 'John', + lastname: 'Carmack', + street: '10 Keen Street', + city: 'London' + }, + { + id: 2, + firstname: 'Grace', + lastname: 'Hopper', + street: '32 Deebug Road', + city: 'London' + } +] diff --git a/src/app/models/contact.ts b/src/app/models/contact.ts new file mode 100644 index 00000000..d85d962a --- /dev/null +++ b/src/app/models/contact.ts @@ -0,0 +1,7 @@ +export interface Contact { + id: number | null; + firstname: string; + lastname: string; + street: string; + city: string; +} From 996c12374432e00c262d616ae1487f9e1a061f91 Mon Sep 17 00:00:00 2001 From: elisabethroys <125894666+elisabethroys@users.noreply.github.com> Date: Mon, 8 Sep 2025 13:36:21 +0200 Subject: [PATCH 4/8] Added view contact functionality --- src/app/app.module.ts | 2 +- src/app/contacts/contacts.service.ts | 7 +++++++ src/app/contacts/list/list.component.html | 2 +- src/app/contacts/list/list.component.ts | 3 ++- src/app/contacts/view/view.component.html | 9 ++++++++- src/app/contacts/view/view.component.ts | 24 ++++++++++++++++++++--- 6 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 545e28c0..34c65937 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -9,7 +9,7 @@ import { ContactsModule } from './contacts/contacts.module'; @NgModule({ declarations: [AppComponent], - imports: [BrowserModule, AppRoutingModule, CommonModule, ContactsModule, LayoutModule], + imports: [BrowserModule, AppRoutingModule, ContactsModule, LayoutModule], bootstrap: [AppComponent], }) export class AppModule {} diff --git a/src/app/contacts/contacts.service.ts b/src/app/contacts/contacts.service.ts index 7f6e82b7..dc93113b 100644 --- a/src/app/contacts/contacts.service.ts +++ b/src/app/contacts/contacts.service.ts @@ -1,4 +1,6 @@ import { Injectable } from '@angular/core'; +import { Observable, of } from 'rxjs'; + import { Contact } from '../models/contact'; import { CONTACTS } from '../data/contacts'; @@ -7,4 +9,9 @@ import { CONTACTS } from '../data/contacts'; }) export class ContactsService { public contacts: Contact[] = CONTACTS; + + GetBeerById(id: number): Observable { + const contact = this.contacts.find((c) => c.id === id); + return of(contact); + } } diff --git a/src/app/contacts/list/list.component.html b/src/app/contacts/list/list.component.html index f633054e..38ed6b18 100644 --- a/src/app/contacts/list/list.component.html +++ b/src/app/contacts/list/list.component.html @@ -2,7 +2,7 @@

Contacts

{{ contact.firstname }} {{contact.lastname}}

-

View

+ View

diff --git a/src/app/contacts/list/list.component.ts b/src/app/contacts/list/list.component.ts index 41b57073..08b08cfb 100644 --- a/src/app/contacts/list/list.component.ts +++ b/src/app/contacts/list/list.component.ts @@ -2,11 +2,12 @@ import { Component } from '@angular/core'; import { Contact } from '../../models/contact' import { ContactsService } from '../contacts.service'; import { CommonModule } from '@angular/common'; +import { RouterModule } from '@angular/router'; @Component({ selector: 'app-list', standalone: true, - imports: [CommonModule ], + imports: [ CommonModule, RouterModule], templateUrl: './list.component.html', styleUrl: './list.component.css' }) diff --git a/src/app/contacts/view/view.component.html b/src/app/contacts/view/view.component.html index 48dbfee6..3e955d94 100644 --- a/src/app/contacts/view/view.component.html +++ b/src/app/contacts/view/view.component.html @@ -1 +1,8 @@ -

view works!

+
+

{{ contact.firstname }} {{ contact.lastname }}

+

{{ contact.street }} {{ contact.city }}

+
+ + +

Loading contact details...

+
diff --git a/src/app/contacts/view/view.component.ts b/src/app/contacts/view/view.component.ts index b9d123db..52cbc2a3 100644 --- a/src/app/contacts/view/view.component.ts +++ b/src/app/contacts/view/view.component.ts @@ -1,12 +1,30 @@ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +import { Contact } from 'src/app/models/contact'; +import { ContactsService } from '../contacts.service'; +import { CommonModule } from '@angular/common'; @Component({ selector: 'app-view', standalone: true, - imports: [], + imports: [CommonModule], templateUrl: './view.component.html', styleUrl: './view.component.css' }) -export class ViewComponent { +export class ViewComponent implements OnInit { + contact: Contact | null = null; + contactId: number | null = null; + + constructor( + private route: ActivatedRoute, + private contactService: ContactsService + ) {} + ngOnInit(): void { + this.contactId = Number(this.route.snapshot.paramMap.get('id')); + this.contactService.GetBeerById(this.contactId).subscribe((data) => { + this.contact = data!; + }); + } } From 1e5712e4b3c7e2f8ab8f662ada475a864d1a9334 Mon Sep 17 00:00:00 2001 From: elisabethroys <125894666+elisabethroys@users.noreply.github.com> Date: Mon, 8 Sep 2025 13:55:35 +0200 Subject: [PATCH 5/8] Added the add new contact functionalitity --- src/app/app.module.ts | 1 - src/app/contacts/add/add.component.html | 49 ++++++++++++++++++++++++- src/app/contacts/add/add.component.ts | 34 ++++++++++++++++- src/app/contacts/contacts.module.ts | 2 + src/app/contacts/contacts.service.ts | 4 ++ 5 files changed, 86 insertions(+), 4 deletions(-) diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 34c65937..ba77c96f 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,6 +1,5 @@ import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; -import { CommonModule } from '@angular/common'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; diff --git a/src/app/contacts/add/add.component.html b/src/app/contacts/add/add.component.html index fa723f3a..511d037b 100644 --- a/src/app/contacts/add/add.component.html +++ b/src/app/contacts/add/add.component.html @@ -1 +1,48 @@ -

add works!

+
+

Add Contact

+
+
+ + +
+
+
+ + +
+
+
+ + +
+
+
+ + +
+
+ +
+
diff --git a/src/app/contacts/add/add.component.ts b/src/app/contacts/add/add.component.ts index 385416f1..5c1c3f84 100644 --- a/src/app/contacts/add/add.component.ts +++ b/src/app/contacts/add/add.component.ts @@ -1,12 +1,42 @@ import { Component } from '@angular/core'; +import { Router, RouterModule } from '@angular/router'; +import { FormGroup, FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms'; + +import { Contact } from '../../models/contact' +import { ContactsService } from '../contacts.service'; +import { CommonModule } from '@angular/common'; @Component({ selector: 'app-add', standalone: true, - imports: [], + imports: [CommonModule, RouterModule, ReactiveFormsModule], templateUrl: './add.component.html', styleUrl: './add.component.css' }) export class AddComponent { - + contactForm: FormGroup; + constructor( + private readonly formBuilder: FormBuilder, + private readonly contactService: ContactsService, + private readonly router: Router + ) { + this.contactForm = this.formBuilder.group({ + firstname: ['', Validators.required], + lastname: ['', Validators.required], + street: ['', Validators.required], + city: ['', Validators.required], + }); + } + addContact(): void { + const newContact: Contact = { + id: 0, + firstname: this.contactForm.value.firstname, + lastname: this.contactForm.value.lastname, + street: this.contactForm.value.street, + city: this.contactForm.value.city, + }; + this.contactService.AddContact(newContact); + this.contactForm.reset(); + this.router.navigate(['/contacts']); + } } diff --git a/src/app/contacts/contacts.module.ts b/src/app/contacts/contacts.module.ts index 8d7853e3..1d3b26f6 100644 --- a/src/app/contacts/contacts.module.ts +++ b/src/app/contacts/contacts.module.ts @@ -1,6 +1,7 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterModule } from '@angular/router'; +import { ReactiveFormsModule } from '@angular/forms'; import { ListComponent } from './list/list.component'; import { AddComponent } from './add/add.component'; @@ -12,6 +13,7 @@ import { ViewComponent } from './view/view.component'; declarations: [], imports: [ CommonModule, + ReactiveFormsModule, RouterModule, ListComponent, AddComponent, diff --git a/src/app/contacts/contacts.service.ts b/src/app/contacts/contacts.service.ts index dc93113b..6c108313 100644 --- a/src/app/contacts/contacts.service.ts +++ b/src/app/contacts/contacts.service.ts @@ -10,6 +10,10 @@ import { CONTACTS } from '../data/contacts'; export class ContactsService { public contacts: Contact[] = CONTACTS; + public AddContact(contact: Contact): void { + this.contacts.push(contact); + } + GetBeerById(id: number): Observable { const contact = this.contacts.find((c) => c.id === id); return of(contact); From 4917e0f75ae1408c040f873a7d8050d6dc9cc5cf Mon Sep 17 00:00:00 2001 From: elisabethroys <125894666+elisabethroys@users.noreply.github.com> Date: Mon, 8 Sep 2025 14:02:03 +0200 Subject: [PATCH 6/8] Added the edit component --- src/app/app-routing.module.ts | 4 +++- src/app/contacts/edit/edit.component.css | 0 src/app/contacts/edit/edit.component.html | 1 + src/app/contacts/edit/edit.component.ts | 14 ++++++++++++++ src/app/contacts/view/view.component.html | 1 + src/app/contacts/view/view.component.ts | 4 ++-- 6 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 src/app/contacts/edit/edit.component.css create mode 100644 src/app/contacts/edit/edit.component.html create mode 100644 src/app/contacts/edit/edit.component.ts diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 09ba59d8..02838ced 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -4,11 +4,13 @@ import { RouterModule, Routes } from '@angular/router'; import { ListComponent } from './contacts/list/list.component'; import { AddComponent } from './contacts/add/add.component'; import { ViewComponent } from './contacts/view/view.component'; +import { EditComponent } from './contacts/edit/edit.component'; const routes: Routes = [ { path: 'contacts', component: ListComponent}, { path: 'contacts/add', component: AddComponent}, - { path: 'contacts/:id', component: ViewComponent} + { path: 'contacts/:id', component: ViewComponent}, + { path: 'contacts/:id/edit', component: EditComponent} ]; @NgModule({ diff --git a/src/app/contacts/edit/edit.component.css b/src/app/contacts/edit/edit.component.css new file mode 100644 index 00000000..e69de29b diff --git a/src/app/contacts/edit/edit.component.html b/src/app/contacts/edit/edit.component.html new file mode 100644 index 00000000..d1393d89 --- /dev/null +++ b/src/app/contacts/edit/edit.component.html @@ -0,0 +1 @@ +

edit works!

diff --git a/src/app/contacts/edit/edit.component.ts b/src/app/contacts/edit/edit.component.ts new file mode 100644 index 00000000..9a84c8df --- /dev/null +++ b/src/app/contacts/edit/edit.component.ts @@ -0,0 +1,14 @@ +import { CommonModule } from '@angular/common'; +import { Component } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +@Component({ + selector: 'app-edit', + standalone: true, + imports: [CommonModule, RouterModule], + templateUrl: './edit.component.html', + styleUrl: './edit.component.css' +}) +export class EditComponent { + +} diff --git a/src/app/contacts/view/view.component.html b/src/app/contacts/view/view.component.html index 3e955d94..6d2509dd 100644 --- a/src/app/contacts/view/view.component.html +++ b/src/app/contacts/view/view.component.html @@ -1,6 +1,7 @@

{{ contact.firstname }} {{ contact.lastname }}

{{ contact.street }} {{ contact.city }}

+ Edit
diff --git a/src/app/contacts/view/view.component.ts b/src/app/contacts/view/view.component.ts index 52cbc2a3..31ff3753 100644 --- a/src/app/contacts/view/view.component.ts +++ b/src/app/contacts/view/view.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, RouterLink, RouterModule } from '@angular/router'; import { Contact } from 'src/app/models/contact'; import { ContactsService } from '../contacts.service'; @@ -8,7 +8,7 @@ import { CommonModule } from '@angular/common'; @Component({ selector: 'app-view', standalone: true, - imports: [CommonModule], + imports: [CommonModule, RouterModule], templateUrl: './view.component.html', styleUrl: './view.component.css' }) From 076f1c74556ff8b0114b406e7ada34b314aafb7e Mon Sep 17 00:00:00 2001 From: elisabethroys <125894666+elisabethroys@users.noreply.github.com> Date: Mon, 8 Sep 2025 14:14:16 +0200 Subject: [PATCH 7/8] Added a error message if a user tries to edit a contact, that does not exist --- src/app/contacts/edit/edit.component.html | 8 +++++++- src/app/contacts/edit/edit.component.ts | 21 ++++++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/app/contacts/edit/edit.component.html b/src/app/contacts/edit/edit.component.html index d1393d89..7a5db3f0 100644 --- a/src/app/contacts/edit/edit.component.html +++ b/src/app/contacts/edit/edit.component.html @@ -1 +1,7 @@ -

edit works!

+
+

{{ contact.firstname }} {{ contact.lastname }}

+
+ + +

This contact does not exist

+
diff --git a/src/app/contacts/edit/edit.component.ts b/src/app/contacts/edit/edit.component.ts index 9a84c8df..d1f66e2f 100644 --- a/src/app/contacts/edit/edit.component.ts +++ b/src/app/contacts/edit/edit.component.ts @@ -1,6 +1,8 @@ import { CommonModule } from '@angular/common'; -import { Component } from '@angular/core'; -import { RouterModule } from '@angular/router'; +import { Component, OnInit } from '@angular/core'; +import { RouterModule, ActivatedRoute } from '@angular/router'; +import { Contact } from 'src/app/models/contact'; +import { ContactsService } from '../contacts.service'; @Component({ selector: 'app-edit', @@ -9,6 +11,19 @@ import { RouterModule } from '@angular/router'; templateUrl: './edit.component.html', styleUrl: './edit.component.css' }) -export class EditComponent { +export class EditComponent implements OnInit { + contact: Contact | null = null; + contactId: number | null = null; + constructor( + private route: ActivatedRoute, + private contactService: ContactsService + ) {} + + ngOnInit(): void { + this.contactId = Number(this.route.snapshot.paramMap.get('id')); + this.contactService.GetBeerById(this.contactId).subscribe((data) => { + this.contact = data!; + }); + } } From 8957510e34aec9576e58b200117326d8919ed6a3 Mon Sep 17 00:00:00 2001 From: elisabethroys <125894666+elisabethroys@users.noreply.github.com> Date: Mon, 8 Sep 2025 14:34:33 +0200 Subject: [PATCH 8/8] Added edit contact functionality --- src/app/contacts/contacts.service.ts | 9 ++++- src/app/contacts/edit/edit.component.html | 49 ++++++++++++++++++++++- src/app/contacts/edit/edit.component.ts | 45 ++++++++++++++++++--- src/app/contacts/view/view.component.ts | 4 +- 4 files changed, 97 insertions(+), 10 deletions(-) diff --git a/src/app/contacts/contacts.service.ts b/src/app/contacts/contacts.service.ts index 6c108313..bf1eb25a 100644 --- a/src/app/contacts/contacts.service.ts +++ b/src/app/contacts/contacts.service.ts @@ -13,8 +13,15 @@ export class ContactsService { public AddContact(contact: Contact): void { this.contacts.push(contact); } + + public EditContact(updatedContact: Contact): void { + const index = this.contacts.findIndex(c => c.id === updatedContact.id); + if (index !== -1) { + this.contacts[index] = updatedContact; + } + } - GetBeerById(id: number): Observable { + GetContactById(id: number): Observable { const contact = this.contacts.find((c) => c.id === id); return of(contact); } diff --git a/src/app/contacts/edit/edit.component.html b/src/app/contacts/edit/edit.component.html index 7a5db3f0..e1f19d32 100644 --- a/src/app/contacts/edit/edit.component.html +++ b/src/app/contacts/edit/edit.component.html @@ -1,5 +1,52 @@
-

{{ contact.firstname }} {{ contact.lastname }}

+
+

Edit Contact

+
+
+ + +
+
+
+ + +
+
+
+ + +
+
+
+ + +
+
+ +
+
diff --git a/src/app/contacts/edit/edit.component.ts b/src/app/contacts/edit/edit.component.ts index d1f66e2f..aabe6a91 100644 --- a/src/app/contacts/edit/edit.component.ts +++ b/src/app/contacts/edit/edit.component.ts @@ -1,29 +1,62 @@ import { CommonModule } from '@angular/common'; import { Component, OnInit } from '@angular/core'; -import { RouterModule, ActivatedRoute } from '@angular/router'; +import { Router, RouterModule, ActivatedRoute } from '@angular/router'; import { Contact } from 'src/app/models/contact'; import { ContactsService } from '../contacts.service'; +import { FormGroup, FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms'; @Component({ selector: 'app-edit', standalone: true, - imports: [CommonModule, RouterModule], + imports: [CommonModule, RouterModule, ReactiveFormsModule], templateUrl: './edit.component.html', styleUrl: './edit.component.css' }) export class EditComponent implements OnInit { contact: Contact | null = null; contactId: number | null = null; + contactForm: FormGroup; constructor( private route: ActivatedRoute, - private contactService: ContactsService - ) {} + private contactService: ContactsService, + + private readonly formBuilder: FormBuilder, + private readonly router: Router + ) { + this.contactForm = this.formBuilder.group({ + firstname: ['', Validators.required], + lastname: ['', Validators.required], + street: ['', Validators.required], + city: ['', Validators.required], + }); + } ngOnInit(): void { this.contactId = Number(this.route.snapshot.paramMap.get('id')); - this.contactService.GetBeerById(this.contactId).subscribe((data) => { - this.contact = data!; + this.contactService.GetContactById(this.contactId).subscribe((data) => { + if (data) { + this.contact = data; + this.contactForm.patchValue({ + firstname: data.firstname, + lastname: data.lastname, + street: data.street, + city: data.city + }); + } }); } + + editContact(): void { + const updatedContact: Contact = { + id: this.contactId, + firstname: this.contactForm.value.firstname, + lastname: this.contactForm.value.lastname, + street: this.contactForm.value.street, + city: this.contactForm.value.city, + }; + this.contactService.EditContact(updatedContact); + this.contactForm.reset(); + this.router.navigate(['/contacts/', this.contactId]); + } } diff --git a/src/app/contacts/view/view.component.ts b/src/app/contacts/view/view.component.ts index 31ff3753..ca3da559 100644 --- a/src/app/contacts/view/view.component.ts +++ b/src/app/contacts/view/view.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute, RouterLink, RouterModule } from '@angular/router'; +import { ActivatedRoute, RouterModule } from '@angular/router'; import { Contact } from 'src/app/models/contact'; import { ContactsService } from '../contacts.service'; @@ -23,7 +23,7 @@ export class ViewComponent implements OnInit { ngOnInit(): void { this.contactId = Number(this.route.snapshot.paramMap.get('id')); - this.contactService.GetBeerById(this.contactId).subscribe((data) => { + this.contactService.GetContactById(this.contactId).subscribe((data) => { this.contact = data!; }); }