From 68d4b8275607fb1f8d57a17c842faacdc1ed04a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beatrice=20Dellac=C3=A0?= Date: Sun, 3 Nov 2024 11:16:14 +0100 Subject: [PATCH] TG-2 TG-9 - Push base Angular app --- package-lock.json | 271 +++++++++----- package.json | 6 + src/app/app.component.html | 344 +----------------- src/app/app.component.ts | 27 +- src/app/app.config.ts | 15 +- src/app/app.routes.ts | 16 +- src/app/interface/auth.ts | 4 + src/app/interface/user.ts | 6 + src/app/services/api.service.spec.ts | 16 + src/app/services/api.service.ts | 27 ++ src/app/services/auth-guard.service.spec.ts | 16 + src/app/services/auth-guard.service.ts | 22 ++ .../services/auth-interceptor.service.spec.ts | 16 + src/app/services/auth-interceptor.service.ts | 27 ++ src/app/services/auth.service.spec.ts | 16 + src/app/services/auth.service.ts | 67 ++++ .../beta/auth-form/auth-form.component.html | 4 + .../beta/auth-form/auth-form.component.scss | 0 .../auth-form/auth-form.component.spec.ts | 23 ++ .../beta/auth-form/auth-form.component.ts | 31 ++ .../views/dashboard/dashboard.component.html | 10 + .../views/dashboard/dashboard.component.scss | 0 .../dashboard/dashboard.component.spec.ts | 23 ++ .../views/dashboard/dashboard.component.ts | 46 +++ src/app/views/login/login.component.html | 68 ++++ src/app/views/login/login.component.scss | 0 src/app/views/login/login.component.spec.ts | 23 ++ src/app/views/login/login.component.ts | 70 ++++ .../views/register/register.component.html | 55 +++ .../views/register/register.component.scss | 0 .../views/register/register.component.spec.ts | 23 ++ src/app/views/register/register.component.ts | 30 ++ src/main.ts | 2 + src/styles.scss | 9 + tsconfig.app.json | 4 +- tsconfig.spec.json | 3 +- 36 files changed, 879 insertions(+), 441 deletions(-) create mode 100644 src/app/interface/auth.ts create mode 100644 src/app/interface/user.ts create mode 100644 src/app/services/api.service.spec.ts create mode 100644 src/app/services/api.service.ts create mode 100644 src/app/services/auth-guard.service.spec.ts create mode 100644 src/app/services/auth-guard.service.ts create mode 100644 src/app/services/auth-interceptor.service.spec.ts create mode 100644 src/app/services/auth-interceptor.service.ts create mode 100644 src/app/services/auth.service.spec.ts create mode 100644 src/app/services/auth.service.ts create mode 100644 src/app/views/beta/auth-form/auth-form.component.html create mode 100644 src/app/views/beta/auth-form/auth-form.component.scss create mode 100644 src/app/views/beta/auth-form/auth-form.component.spec.ts create mode 100644 src/app/views/beta/auth-form/auth-form.component.ts create mode 100644 src/app/views/dashboard/dashboard.component.html create mode 100644 src/app/views/dashboard/dashboard.component.scss create mode 100644 src/app/views/dashboard/dashboard.component.spec.ts create mode 100644 src/app/views/dashboard/dashboard.component.ts create mode 100644 src/app/views/login/login.component.html create mode 100644 src/app/views/login/login.component.scss create mode 100644 src/app/views/login/login.component.spec.ts create mode 100644 src/app/views/login/login.component.ts create mode 100644 src/app/views/register/register.component.html create mode 100644 src/app/views/register/register.component.scss create mode 100644 src/app/views/register/register.component.spec.ts create mode 100644 src/app/views/register/register.component.ts diff --git a/package-lock.json b/package-lock.json index 8c79bcb..c295a4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,11 @@ "@angular/platform-browser": "^17.3.0", "@angular/platform-browser-dynamic": "^17.3.0", "@angular/router": "^17.3.0", + "@ng-bootstrap/ng-bootstrap": "^16.0.0", + "@popperjs/core": "^2.11.8", + "bootstrap": "^5.3.2", + "mdb-ui-kit": "^8.0.0", + "moment": "^2.30.1", "rxjs": "~7.8.0", "tslib": "^2.3.0", "zone.js": "~0.14.3" @@ -24,6 +29,7 @@ "@angular-devkit/build-angular": "^17.3.11", "@angular/cli": "^17.3.11", "@angular/compiler-cli": "^17.3.0", + "@angular/localize": "^17.3.0", "@types/jasmine": "~5.1.0", "jasmine-core": "~5.1.0", "karma": "~6.4.0", @@ -38,7 +44,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -358,7 +363,6 @@ "version": "17.3.12", "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-17.3.12.tgz", "integrity": "sha512-1F8M7nWfChzurb7obbvuE7mJXlHtY1UG58pcwcomVtpPb+kPavgAO8OEvJHYBMV+bzSxkXt5UIwL9lt9jHUxZA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/core": "7.23.9", @@ -387,7 +391,6 @@ "version": "7.23.9", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", - "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", @@ -418,14 +421,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, "license": "MIT" }, "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { "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" @@ -465,6 +466,75 @@ "rxjs": "^6.5.3 || ^7.4.0" } }, + "node_modules/@angular/localize": { + "version": "17.3.12", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-17.3.12.tgz", + "integrity": "sha512-b7J7zY/CgJhFVPtmu/pEjefU5SHuTy7lQgX6kTrJPaUSJ5i578R17xr4SwrWe7G4jzQwO6GXZZd17a62uNRyOA==", + "license": "MIT", + "dependencies": { + "@babel/core": "7.23.9", + "@types/babel__core": "7.20.5", + "fast-glob": "3.3.2", + "yargs": "^17.2.1" + }, + "bin": { + "localize-extract": "tools/bundles/src/extract/cli.js", + "localize-migrate": "tools/bundles/src/migrate/cli.js", + "localize-translate": "tools/bundles/src/translate/cli.js" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/compiler": "17.3.12", + "@angular/compiler-cli": "17.3.12" + } + }, + "node_modules/@angular/localize/node_modules/@babel/core": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", + "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.9", + "@babel/parser": "^7.23.9", + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@angular/localize/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/@angular/localize/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@angular/platform-browser": { "version": "17.3.12", "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-17.3.12.tgz", @@ -527,7 +597,6 @@ "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", @@ -542,7 +611,6 @@ "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -552,7 +620,6 @@ "version": "7.24.0", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.0.tgz", "integrity": "sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==", - "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", @@ -583,14 +650,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, "license": "MIT" }, "node_modules/@babel/core/node_modules/semver": { "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" @@ -600,7 +665,6 @@ "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.23.6", @@ -643,7 +707,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.25.9", @@ -660,7 +723,6 @@ "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" @@ -800,7 +862,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.25.9", @@ -814,7 +875,6 @@ "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.25.9", @@ -945,7 +1005,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -955,7 +1014,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -965,7 +1023,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -990,7 +1047,6 @@ "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.25.9", @@ -1004,7 +1060,6 @@ "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.26.0" @@ -2333,7 +2388,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.25.9", @@ -2348,7 +2402,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.25.9", @@ -2367,7 +2420,6 @@ "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.26.2", @@ -2384,7 +2436,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -2397,7 +2448,6 @@ "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.25.9", @@ -2952,7 +3002,6 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", @@ -2967,7 +3016,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -2977,7 +3025,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -2998,14 +3045,12 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -3032,6 +3077,23 @@ "node": ">= 0.4" } }, + "node_modules/@ng-bootstrap/ng-bootstrap": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-16.0.0.tgz", + "integrity": "sha512-+FJ3e6cX9DW2t7021Ji3oz433rk3+4jLfqzU+Jyx6/vJz1dIOaML3EAY6lYuW4TLiXgMPOMvs6KzPFALGh4Lag==", + "license": "MIT", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": "^17.0.0", + "@angular/core": "^17.0.0", + "@angular/forms": "^17.0.0", + "@angular/localize": "^17.0.0", + "@popperjs/core": "^2.11.8", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, "node_modules/@ngtools/webpack": { "version": "17.3.11", "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.11.tgz", @@ -3053,7 +3115,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -3067,7 +3128,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -3077,7 +3137,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -3404,6 +3463,16 @@ "node": ">=14" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.24.3", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.3.tgz", @@ -3820,6 +3889,47 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, "node_modules/@types/body-parser": { "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", @@ -4456,7 +4566,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -4466,7 +4575,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -4482,7 +4590,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", @@ -4496,7 +4603,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -4740,7 +4846,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -4821,6 +4926,25 @@ "dev": true, "license": "ISC" }, + "node_modules/bootstrap": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", + "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "license": "MIT", + "peerDependencies": { + "@popperjs/core": "^2.11.8" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -4836,7 +4960,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -4849,7 +4972,6 @@ "version": "4.24.2", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -5042,7 +5164,6 @@ "version": "1.0.30001676", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001676.tgz", "integrity": "sha512-Qz6zwGCiPghQXGJvgQAem79esjitvJ+CxSbSQkW9H/UX5hg8XM88d4lp2W+MEQ81j+Hip58Il+jGVdazk1z9cw==", - "dev": true, "funding": [ { "type": "opencollective", @@ -5087,7 +5208,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, "license": "MIT", "dependencies": { "anymatch": "~3.1.2", @@ -5178,7 +5298,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "license": "ISC", "dependencies": { "string-width": "^4.2.0", @@ -5193,7 +5312,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -5236,7 +5354,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -5249,7 +5366,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/colorette": { @@ -5399,7 +5515,6 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true, "license": "MIT" }, "node_modules/cookie": { @@ -5699,7 +5814,6 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -5918,14 +6032,12 @@ "version": "1.5.50", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.50.tgz", "integrity": "sha512-eMVObiUQ2LdgeO1F/ySTXsvqvxb6ZH2zPGaMYsWzRDdOddUa77tdmI0ltg+L16UpbWdhPmuF3wIQYyQq65WfZw==", - "dev": true, "license": "ISC" }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/emojis-list": { @@ -6173,7 +6285,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -6467,7 +6578,6 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -6491,7 +6601,6 @@ "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -6530,7 +6639,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -6767,7 +6875,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -6792,7 +6899,6 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -6802,7 +6908,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" @@ -6877,7 +6982,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -6897,7 +7001,6 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -7523,7 +7626,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" @@ -7568,7 +7670,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -7578,7 +7679,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -7588,7 +7688,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -7618,7 +7717,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -7892,7 +7990,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -7920,7 +8017,6 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -7950,7 +8046,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, "license": "MIT", "bin": { "json5": "lib/cli.js" @@ -8417,7 +8512,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, "license": "ISC", "dependencies": { "yallist": "^3.0.2" @@ -8486,6 +8580,12 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/mdb-ui-kit": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/mdb-ui-kit/-/mdb-ui-kit-8.0.0.tgz", + "integrity": "sha512-x4RVci4qe4na7X551I8UZ8UlhEuhIeYmwpOLWZeqNz1Z4nA1wnieXrM/81xI7Nx546UG04bk8T6xFk0be9engg==", + "license": "SEE LICENSE IN " + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -8530,7 +8630,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -8550,7 +8649,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -8564,7 +8662,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -8888,6 +8985,15 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/mrmime": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", @@ -8902,7 +9008,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/multicast-dns": { @@ -9156,7 +9261,6 @@ "version": "2.0.18", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", - "dev": true, "license": "MIT" }, "node_modules/nopt": { @@ -9194,7 +9298,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -9779,7 +9882,6 @@ "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": { @@ -10166,7 +10268,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -10316,7 +10417,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "license": "MIT", "dependencies": { "picomatch": "^2.2.1" @@ -10329,7 +10429,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -10342,7 +10441,6 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", - "dev": true, "license": "Apache-2.0" }, "node_modules/regenerate": { @@ -10444,7 +10542,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -10565,7 +10662,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -10648,7 +10744,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "funding": [ { "type": "github", @@ -10817,7 +10912,6 @@ "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" @@ -10833,7 +10927,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -10846,7 +10939,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, "license": "ISC" }, "node_modules/send": { @@ -11453,7 +11545,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -11484,7 +11575,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -11783,7 +11873,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -11871,7 +11960,6 @@ "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -12019,7 +12107,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", - "dev": true, "funding": [ { "type": "opencollective", @@ -13047,7 +13134,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -13057,14 +13143,12 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, "license": "ISC" }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, "license": "MIT", "dependencies": { "cliui": "^8.0.1", @@ -13083,7 +13167,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" diff --git a/package.json b/package.json index 5b43624..3a49b6d 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,11 @@ "@angular/platform-browser": "^17.3.0", "@angular/platform-browser-dynamic": "^17.3.0", "@angular/router": "^17.3.0", + "@ng-bootstrap/ng-bootstrap": "^16.0.0", + "@popperjs/core": "^2.11.8", + "bootstrap": "^5.3.2", + "mdb-ui-kit": "^8.0.0", + "moment": "^2.30.1", "rxjs": "~7.8.0", "tslib": "^2.3.0", "zone.js": "~0.14.3" @@ -26,6 +31,7 @@ "@angular-devkit/build-angular": "^17.3.11", "@angular/cli": "^17.3.11", "@angular/compiler-cli": "^17.3.0", + "@angular/localize": "^17.3.0", "@types/jasmine": "~5.1.0", "jasmine-core": "~5.1.0", "karma": "~6.4.0", diff --git a/src/app/app.component.html b/src/app/app.component.html index 36093e1..3277f50 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,336 +1,8 @@ - - - - - - - - - - - -
-
-
- -

Hello, {{ title }}

-

Congratulations! Your app is running. 🎉

-
- -
-
- @for (item of [ - { title: 'Explore the Docs', link: 'https://angular.dev' }, - { title: 'Learn with Tutorials', link: 'https://angular.dev/tutorials' }, - { title: 'CLI Docs', link: 'https://angular.dev/tools/cli' }, - { title: 'Angular Language Service', link: 'https://angular.dev/tools/language-service' }, - { title: 'Angular DevTools', link: 'https://angular.dev/tools/devtools' }, - ]; track item.title) { - - {{ item.title }} - - - - - } -
- -
-
-
- - - - - - - - - - - + + +
+ +
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 8ce01f2..4d48e72 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,13 +1,34 @@ -import { Component } from '@angular/core'; -import { RouterOutlet } from '@angular/router'; +import {HTTP_INTERCEPTORS} from "@angular/common/http"; +import {AuthInterceptorService} from "./services/auth-interceptor.service"; +import {AfterViewChecked, AfterViewInit, Component, OnInit} from "@angular/core"; +import {RouterOutlet} from "@angular/router"; +import {LoginComponent} from "./views/login/login.component"; +import {ApiService} from "./services/api.service"; +import {RegisterComponent} from "./views/register/register.component"; +import {AuthService} from "./services/auth.service"; +import {NgIf} from "@angular/common"; + + +/** Array of Http interceptor providers in outside-in order */ +export const httpInterceptorProviders = [ + { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptorService, multi: true }, +]; @Component({ selector: 'app-root', standalone: true, - imports: [RouterOutlet], + imports: [RouterOutlet, LoginComponent, RegisterComponent, NgIf], templateUrl: './app.component.html', styleUrl: './app.component.scss' }) export class AppComponent { + + constructor( + private apiService: ApiService, + public authService: AuthService + ) { + } + title = 'release-hive-fe'; + } diff --git a/src/app/app.config.ts b/src/app/app.config.ts index 6c6ef60..6c7c9ef 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -1,8 +1,15 @@ -import { ApplicationConfig } from '@angular/core'; -import { provideRouter } from '@angular/router'; +import {ApplicationConfig} from '@angular/core'; +import {provideRouter, provideRoutes, withComponentInputBinding} from '@angular/router'; -import { routes } from './app.routes'; +import {routes} from './app.routes'; +import {provideHttpClient, withInterceptors, withInterceptorsFromDi} from "@angular/common/http"; +import {httpInterceptorProviders} from "./app.component"; export const appConfig: ApplicationConfig = { - providers: [provideRouter(routes)] + + providers: [provideRouter(routes), + provideHttpClient(withInterceptorsFromDi()), + httpInterceptorProviders, + provideRouter(routes) + ] }; diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index dc39edb..5251d98 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -1,3 +1,15 @@ -import { Routes } from '@angular/router'; +import {Routes} from '@angular/router'; +import {DashboardComponent} from "./views/dashboard/dashboard.component"; +import {AppComponent} from "./app.component"; +import {LoginComponent} from "./views/login/login.component"; +import {AuthFormComponent} from "./views/beta/auth-form/auth-form.component"; +import {RegisterComponent} from "./views/register/register.component"; +import {AuthGuardService} from "./services/auth-guard.service"; -export const routes: Routes = []; +export const routes: Routes = [ + {path: '', redirectTo: '/dashboard', pathMatch: 'full'}, + {path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuardService]}, + {path: 'login', component: AuthFormComponent}, + {path: 'beta/authForm', component: AuthFormComponent}, + {path: '**', component: AppComponent}, +]; diff --git a/src/app/interface/auth.ts b/src/app/interface/auth.ts new file mode 100644 index 0000000..e5d3093 --- /dev/null +++ b/src/app/interface/auth.ts @@ -0,0 +1,4 @@ +export interface TokenResponse { + token: string; + expiresIn: number; +} diff --git a/src/app/interface/user.ts b/src/app/interface/user.ts new file mode 100644 index 0000000..6867225 --- /dev/null +++ b/src/app/interface/user.ts @@ -0,0 +1,6 @@ +export interface UserData { + username: string | null; + uuid: string | null; + email: string | null; + createdAt: Date | null; +} diff --git a/src/app/services/api.service.spec.ts b/src/app/services/api.service.spec.ts new file mode 100644 index 0000000..c0310ae --- /dev/null +++ b/src/app/services/api.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ApiService } from './api.service'; + +describe('ApiService', () => { + let service: ApiService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ApiService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/services/api.service.ts b/src/app/services/api.service.ts new file mode 100644 index 0000000..79845ec --- /dev/null +++ b/src/app/services/api.service.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from "@angular/common/http"; +import {UserData} from "../interface/user"; + +@Injectable({ + providedIn: 'root' +}) +export class ApiService { + + private apiUrl = 'http://localhost:8080/api/'; + + constructor( + private http: HttpClient + ) { + + } + + + // v1 USERS + getCurrentUser() { + return this.http.get(this.apiUrl + 'v1/users/me'); + } + + getAllUsers() { + return this.http.get(this.apiUrl + 'v1/users/all'); + } +} diff --git a/src/app/services/auth-guard.service.spec.ts b/src/app/services/auth-guard.service.spec.ts new file mode 100644 index 0000000..35afd37 --- /dev/null +++ b/src/app/services/auth-guard.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AuthGuardService } from './auth-guard.service'; + +describe('AuthGuardService', () => { + let service: AuthGuardService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AuthGuardService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/services/auth-guard.service.ts b/src/app/services/auth-guard.service.ts new file mode 100644 index 0000000..b91fd9e --- /dev/null +++ b/src/app/services/auth-guard.service.ts @@ -0,0 +1,22 @@ +import { Injectable } from '@angular/core'; +import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from "@angular/router"; +import {AuthService} from "./auth.service"; + +@Injectable({ + providedIn: 'root' +}) +export class AuthGuardService implements CanActivate { + + constructor(private router: Router, private authService: AuthService) { } + + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { + if (this.authService.isLoggedIn()) { + // logged in so return true + return true; + } + + // not logged in so redirect to login page with the return url + this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }}); + return false; + } +} diff --git a/src/app/services/auth-interceptor.service.spec.ts b/src/app/services/auth-interceptor.service.spec.ts new file mode 100644 index 0000000..03e16c3 --- /dev/null +++ b/src/app/services/auth-interceptor.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AuthInterceptorService } from './auth-interceptor.service'; + +describe('AuthInterceptorService', () => { + let service: AuthInterceptorService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AuthInterceptorService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/services/auth-interceptor.service.ts b/src/app/services/auth-interceptor.service.ts new file mode 100644 index 0000000..c4f127e --- /dev/null +++ b/src/app/services/auth-interceptor.service.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@angular/core'; +import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from "@angular/common/http"; +import {Observable} from "rxjs"; + +@Injectable({ + providedIn: 'root' +}) +export class AuthInterceptorService implements HttpInterceptor { + + intercept (req: HttpRequest, next: HttpHandler): Observable> { + + const tokenId = localStorage.getItem('tokenId'); + + if (!!tokenId) { + const cloned = req.clone({ + headers: req.headers.set("Authorization", + "Bearer " + tokenId) + }); + return next.handle(cloned); + } + + return next.handle(req); + } + + + constructor() { } +} diff --git a/src/app/services/auth.service.spec.ts b/src/app/services/auth.service.spec.ts new file mode 100644 index 0000000..f1251ca --- /dev/null +++ b/src/app/services/auth.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AuthService } from './auth.service'; + +describe('AuthService', () => { + let service: AuthService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AuthService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts new file mode 100644 index 0000000..f61cfa0 --- /dev/null +++ b/src/app/services/auth.service.ts @@ -0,0 +1,67 @@ +import { Injectable } from '@angular/core'; +import {TokenResponse} from "../interface/auth"; +import moment from "moment"; +import {HttpClient} from "@angular/common/http"; +import {tap} from "rxjs"; + +@Injectable({ + providedIn: 'root' +}) +export class AuthService { + + private apiUrl = 'http://localhost:8080/api/'; + + constructor( + private httpClient: HttpClient + ) { + + } + + public register(email: string, username: string, password: string) { + + const body = { + email: email, + username: username, + password: password + } + return this.httpClient.post(this.apiUrl + 'v1/auth/register', body); + } + + public authenticate(email: string, password: string) { + + const body = { + email: email, + password: password + } + + return this.httpClient.post(this.apiUrl + 'v1/auth/login', body) + .pipe(tap(token => {this.setSession(token)})); + } + + private setSession(res: TokenResponse) { + const expiresAt = moment().add(res.expiresIn, 'milliseconds'); + + localStorage.setItem('tokenId', res.token); + localStorage.setItem("expiresAt", JSON.stringify(expiresAt.valueOf()) ); + } + + + public logout() { + localStorage.removeItem("tokenId"); + localStorage.removeItem("expiresAt"); + } + + public isLoggedIn() { + return moment().isBefore(this.getExpiration()); + } + + isLoggedOut() { + return !this.isLoggedIn(); + } + + getExpiration() { + const expiration = localStorage.getItem("expiresAt"); + const expiresAt = JSON.parse(expiration ? expiration : '{}'); + return moment(expiresAt); + } +} diff --git a/src/app/views/beta/auth-form/auth-form.component.html b/src/app/views/beta/auth-form/auth-form.component.html new file mode 100644 index 0000000..850271c --- /dev/null +++ b/src/app/views/beta/auth-form/auth-form.component.html @@ -0,0 +1,4 @@ + + + + diff --git a/src/app/views/beta/auth-form/auth-form.component.scss b/src/app/views/beta/auth-form/auth-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/views/beta/auth-form/auth-form.component.spec.ts b/src/app/views/beta/auth-form/auth-form.component.spec.ts new file mode 100644 index 0000000..b967099 --- /dev/null +++ b/src/app/views/beta/auth-form/auth-form.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AuthFormComponent } from './auth-form.component'; + +describe('AuthFormComponent', () => { + let component: AuthFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [AuthFormComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(AuthFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/views/beta/auth-form/auth-form.component.ts b/src/app/views/beta/auth-form/auth-form.component.ts new file mode 100644 index 0000000..99255ea --- /dev/null +++ b/src/app/views/beta/auth-form/auth-form.component.ts @@ -0,0 +1,31 @@ +import { Component } from '@angular/core'; +import {LoginComponent} from "../../login/login.component"; +import {NgIf} from "@angular/common"; +import {RegisterComponent} from "../../register/register.component"; +import {AuthService} from "../../../services/auth.service"; + +@Component({ + selector: 'app-auth-form', + standalone: true, + imports: [ + LoginComponent, + NgIf, + RegisterComponent + ], + templateUrl: './auth-form.component.html', + styleUrl: './auth-form.component.scss' +}) +export class AuthFormComponent { + + constructor(private authService: AuthService) { + } + + isLoggedIn = false; + + ngOnInit() { + setTimeout(() => { + this.isLoggedIn = this.authService.isLoggedIn(); + }); + } + +} diff --git a/src/app/views/dashboard/dashboard.component.html b/src/app/views/dashboard/dashboard.component.html new file mode 100644 index 0000000..cbb0ee1 --- /dev/null +++ b/src/app/views/dashboard/dashboard.component.html @@ -0,0 +1,10 @@ +
+
+

+ Username: {{userData.username}} | + eMail: {{userData.email}} | + UUID: {{userData.uuid}} | + Created At: {{userData.createdAt}} +

+
+
diff --git a/src/app/views/dashboard/dashboard.component.scss b/src/app/views/dashboard/dashboard.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/views/dashboard/dashboard.component.spec.ts b/src/app/views/dashboard/dashboard.component.spec.ts new file mode 100644 index 0000000..815d1b8 --- /dev/null +++ b/src/app/views/dashboard/dashboard.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DashboardComponent } from './dashboard.component'; + +describe('DashboardComponent', () => { + let component: DashboardComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [DashboardComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(DashboardComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/views/dashboard/dashboard.component.ts b/src/app/views/dashboard/dashboard.component.ts new file mode 100644 index 0000000..9d6f9ef --- /dev/null +++ b/src/app/views/dashboard/dashboard.component.ts @@ -0,0 +1,46 @@ +import {Component, OnInit} from '@angular/core'; +import {UserData} from "../../interface/user"; +import {AuthService} from "../../services/auth.service"; +import {ApiService} from "../../services/api.service"; +import {NgbDatepicker, NgbDateStruct} from "@ng-bootstrap/ng-bootstrap"; +import {FormsModule} from "@angular/forms"; +import {NgIf} from "@angular/common"; +import {Router} from "@angular/router"; + +@Component({ + selector: 'app-dashboard', + standalone: true, + imports: [ + NgbDatepicker, + FormsModule, + NgIf + ], + templateUrl: './dashboard.component.html', + styleUrl: './dashboard.component.scss' +}) +export class DashboardComponent implements OnInit { + + isLoggedIn = false; + + userData: UserData = { + uuid: null, + username: null, + email: null, + createdAt: null + } + + constructor(private authService: AuthService, private apiService: ApiService, private router: Router) { + } + + ngOnInit(): void { + if (this.authService.isLoggedIn()) { + this.apiService.getCurrentUser().subscribe(res => { + this.userData = res; + this.isLoggedIn = true; + }) + } else { + this.router.navigate(['/login']).then(); + } + } + +} diff --git a/src/app/views/login/login.component.html b/src/app/views/login/login.component.html new file mode 100644 index 0000000..c9767cb --- /dev/null +++ b/src/app/views/login/login.component.html @@ -0,0 +1,68 @@ +
+
+

+ Login +

+
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+ +
+
+
+ +
+
+ +
+
+
+
+
diff --git a/src/app/views/login/login.component.scss b/src/app/views/login/login.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/views/login/login.component.spec.ts b/src/app/views/login/login.component.spec.ts new file mode 100644 index 0000000..1e19e5d --- /dev/null +++ b/src/app/views/login/login.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LoginComponent } from './login.component'; + +describe('LoginComponent', () => { + let component: LoginComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [LoginComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(LoginComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/views/login/login.component.ts b/src/app/views/login/login.component.ts new file mode 100644 index 0000000..33b7caf --- /dev/null +++ b/src/app/views/login/login.component.ts @@ -0,0 +1,70 @@ +import {Component, OnInit} from '@angular/core'; +import {FormsModule} from '@angular/forms'; +import {AuthService} from "../../services/auth.service"; +import {UserData} from "../../interface/user"; +import {ApiService} from "../../services/api.service"; +import {NgIf} from "@angular/common"; +import {Router} from "@angular/router"; + +@Component({ + selector: 'app-login', + standalone: true, + imports: [FormsModule, NgIf], + templateUrl: './login.component.html', + styleUrl: './login.component.scss' +}) +export class LoginComponent implements OnInit { + + email = ""; + password = ""; + + isLoggedIn = false; + + loggedUser: UserData | null = { + username: null, + uuid: null, + email: null, + createdAt: null + }; + + constructor( + public authService: AuthService, + private apiService: ApiService, + private router: Router + ) { + } + + public attemptLogin() { + this.authService.authenticate(this.email, this.password) + .subscribe(token => { + this.router.navigate(['/']).then(); + }); + } + + ngOnInit(): void { + if (this.authService.isLoggedOut()) { + this.authService.logout(); + } + + if (this.authService.isLoggedIn()) { + this.setLoggedIn(); + } + } + + setLoggedIn() { + this.apiService.getCurrentUser().subscribe(res => { + this.isLoggedIn = true; + this.loggedUser = res; + this.email = res.email ? res.email : ''; + }); + } + + logOut() { + this.authService.logout(); + this.reloadCurrentRoute(); + } + + reloadCurrentRoute() { + window.location.reload() + } +} diff --git a/src/app/views/register/register.component.html b/src/app/views/register/register.component.html new file mode 100644 index 0000000..7690d5e --- /dev/null +++ b/src/app/views/register/register.component.html @@ -0,0 +1,55 @@ +
+
+

+ Register +

+
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+ +
+
+ +
+
+
+
diff --git a/src/app/views/register/register.component.scss b/src/app/views/register/register.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/views/register/register.component.spec.ts b/src/app/views/register/register.component.spec.ts new file mode 100644 index 0000000..3a5dfc8 --- /dev/null +++ b/src/app/views/register/register.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RegisterComponent } from './register.component'; + +describe('RegisterComponent', () => { + let component: RegisterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [RegisterComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(RegisterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/views/register/register.component.ts b/src/app/views/register/register.component.ts new file mode 100644 index 0000000..bd8f0d5 --- /dev/null +++ b/src/app/views/register/register.component.ts @@ -0,0 +1,30 @@ +import { Component } from '@angular/core'; +import {FormsModule} from "@angular/forms"; +import {AuthService} from "../../services/auth.service"; + +@Component({ + selector: 'app-register', + standalone: true, + imports: [ + FormsModule + ], + templateUrl: './register.component.html', + styleUrl: './register.component.scss' +}) +export class RegisterComponent { + + email = ""; + password= ""; + username= ""; + + constructor(private authService: AuthService) { + } + + attemptRegister(){ + this.authService.register(this.email, this.username, this.password).subscribe(() => { + this.authService.logout(); + this.authService.authenticate(this.email, this.password); + }); + } + +} diff --git a/src/main.ts b/src/main.ts index 35b00f3..ee35435 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,3 +1,5 @@ +/// + import { bootstrapApplication } from '@angular/platform-browser'; import { appConfig } from './app/app.config'; import { AppComponent } from './app/app.component'; diff --git a/src/styles.scss b/src/styles.scss index 90d4ee0..03d7d41 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1 +1,10 @@ /* You can add global styles to this file, and also import other style files */ + +@import 'mdb-ui-kit/css/mdb.min.css'; +@import 'bootstrap/scss/mixins'; +@import 'bootstrap/scss/functions'; +@import 'bootstrap/scss/variables'; +@import 'bootstrap/scss/variables-dark'; +@import 'bootstrap/scss/maps'; +@import 'bootstrap/scss/utilities'; +@import 'bootstrap/scss/grid'; diff --git a/tsconfig.app.json b/tsconfig.app.json index 374cc9d..ec26f70 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -3,7 +3,9 @@ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "./out-tsc/app", - "types": [] + "types": [ + "@angular/localize" + ] }, "files": [ "src/main.ts" diff --git a/tsconfig.spec.json b/tsconfig.spec.json index be7e9da..c63b698 100644 --- a/tsconfig.spec.json +++ b/tsconfig.spec.json @@ -4,7 +4,8 @@ "compilerOptions": { "outDir": "./out-tsc/spec", "types": [ - "jasmine" + "jasmine", + "@angular/localize" ] }, "include": [