Compare commits

..

No commits in common. "9231bd0d4a1528e7c9b99342faed139e33397d73" and "380b2efa0d0bad876e1ab3406fa724dbe1a7279c" have entirely different histories.

11 changed files with 429 additions and 482 deletions

313
package-lock.json generated
View File

@ -1,35 +1,34 @@
{ {
"name": "frontend", "name": "frontend",
"version": "1.0.0-b8", "version": "1.0.0-b7",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "frontend", "name": "frontend",
"version": "1.0.0-b8", "version": "1.0.0-b7",
"dependencies": { "dependencies": {
"@angular/animations": "^18.2.7", "@angular/animations": "^18.2.6",
"@angular/cdk": "~18.2.7", "@angular/cdk": "~18.2.6",
"@angular/cdk-experimental": "^18.2.7", "@angular/cdk-experimental": "^18.2.6",
"@angular/common": "^18.2.7", "@angular/common": "^18.2.6",
"@angular/compiler": "^18.2.7", "@angular/compiler": "^18.2.6",
"@angular/core": "^18.2.7", "@angular/core": "^18.2.6",
"@angular/forms": "^18.2.7", "@angular/forms": "^18.2.6",
"@angular/material": "~18.2.7", "@angular/material": "~18.2.6",
"@angular/platform-browser": "^18.2.7", "@angular/platform-browser": "^18.2.6",
"@angular/platform-browser-dynamic": "^18.2.7", "@angular/platform-browser-dynamic": "^18.2.6",
"@angular/router": "^18.2.7", "@angular/router": "^18.2.6",
"@dhutaryan/ngx-mat-timepicker": "^18.0.2", "@dhutaryan/ngx-mat-timepicker": "^18.0.2",
"@progress/kendo-date-math": "^1.5.13", "@progress/kendo-date-math": "^1.5.13",
"ngx-toastr": "^19.0.0",
"rxjs": "~7.8.1", "rxjs": "~7.8.1",
"tslib": "^2.7.0", "tslib": "^2.7.0",
"zone.js": "^0.14.10" "zone.js": "^0.14.10"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "^18.2.7", "@angular-devkit/build-angular": "^18.2.6",
"@angular/cli": "^18.2.7", "@angular/cli": "^18.2.6",
"@angular/compiler-cli": "^18.2.7", "@angular/compiler-cli": "^18.2.6",
"@types/jasmine": "~5.1.4", "@types/jasmine": "~5.1.4",
"jasmine-core": "~5.3.0", "jasmine-core": "~5.3.0",
"karma": "~6.4.4", "karma": "~6.4.4",
@ -54,13 +53,13 @@
} }
}, },
"node_modules/@angular-devkit/architect": { "node_modules/@angular-devkit/architect": {
"version": "0.1802.7", "version": "0.1802.6",
"resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.7.tgz", "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.6.tgz",
"integrity": "sha512-kpcgXnepEXcoxDTbqbGj7Hg1WJLWj1HLR3/FKmC5TbpBf1xiLxiqfkQNwz3BbE/W9JWMLdrXr3GI9O3O2gWPLg==", "integrity": "sha512-oF7cPFdTLxeuvXkK/opSdIxZ1E4LrBbmuytQ/nCoAGOaKBWdqvwagRZ6jVhaI0Gwu48rkcV7Zhesg/ESNnROdw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@angular-devkit/core": "18.2.7", "@angular-devkit/core": "18.2.6",
"rxjs": "7.8.1" "rxjs": "7.8.1"
}, },
"engines": { "engines": {
@ -70,17 +69,17 @@
} }
}, },
"node_modules/@angular-devkit/build-angular": { "node_modules/@angular-devkit/build-angular": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.2.6.tgz",
"integrity": "sha512-u8PriYdgddK7k+OS/pOFPD1v4Iu5bztUJZXZVcGeXBZFFdnGFFzKmQw9mfcyGvTMJp2ABgBuuJT0YqYgNfAhzw==", "integrity": "sha512-u12cJZttgs5j7gICHWSmcaTCu0EFXEzKqI8nkYCwq2MtuJlAXiMQSXYuEP9OU3Go4vMAPtQh2kShyOWCX5b4EQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ampproject/remapping": "2.3.0", "@ampproject/remapping": "2.3.0",
"@angular-devkit/architect": "0.1802.7", "@angular-devkit/architect": "0.1802.6",
"@angular-devkit/build-webpack": "0.1802.7", "@angular-devkit/build-webpack": "0.1802.6",
"@angular-devkit/core": "18.2.7", "@angular-devkit/core": "18.2.6",
"@angular/build": "18.2.7", "@angular/build": "18.2.6",
"@babel/core": "7.25.2", "@babel/core": "7.25.2",
"@babel/generator": "7.25.0", "@babel/generator": "7.25.0",
"@babel/helper-annotate-as-pure": "7.24.7", "@babel/helper-annotate-as-pure": "7.24.7",
@ -91,7 +90,7 @@
"@babel/preset-env": "7.25.3", "@babel/preset-env": "7.25.3",
"@babel/runtime": "7.25.0", "@babel/runtime": "7.25.0",
"@discoveryjs/json-ext": "0.6.1", "@discoveryjs/json-ext": "0.6.1",
"@ngtools/webpack": "18.2.7", "@ngtools/webpack": "18.2.6",
"@vitejs/plugin-basic-ssl": "1.1.0", "@vitejs/plugin-basic-ssl": "1.1.0",
"ansi-colors": "4.1.3", "ansi-colors": "4.1.3",
"autoprefixer": "10.4.20", "autoprefixer": "10.4.20",
@ -241,13 +240,13 @@
"license": "0BSD" "license": "0BSD"
}, },
"node_modules/@angular-devkit/build-webpack": { "node_modules/@angular-devkit/build-webpack": {
"version": "0.1802.7", "version": "0.1802.6",
"resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1802.7.tgz", "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1802.6.tgz",
"integrity": "sha512-VrtbrhZ+dht3f0GjtfRLRGRN4XHN/W+/bA9DqckdxVS6SydsrCWNHonvEPmOs4jJmGIGXIu6tUBMcWleTao2sg==", "integrity": "sha512-JMLcXFaitJplwZMKkqhbYirINCRD6eOPZuIGaIOVynXYGWgvJkLT9t5C2wm9HqSLtp1K7NcYG2Y7PtTVR4krnQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@angular-devkit/architect": "0.1802.7", "@angular-devkit/architect": "0.1802.6",
"rxjs": "7.8.1" "rxjs": "7.8.1"
}, },
"engines": { "engines": {
@ -261,9 +260,9 @@
} }
}, },
"node_modules/@angular-devkit/core": { "node_modules/@angular-devkit/core": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.6.tgz",
"integrity": "sha512-1ZTi4A6tEC2bkJ/puCIdIPYhesnlCVOMSDJL/lZAd0hC6X22T4pwu0AEvue7mcP5NbXpQDiBaXOZ3MmCA8PwOA==", "integrity": "sha512-la4CFvs5PcRWSkQ/H7TB5cPZirFVA9GoWk5LzIk8si6VjWBJRm8b3keKJoC9LlNeABRUIR5z0ocYkyQQUhdMfg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -307,13 +306,13 @@
} }
}, },
"node_modules/@angular-devkit/schematics": { "node_modules/@angular-devkit/schematics": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.6.tgz",
"integrity": "sha512-j7198lpkOXMG+Gyfln/5aDgBZV7m4pWMzHFhkO3+w3cbCNUN1TVZW0SyJcF+CYaxANzTbuumfvpsYc/fTeAGLw==", "integrity": "sha512-uIttrQ2cQ2PWAFFVPeCoNR8xvs7tPJ2i8gzqsIwYdge107xDC6u9CqfgmBqPDSFpWj+IiC2Jwcm8Z4HYKU4+7A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@angular-devkit/core": "18.2.7", "@angular-devkit/core": "18.2.6",
"jsonc-parser": "3.3.1", "jsonc-parser": "3.3.1",
"magic-string": "0.30.11", "magic-string": "0.30.11",
"ora": "5.4.1", "ora": "5.4.1",
@ -326,9 +325,9 @@
} }
}, },
"node_modules/@angular/animations": { "node_modules/@angular/animations": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.2.6.tgz",
"integrity": "sha512-5B7qD1K+kKOf9lgJT4VNMft3IK2BnRHjN1S6l38ywzQ/nxpmCG7f+qKAAU6CpCywhNUBeXW0hVXTMuMNPVOcQQ==", "integrity": "sha512-vy9wy+Q9beiRxkEO8wNxFQ63AqAujGvk8AUHepxxIT7QNNc512TNKz8uH+feWDPO38Dm2obwYQHMGzs3WO7pUA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"tslib": "^2.3.0" "tslib": "^2.3.0"
@ -337,18 +336,18 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0" "node": "^18.19.1 || ^20.11.1 || >=22.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/core": "18.2.7" "@angular/core": "18.2.6"
} }
}, },
"node_modules/@angular/build": { "node_modules/@angular/build": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@angular/build/-/build-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.2.6.tgz",
"integrity": "sha512-oq6JsVxLP9/w9F2IjKroJwPB9CdlMblu2Xhfq/qQZRSUuM8Ppt1svr2FBTo1HrLIbosqukkVcSSdmKYDneo+cg==", "integrity": "sha512-TQzX6Mi7uXFvmz7+OVl4Za7WawYPcx+B5Ewm6IY/DdMyB9P/Z4tbKb1LO+ynWUXYwm7avXo6XQQ4m5ArDY5F/A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ampproject/remapping": "2.3.0", "@ampproject/remapping": "2.3.0",
"@angular-devkit/architect": "0.1802.7", "@angular-devkit/architect": "0.1802.6",
"@babel/core": "7.25.2", "@babel/core": "7.25.2",
"@babel/helper-annotate-as-pure": "7.24.7", "@babel/helper-annotate-as-pure": "7.24.7",
"@babel/helper-split-export-declaration": "7.24.7", "@babel/helper-split-export-declaration": "7.24.7",
@ -428,9 +427,9 @@
} }
}, },
"node_modules/@angular/cdk": { "node_modules/@angular/cdk": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.2.6.tgz",
"integrity": "sha512-Dfl37WBLeEUURQrDeuMcOgX2bkQJ+BGMOlr1qsFXzUWHH+qgYW2YwO1rbna/rjxyeFzc2Sy569dYRzNPqMewzg==", "integrity": "sha512-Gfq/iv4zhlKYpdQkDaBRwxI71NHNUHM1Cs1XhnZ0/oFct5HXvSv1RHRGTKqBJLLACaAPzZKXJ/UglLoyO5CNiQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"tslib": "^2.3.0" "tslib": "^2.3.0"
@ -445,31 +444,31 @@
} }
}, },
"node_modules/@angular/cdk-experimental": { "node_modules/@angular/cdk-experimental": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@angular/cdk-experimental/-/cdk-experimental-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@angular/cdk-experimental/-/cdk-experimental-18.2.6.tgz",
"integrity": "sha512-ugWpenAfED8RsCafuy7Gz28cTGwp/fNsiwLm9h4Hj7iWP5KNfNUWdocFBnegDXyiiqyNxml4DxH5XZjqFrqCyQ==", "integrity": "sha512-EXrDNqxmodxMNEiqGkNfRmAuZ9S0x4Xhegve1lZkAvWfk81aUjz18B36nbWaQ7zUJJvRFT3tvI/ZLApjo+wBMQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"tslib": "^2.3.0" "tslib": "^2.3.0"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/cdk": "18.2.7", "@angular/cdk": "18.2.6",
"@angular/core": "^18.0.0 || ^19.0.0" "@angular/core": "^18.0.0 || ^19.0.0"
} }
}, },
"node_modules/@angular/cli": { "node_modules/@angular/cli": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.6.tgz",
"integrity": "sha512-KoWgSvhRsU05A2m6B7jw1kdpyoS+Ce5GGLW6xcnX7VF2AckW54vYd/8ZkgpzQrKfvIpVblYd4KJGizKoaLZ5jA==", "integrity": "sha512-tdXsnV/w+Rgu8q0zFsLU5L9ImTVqrTol1vppHaQkJ/vuoHy+s8ZEbBqhVrO/ffosNb2xseUybGYvqMS4zkNQjg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@angular-devkit/architect": "0.1802.7", "@angular-devkit/architect": "0.1802.6",
"@angular-devkit/core": "18.2.7", "@angular-devkit/core": "18.2.6",
"@angular-devkit/schematics": "18.2.7", "@angular-devkit/schematics": "18.2.6",
"@inquirer/prompts": "5.3.8", "@inquirer/prompts": "5.3.8",
"@listr2/prompt-adapter-inquirer": "2.0.15", "@listr2/prompt-adapter-inquirer": "2.0.15",
"@schematics/angular": "18.2.7", "@schematics/angular": "18.2.6",
"@yarnpkg/lockfile": "1.1.0", "@yarnpkg/lockfile": "1.1.0",
"ini": "4.1.3", "ini": "4.1.3",
"jsonc-parser": "3.3.1", "jsonc-parser": "3.3.1",
@ -492,9 +491,9 @@
} }
}, },
"node_modules/@angular/common": { "node_modules/@angular/common": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@angular/common/-/common-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.2.6.tgz",
"integrity": "sha512-5vDBmBR2JcIxHVEDunKXNU+T+OvTGiHZTSo35GFOHJxKFgX5g6+0tJBZunK04oBZGbJQUmp3pg2kMvuKKjZnkQ==", "integrity": "sha512-89793ow+wrI1c7C6kyMbnweLNIZHzXthosxAEjipRZGBrqBYjvTtkE45Fl+5yBa3JO7bAhyGkUnEoyvWtZIAEA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"tslib": "^2.3.0" "tslib": "^2.3.0"
@ -503,14 +502,14 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0" "node": "^18.19.1 || ^20.11.1 || >=22.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/core": "18.2.7", "@angular/core": "18.2.6",
"rxjs": "^6.5.3 || ^7.4.0" "rxjs": "^6.5.3 || ^7.4.0"
} }
}, },
"node_modules/@angular/compiler": { "node_modules/@angular/compiler": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.2.6.tgz",
"integrity": "sha512-XemlYyRGnu/HrICtXwTPmGtyOrI8BhbGg/HMiJ7sVx40AeEIX0uyDgnu9Gc5OjmtDqZZ8Qftg1sQAxaCVjLb1w==", "integrity": "sha512-3tX2/Qw+bZ8XzKitviH8jzNGyY0uohhehhBB57OJOCc+yr4ojy/7SYFnun1lSsRnDztdCE461641X4iQLCQ94w==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"tslib": "^2.3.0" "tslib": "^2.3.0"
@ -519,7 +518,7 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0" "node": "^18.19.1 || ^20.11.1 || >=22.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/core": "18.2.7" "@angular/core": "18.2.6"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"@angular/core": { "@angular/core": {
@ -528,9 +527,9 @@
} }
}, },
"node_modules/@angular/compiler-cli": { "node_modules/@angular/compiler-cli": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.2.6.tgz",
"integrity": "sha512-U7cveObj+rrXH5EC8egAhATCeAAcOceEQDTVIOWmBa0qMR4hOMjtI2XUS2QRuI1Q+fQZ2hVEOW95WVLvEMsANA==", "integrity": "sha512-b5x9STfjNiNM/S0D+CnqRP9UOxPtSz1+RlCH5WdOMiW/p8j5p6dBix8YYgTe6Wg3OD7eItD2pnFQKgF/dWiopA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -552,14 +551,14 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0" "node": "^18.19.1 || ^20.11.1 || >=22.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/compiler": "18.2.7", "@angular/compiler": "18.2.6",
"typescript": ">=5.4 <5.6" "typescript": ">=5.4 <5.6"
} }
}, },
"node_modules/@angular/core": { "node_modules/@angular/core": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.6.tgz",
"integrity": "sha512-hLOxgxLiyWm9iVHBsUsJfx1hDsXWZnfJBlr+N7cev53f0CDoPfbshqq6KV+JFqXFDguzR9dKHm1ewT1jK3e6Tw==", "integrity": "sha512-PjFad2j4YBwLVTw+0Te8CJCa/tV0W8caTHG8aOjj3ObdL6ihGI+FKnwerLc9RVzDFd14BOO4C6/+LbOQAh3Ltw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"tslib": "^2.3.0" "tslib": "^2.3.0"
@ -573,9 +572,9 @@
} }
}, },
"node_modules/@angular/forms": { "node_modules/@angular/forms": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.2.6.tgz",
"integrity": "sha512-WO3c9/OA7ekBnDBgmvi5TlHshOt5S4NREIP+/VVyuRgg28BwUWyO/Nqh19nguE1UNNRt6OMLkT6NSV2ewhcXUg==", "integrity": "sha512-quGkUqTxlBaLB8C/RnpfFG57fdmNF5RQ+368N89Ma++2lpIsVAHaGZZn4yOyo3wNYaM2jBxNqaYxOzZNUl5Tig==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"tslib": "^2.3.0" "tslib": "^2.3.0"
@ -584,23 +583,23 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0" "node": "^18.19.1 || ^20.11.1 || >=22.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "18.2.7", "@angular/common": "18.2.6",
"@angular/core": "18.2.7", "@angular/core": "18.2.6",
"@angular/platform-browser": "18.2.7", "@angular/platform-browser": "18.2.6",
"rxjs": "^6.5.3 || ^7.4.0" "rxjs": "^6.5.3 || ^7.4.0"
} }
}, },
"node_modules/@angular/material": { "node_modules/@angular/material": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@angular/material/-/material-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@angular/material/-/material-18.2.6.tgz",
"integrity": "sha512-mgPj2TCIrsngmu3iNnoaPc6su7uPv+NPCv9HaiKhTx4QGae8EW+RvUxEZJvh4Qaym1fJTi3hjnVeWvQDLQt4CA==", "integrity": "sha512-ObxC/vomSb9QF3vIztuiInQzws+D6u09Dhfx6uNFjtyICqxEFpF7+Qx7QVDWrsuXOgxZTKgacK8f46iV8hWUfg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"tslib": "^2.3.0" "tslib": "^2.3.0"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/animations": "^18.0.0 || ^19.0.0", "@angular/animations": "^18.0.0 || ^19.0.0",
"@angular/cdk": "18.2.7", "@angular/cdk": "18.2.6",
"@angular/common": "^18.0.0 || ^19.0.0", "@angular/common": "^18.0.0 || ^19.0.0",
"@angular/core": "^18.0.0 || ^19.0.0", "@angular/core": "^18.0.0 || ^19.0.0",
"@angular/forms": "^18.0.0 || ^19.0.0", "@angular/forms": "^18.0.0 || ^19.0.0",
@ -609,9 +608,9 @@
} }
}, },
"node_modules/@angular/platform-browser": { "node_modules/@angular/platform-browser": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.2.6.tgz",
"integrity": "sha512-xgj2DH/isFrMZ73dJJm89NRnWBI3AHtugQrZbIapkKBdEt/C1o4SR2W2cV4mPb9o+ELnWurfrxFt9o/q2vnVLw==", "integrity": "sha512-RA8UMiYNLga+QMwpKcDw1357gYPfPyY/rmLeezMak//BbsENFYQOJ4Z6DBOBNiPlHxmBsUJMGaKdlpQhfCROyQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"tslib": "^2.3.0" "tslib": "^2.3.0"
@ -620,9 +619,9 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0" "node": "^18.19.1 || ^20.11.1 || >=22.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/animations": "18.2.7", "@angular/animations": "18.2.6",
"@angular/common": "18.2.7", "@angular/common": "18.2.6",
"@angular/core": "18.2.7" "@angular/core": "18.2.6"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"@angular/animations": { "@angular/animations": {
@ -631,9 +630,9 @@
} }
}, },
"node_modules/@angular/platform-browser-dynamic": { "node_modules/@angular/platform-browser-dynamic": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.2.6.tgz",
"integrity": "sha512-BDldzUKjnUjo0NW5gHjBY6CeJP1bWVfF1h/T3idyYG+F4Lxlb3aykRgLWXg4srNLY1KqE7XOYUmgc5cV613bgw==", "integrity": "sha512-kGBU3FNc+DF9r33hwHZqiWoZgQbCDdEIucU0NCLCIg0Hw6/Q9Hr2ndjxQI+WynCPg0JeBn34jpouvpeJer3YDQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"tslib": "^2.3.0" "tslib": "^2.3.0"
@ -642,16 +641,16 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0" "node": "^18.19.1 || ^20.11.1 || >=22.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "18.2.7", "@angular/common": "18.2.6",
"@angular/compiler": "18.2.7", "@angular/compiler": "18.2.6",
"@angular/core": "18.2.7", "@angular/core": "18.2.6",
"@angular/platform-browser": "18.2.7" "@angular/platform-browser": "18.2.6"
} }
}, },
"node_modules/@angular/router": { "node_modules/@angular/router": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@angular/router/-/router-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.2.6.tgz",
"integrity": "sha512-TXE8Aw63hDp3PEaNu4B1DMNvlS0uCzs36o/OSCCmewmLnzyJygkgi4jeEj20FsWPAQOUj5g5tnCYgxz1IRrCUg==", "integrity": "sha512-t57Sqja8unHhZlPr+4CWnQacuox2M4p2pMHps+31wt337qH6mKf4jqDmK0dE/MFdRyKjT2a2E/2NwtxXxcWNuw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"tslib": "^2.3.0" "tslib": "^2.3.0"
@ -660,9 +659,9 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0" "node": "^18.19.1 || ^20.11.1 || >=22.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "18.2.7", "@angular/common": "18.2.6",
"@angular/core": "18.2.7", "@angular/core": "18.2.6",
"@angular/platform-browser": "18.2.7", "@angular/platform-browser": "18.2.6",
"rxjs": "^6.5.3 || ^7.4.0" "rxjs": "^6.5.3 || ^7.4.0"
} }
}, },
@ -3408,9 +3407,9 @@
} }
}, },
"node_modules/@jsonjoy.com/util": { "node_modules/@jsonjoy.com/util": {
"version": "1.5.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.5.0.tgz", "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz",
"integrity": "sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA==", "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
@ -3616,9 +3615,9 @@
] ]
}, },
"node_modules/@ngtools/webpack": { "node_modules/@ngtools/webpack": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.2.6.tgz",
"integrity": "sha512-BmnFxss6zGobGyq9Mi7736golbK8RLgF+zYCQZ+4/OfMMA1jKVoELnyJqNyAx+DQn3m1qKVBjtGEL7pTNpPzOw==", "integrity": "sha512-7HwOPE1EOgcHnpt4brSiT8G2CcXB50G0+CbCBaKGy4LYCG3Y3mrlzF5Fup9HvMJ6Tzqd62RqzpKKYBiGUT7hxg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -4182,14 +4181,14 @@
] ]
}, },
"node_modules/@schematics/angular": { "node_modules/@schematics/angular": {
"version": "18.2.7", "version": "18.2.6",
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.7.tgz", "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.6.tgz",
"integrity": "sha512-WOBzO11qstznHbC9tZXQf6/8+PqmaRI6QYcdTspqXNh9q9nNglvi43Xn4tSIpEhW8aSHea9hgWZV8sG+i/4W9Q==", "integrity": "sha512-Y988EoOEQDLEyHu3414T6AeVUyx21AexBHQNbUNQkK8cxlxyB6m1eH1cx6vFgLRFUTsLVv+C6Ln/ICNTfLcG4A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@angular-devkit/core": "18.2.7", "@angular-devkit/core": "18.2.6",
"@angular-devkit/schematics": "18.2.7", "@angular-devkit/schematics": "18.2.6",
"jsonc-parser": "3.3.1" "jsonc-parser": "3.3.1"
}, },
"engines": { "engines": {
@ -4383,15 +4382,13 @@
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==",
"dev": true, "dev": true
"license": "MIT"
}, },
"node_modules/@types/cors": { "node_modules/@types/cors": {
"version": "2.8.17", "version": "2.8.17",
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz",
"integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@types/node": "*" "@types/node": "*"
} }
@ -5138,7 +5135,6 @@
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": "^4.5.0 || >= 5.9" "node": "^4.5.0 || >= 5.9"
} }
@ -5926,7 +5922,6 @@
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
"integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">= 0.6" "node": ">= 0.6"
} }
@ -6014,7 +6009,6 @@
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"object-assign": "^4", "object-assign": "^4",
"vary": "^1" "vary": "^1"
@ -6578,11 +6572,10 @@
} }
}, },
"node_modules/engine.io": { "node_modules/engine.io": {
"version": "6.6.1", "version": "6.5.4",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.1.tgz", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz",
"integrity": "sha512-NEpDCw9hrvBW+hVEOK4T7v0jFJ++KgtPl4jKFwsZVfG1XhS0dCrSb3VMb9gPAd7VAdW52VT1EnaNiU2vM8C0og==", "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@types/cookie": "^0.4.1", "@types/cookie": "^0.4.1",
"@types/cors": "^2.8.12", "@types/cors": "^2.8.12",
@ -6593,18 +6586,17 @@
"cors": "~2.8.5", "cors": "~2.8.5",
"debug": "~4.3.1", "debug": "~4.3.1",
"engine.io-parser": "~5.2.1", "engine.io-parser": "~5.2.1",
"ws": "~8.17.1" "ws": "~8.11.0"
}, },
"engines": { "engines": {
"node": ">=10.2.0" "node": ">=10.2.0"
} }
}, },
"node_modules/engine.io-parser": { "node_modules/engine.io-parser": {
"version": "5.2.3", "version": "5.2.2",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz",
"integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"
} }
@ -9441,13 +9433,12 @@
} }
}, },
"node_modules/micromatch": { "node_modules/micromatch": {
"version": "4.0.8", "version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"braces": "^3.0.3", "braces": "^3.0.2",
"picomatch": "^2.3.1" "picomatch": "^2.3.1"
}, },
"engines": { "engines": {
@ -9905,20 +9896,6 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true "dev": true
}, },
"node_modules/ngx-toastr": {
"version": "19.0.0",
"resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-19.0.0.tgz",
"integrity": "sha512-6pTnktwwWD+kx342wuMOWB4+bkyX9221pAgGz3SHOJH0/MI9erLucS8PeeJDFwbUYyh75nQ6AzVtolgHxi52dQ==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
},
"peerDependencies": {
"@angular/common": ">=16.0.0-0",
"@angular/core": ">=16.0.0-0",
"@angular/platform-browser": ">=16.0.0-0"
}
},
"node_modules/nice-napi": { "node_modules/nice-napi": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz",
@ -10274,7 +10251,6 @@
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@ -11997,17 +11973,16 @@
} }
}, },
"node_modules/socket.io": { "node_modules/socket.io": {
"version": "4.8.0", "version": "4.7.5",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.0.tgz", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz",
"integrity": "sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA==", "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"accepts": "~1.3.4", "accepts": "~1.3.4",
"base64id": "~2.0.0", "base64id": "~2.0.0",
"cors": "~2.8.5", "cors": "~2.8.5",
"debug": "~4.3.2", "debug": "~4.3.2",
"engine.io": "~6.6.0", "engine.io": "~6.5.2",
"socket.io-adapter": "~2.5.2", "socket.io-adapter": "~2.5.2",
"socket.io-parser": "~4.2.4" "socket.io-parser": "~4.2.4"
}, },
@ -12016,14 +11991,13 @@
} }
}, },
"node_modules/socket.io-adapter": { "node_modules/socket.io-adapter": {
"version": "2.5.5", "version": "2.5.4",
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz",
"integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"debug": "~4.3.4", "debug": "~4.3.4",
"ws": "~8.17.1" "ws": "~8.11.0"
} }
}, },
"node_modules/socket.io-parser": { "node_modules/socket.io-parser": {
@ -13650,9 +13624,9 @@
} }
}, },
"node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { "node_modules/webpack-dev-server/node_modules/http-proxy-middleware": {
"version": "2.0.7", "version": "2.0.6",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz",
"integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -13981,17 +13955,16 @@
"dev": true "dev": true
}, },
"node_modules/ws": { "node_modules/ws": {
"version": "8.17.1", "version": "8.11.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"bufferutil": "^4.0.1", "bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2" "utf-8-validate": "^5.0.2"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"bufferutil": { "bufferutil": {

View File

@ -1,6 +1,6 @@
{ {
"name": "frontend", "name": "frontend",
"version": "1.0.0-b8", "version": "1.0.0-b7",
"scripts": { "scripts": {
"ng": "ng", "ng": "ng",
"start": "ng serve", "start": "ng serve",
@ -10,28 +10,27 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "^18.2.7", "@angular/animations": "^18.2.6",
"@angular/cdk": "~18.2.7", "@angular/cdk": "~18.2.6",
"@angular/cdk-experimental": "^18.2.7", "@angular/cdk-experimental": "^18.2.6",
"@angular/common": "^18.2.7", "@angular/common": "^18.2.6",
"@angular/compiler": "^18.2.7", "@angular/compiler": "^18.2.6",
"@angular/core": "^18.2.7", "@angular/core": "^18.2.6",
"@angular/forms": "^18.2.7", "@angular/forms": "^18.2.6",
"@angular/material": "~18.2.7", "@angular/material": "~18.2.6",
"@angular/platform-browser": "^18.2.7", "@angular/platform-browser": "^18.2.6",
"@angular/platform-browser-dynamic": "^18.2.7", "@angular/platform-browser-dynamic": "^18.2.6",
"@angular/router": "^18.2.7", "@angular/router": "^18.2.6",
"@dhutaryan/ngx-mat-timepicker": "^18.0.2", "@dhutaryan/ngx-mat-timepicker": "^18.0.2",
"@progress/kendo-date-math": "^1.5.13", "@progress/kendo-date-math": "^1.5.13",
"ngx-toastr": "^19.0.0",
"rxjs": "~7.8.1", "rxjs": "~7.8.1",
"tslib": "^2.7.0", "tslib": "^2.7.0",
"zone.js": "^0.14.10" "zone.js": "^0.14.10"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "^18.2.7", "@angular-devkit/build-angular": "^18.2.6",
"@angular/cli": "^18.2.7", "@angular/cli": "^18.2.6",
"@angular/compiler-cli": "^18.2.7", "@angular/compiler-cli": "^18.2.6",
"@types/jasmine": "~5.1.4", "@types/jasmine": "~5.1.4",
"jasmine-core": "~5.3.0", "jasmine-core": "~5.3.0",
"karma": "~6.4.4", "karma": "~6.4.4",

View File

@ -64,4 +64,36 @@ export class RequestBuilder {
needAuth: false needAuth: false
}; };
} }
public getEndpoint(): string {
return this.endpoint;
}
public getQueryParams(): Record<string, string | number | boolean | Array<any> | null> | null {
return this.queryParams;
}
public getHttpHeaders(): HttpHeaders {
return this.httpHeaders;
}
public getData(): any {
return this.data;
}
public getSilenceMode(): boolean {
return this.silenceMode;
}
public static getStandardRequestData(): RequestData {
return {
endpoint: '',
queryParams: null,
httpHeaders: new HttpHeaders(),
data: null,
silenceMode: false,
withCredentials: false,
needAuth: false
};
}
} }

View File

@ -1,21 +1,35 @@
import { import {catchError, distinctUntilChanged, filter, first, mergeMap, Observable, retryWhen, switchMap, timer} from "rxjs";
BehaviorSubject,
catchError,
distinctUntilChanged,
filter,
first,
Observable,
of,
ReplaySubject,
switchMap
} from "rxjs";
import {HttpClient, HttpErrorResponse} from "@angular/common/http"; import {HttpClient, HttpErrorResponse} from "@angular/common/http";
import {NotifyColor, OpenNotifyService} from "@service/open-notify.service";
import {environment} from "@environment"; import {environment} from "@environment";
import {Router} from "@angular/router"; import {Router} from "@angular/router";
import {Injectable} from "@angular/core"; import {Injectable} from "@angular/core";
import {RequestBuilder, RequestData} from "@api/RequestBuilder"; import {RequestBuilder, RequestData} from "@api/RequestBuilder";
import {ToastrService} from "ngx-toastr"; import {TokenRefreshService} from "@service/token-refresh.service";
import {AuthRoles} from "@model/AuthRoles"; import {AuthToken} from "@service/auth.service";
export function retryWithInterval<T>(): (source: Observable<T>) => Observable<T> {
return (source: Observable<T>) =>
source.pipe(
retryWhen((errors: Observable<any>) =>
errors.pipe(
mergeMap((error, index) => {
if (index < (environment.maxRetry < 0 ? Infinity : environment.maxRetry - 1) && !error.status.toString().startsWith('4') && !error.status.toString().startsWith('5')) {
console.log(`Retrying after ${environment.retryDelay}ms...`);
return timer(environment.retryDelay);
} else {
if (error.status.toString().startsWith('4'))
console.error(`Server returned a client code error`);
else
console.error(`Exceeded maximum retries (${environment.maxRetry})`);
throw error;
}
})
)
)
);
}
export enum AvailableVersion { export enum AvailableVersion {
v1 v1
@ -23,16 +37,16 @@ export enum AvailableVersion {
@Injectable() @Injectable()
export default abstract class ApiService { export default abstract class ApiService {
constructor(private http: HttpClient, private notify: ToastrService, private router: Router) { constructor(private http: HttpClient, private notify: OpenNotifyService, private router: Router, protected tokenRefreshService: TokenRefreshService) {
} }
private apiUrl = environment.apiUrl; private apiUrl = environment.apiUrl;
private static isRefreshingToken: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
private static refreshTokenSubject: ReplaySubject<any> = new ReplaySubject(1);
protected abstract basePath: string; protected abstract basePath: string;
protected abstract version: AvailableVersion; protected abstract version: AvailableVersion;
public static readonly tokenKey = 'auth_token';
private static addQuery(endpoint: string, queryParams?: Record<string, string | number | boolean | Array<any> | null> | null): string { private static addQuery(endpoint: string, queryParams?: Record<string, string | number | boolean | Array<any> | null> | null): string {
const url = new URL(endpoint); const url = new URL(endpoint);
@ -59,7 +73,7 @@ export default abstract class ApiService {
return ApiService.addQuery(ApiService.combineUrls(this.apiUrl, AvailableVersion[this.version], this.basePath, request.endpoint), request.queryParams); return ApiService.addQuery(ApiService.combineUrls(this.apiUrl, AvailableVersion[this.version], this.basePath, request.endpoint), request.queryParams);
} }
private sendHttpRequest<Type>(method: 'get' | 'post' | 'delete' | 'put', request: RequestData, secondTry: boolean = false): Observable<Type> { private sendHttpRequest<Type>(method: 'get' | 'post' | 'delete' | 'put', request: RequestData): Observable<Type> {
const doneEndpoint = this.combinedUrl(request); const doneEndpoint = this.combinedUrl(request);
return this.http.request<Type>(method, doneEndpoint, { return this.http.request<Type>(method, doneEndpoint, {
@ -67,58 +81,35 @@ export default abstract class ApiService {
headers: request.httpHeaders, headers: request.httpHeaders,
body: request.data body: request.data
}).pipe( }).pipe(
retryWithInterval<Type>(),
catchError(error => { catchError(error => {
if (!secondTry && error.status === 401) if (!request.silenceMode)
return this.handle401Error().pipe( this.handleError(error);
switchMap(() => this.sendHttpRequest<Type>(method, request, true))
);
else {
if (!request.silenceMode)
this.handleError(error);
throw error; throw error;
}
})
);
}
private refreshToken(): Observable<AuthRoles> {
return this.http.get<AuthRoles>(ApiService.combineUrls(this.apiUrl, AvailableVersion[AvailableVersion.v1], 'Auth', 'ReLogin'), {
withCredentials: true
});
}
private handle401Error(): Observable<any> {
if (ApiService.isRefreshingToken.value)
return ApiService.refreshTokenSubject.asObservable();
ApiService.isRefreshingToken.next(true);
return this.refreshToken().pipe(
switchMap(_ => {
ApiService.isRefreshingToken.next(false);
ApiService.refreshTokenSubject.next(null);
return of(null);
}),
catchError(err => {
ApiService.isRefreshingToken.next(false);
ApiService.refreshTokenSubject.error(err);
ApiService.refreshTokenSubject = new ReplaySubject(1);
throw err;
}) })
); );
} }
private makeHttpRequest<Type>(method: 'get' | 'post' | 'delete' | 'put', request: RequestData): Observable<Type> { private makeHttpRequest<Type>(method: 'get' | 'post' | 'delete' | 'put', request: RequestData): Observable<Type> {
if (request.needAuth) { if (request.needAuth)
return ApiService.isRefreshingToken.pipe( return this.tokenRefreshService.getTokenRefreshing$().pipe(
distinctUntilChanged(), distinctUntilChanged(),
filter(isRefreshing => !isRefreshing), filter(isRefreshing => !isRefreshing),
first(), first(),
switchMap(() => this.sendHttpRequest<Type>(method, request)) switchMap(() => {
const token = localStorage.getItem(ApiService.tokenKey);
if (token) {
const authToken = AuthToken.httpHeader((JSON.parse(token) as AuthToken));
authToken.keys().forEach(key => request.httpHeaders = request.httpHeaders.append(key, authToken.get(key) ?? ''));
}
return this.sendHttpRequest<Type>(method, request);
})
); );
} else {
return this.sendHttpRequest<Type>(method, request); return this.sendHttpRequest<Type>(method, request);
}
} }
private getRequest(request: RequestData | string | null): RequestData { private getRequest(request: RequestData | string | null): RequestData {
@ -152,7 +143,6 @@ export default abstract class ApiService {
public addAuth(request: RequestData) { public addAuth(request: RequestData) {
request.needAuth = true; request.needAuth = true;
request.withCredentials = true;
return this; return this;
} }
@ -163,45 +153,41 @@ export default abstract class ApiService {
return; return;
} }
let title: string; let message: string;
let message: string | undefined = undefined;
if (error.error instanceof ErrorEvent) { if (error.error instanceof ErrorEvent) {
title = `Произошла ошибка: ${error.error.message}`; message = `Произошла ошибка: ${error.error.message}`;
} else { } else {
switch (error.status) { switch (error.status) {
case 0: case 0:
title = 'Неизвестная ошибка. Пожалуйста, попробуйте позже.'; message = 'Неизвестная ошибка. Пожалуйста, попробуйте позже.';
break; break;
case 400: case 400:
title = 'Ошибка запроса. Пожалуйста, проверьте отправленные данные.'; message = 'Ошибка запроса. Пожалуйста, проверьте отправленные данные.';
break; break;
case 401: case 401:
this.router.navigate(['/login/']).then(); this.router.navigate(['/login/']).then();
title = 'Ошибка авторизации. Пожалуйста, выполните вход с правильными учетными данными.'; message = 'Ошибка авторизации. Пожалуйста, выполните вход с правильными учетными данными.';
break; break;
case 403: case 403:
title = 'Отказано в доступе. У вас нет разрешения на выполнение этого действия.'; message = 'Отказано в доступе. У вас нет разрешения на выполнение этого действия.';
break; break;
case 404: case 404:
title = 'Запрашиваемый ресурс не найден.'; message = 'Запрашиваемый ресурс не найден.';
break; break;
case 500: case 500:
title = 'Внутренняя ошибка сервера. Пожалуйста, попробуйте позже.'; message = 'Внутренняя ошибка сервера. Пожалуйста, попробуйте позже.';
break; break;
case 503: case 503:
title = 'Сервер на обслуживании. Пожалуйста, попробуйте позже.'; message = 'Сервер на обслуживании. Пожалуйста, попробуйте позже.';
break; break;
default: default:
title = `Сервер вернул код ошибки: ${error.status}`; message = `Сервер вернул код ошибки: ${error.status}`;
break; break;
} }
if (error.error?.Error) if (error.error?.Error) {
message = error.error.Error; message += ` ${error.error.Error}`;
else if (error.error instanceof String) }
message = error.error.toString();
else
message = error.error.statusMessage;
} }
this.notify.error(message == '' ? undefined : message, title); this.notify.open(message, NotifyColor.Danger);
} }
} }

View File

@ -1,8 +1,10 @@
import {Injectable} from "@angular/core"; import {Injectable} from "@angular/core";
import ApiService, {AvailableVersion} from "@api/api.service"; import ApiService, {AvailableVersion} from "@api/api.service";
import {LoginRequest} from "@api/v1/loginRequest"; import {LoginRequest} from "@api/v1/loginRequest";
import {catchError, of} from "rxjs"; import {TokenResponse} from "@api/v1/tokenResponse";
import {catchError, of, tap} from "rxjs";
import {AuthRoles} from "@model/AuthRoles"; import {AuthRoles} from "@model/AuthRoles";
import {AuthService, AvailableAuthenticationProvider} from "@service/auth.service";
@Injectable() @Injectable()
export default class AuthApiService extends ApiService { export default class AuthApiService extends ApiService {
@ -16,16 +18,13 @@ export default class AuthApiService extends ApiService {
.setWithCredentials() .setWithCredentials()
.build; .build;
return this.post<AuthRoles>(request); return this.post<TokenResponse>(request)
} .pipe(
tap(response => {
public reLogin(){ AuthService.setToken(response, AvailableAuthenticationProvider.Bearer, this.combinedUrl(this.createRequestBuilder().setEndpoint('ReLogin').build));
let request = this.createRequestBuilder() this.tokenRefreshService.setRefreshTokenExpireMs(response.expiresIn);
.setEndpoint('ReLogin') })
.setWithCredentials() );
.build;
return this.get<AuthRoles>(request);
} }
public logout() { public logout() {
@ -34,7 +33,13 @@ export default class AuthApiService extends ApiService {
.setEndpoint('Logout') .setEndpoint('Logout')
.build; .build;
return this.addAuth(request).get(request); return this.addAuth(request)
.get(request)
.pipe(
tap(_ => {
localStorage.removeItem(ApiService.tokenKey);
})
);
} }
public getRole(isSilence: boolean = true) { public getRole(isSilence: boolean = true) {

View File

@ -4,23 +4,7 @@ import {provideRouter} from '@angular/router';
import {routes} from './app.routes'; import {routes} from './app.routes';
import {provideAnimationsAsync} from '@angular/platform-browser/animations/async'; import {provideAnimationsAsync} from '@angular/platform-browser/animations/async';
import {provideHttpClient} from "@angular/common/http"; import {provideHttpClient} from "@angular/common/http";
import {provideToastr} from "ngx-toastr";
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
providers: [ providers: [provideRouter(routes), provideAnimationsAsync(), provideHttpClient()]
provideRouter(routes),
provideAnimationsAsync(),
provideHttpClient(),
provideToastr({
timeOut: 5000,
extendedTimeOut: 2000,
positionClass: "toast-top-right",
progressBar: true,
progressAnimation: "decreasing",
newestOnTop: true,
tapToDismiss: true,
disableTimeOut: false,
autoDismiss: true,
maxOpened: 5
})]
}; };

View File

@ -6,9 +6,7 @@
<base href="/"> <base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="preconnect" href="https://fonts.googleapis.com"> <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head> </head>
<body class="mat-typography"> <body class="mat-typography">

View File

@ -82,7 +82,7 @@ export class LoginComponent {
}) })
.pipe(catchError(error => { .pipe(catchError(error => {
this.loaderActive = false; this.loaderActive = false;
this.errorText = error.error instanceof String ? error.error : error.statusText; this.errorText = error.error;
this.loginButtonIsDisable = true; this.loginButtonIsDisable = true;
throw error; throw error;
})) }))

View File

@ -0,0 +1,83 @@
import {Injectable} from '@angular/core';
import {HttpClient, HttpHeaders} from "@angular/common/http";
import {map, Observable, throwError} from "rxjs";
import {TokenResponse} from "@api/v1/tokenResponse";
import ApiService from "@api/api.service";
export enum AvailableAuthenticationProvider {
Bearer
}
export class AuthToken {
accessToken: string;
expiresIn: Date;
authProvider: AvailableAuthenticationProvider;
endpoint: string;
constructor(accessToken: string, expiresIn: Date, authProvider: AvailableAuthenticationProvider, refreshEndpoint: string) {
this.accessToken = accessToken;
this.expiresIn = expiresIn;
this.authProvider = authProvider;
this.endpoint = refreshEndpoint;
}
public static httpHeader(token: AuthToken): HttpHeaders {
let header = new HttpHeaders();
if (token.authProvider === AvailableAuthenticationProvider.Bearer)
header = header.set('Authorization', `Bearer ${token.accessToken}`);
return header;
}
}
@Injectable({
providedIn: 'root',
})
export class AuthService {
constructor(private http: HttpClient) {
}
public static setToken(token: TokenResponse, provider: AvailableAuthenticationProvider, refreshEndpoint: string) {
localStorage.setItem(ApiService.tokenKey, JSON.stringify(
new AuthToken(token.accessToken, token.expiresIn, provider, refreshEndpoint)
));
}
public static get tokenExpiresIn(): Date {
const token = localStorage.getItem(ApiService.tokenKey);
if (!token)
return new Date();
const result = new Date((JSON.parse(token) as AuthToken).expiresIn);
return result <= new Date() ? new Date() : result;
}
public refreshToken(): Observable<Date> {
const token = localStorage.getItem(ApiService.tokenKey);
if (!token)
return throwError(() => new Error("Token is not found"));
const authToken = JSON.parse(token) as AuthToken;
switch (authToken.authProvider) {
case AvailableAuthenticationProvider.Bearer:
return this.http.get<TokenResponse>(authToken.endpoint, {withCredentials: true})
.pipe(
map(response => {
const newExpireDate = new Date(response.expiresIn);
const oldExpireDate = new Date(authToken.expiresIn);
if (newExpireDate.getTime() !== oldExpireDate.getTime()) {
AuthService.setToken(response, AvailableAuthenticationProvider.Bearer, authToken.endpoint);
return newExpireDate;
}
return newExpireDate;
})
);
}
}
}

View File

@ -0,0 +1,59 @@
import {Injectable} from '@angular/core';
import {MatSnackBar} from '@angular/material/snack-bar';
import {NotificationComponent} from "@component/common/notification/notification.component";
export enum NotifyColor {
Basic,
Warn,
Danger,
Success
}
@Injectable({
providedIn: 'root'
})
export class OpenNotifyService {
constructor(private _snackBar: MatSnackBar) {
}
colorClass: string = '';
set setColorClass(color: NotifyColor) {
switch (color) {
case NotifyColor.Warn: {
this.colorClass = 'yellow-snackbar';
}
break;
case NotifyColor.Danger: {
this.colorClass = 'red-snackbar';
}
break;
case NotifyColor.Success: {
this.colorClass = 'green-snackbar';
}
break;
default: {
this.colorClass = 'snackbar';
}
break;
}
}
open(message: string, color: NotifyColor = NotifyColor.Basic, duration: number = 5000) {
this.setColorClass = color;
this._snackBar.openFromComponent(NotificationComponent, {
data: {
message: message,
duration: duration,
className: this.colorClass,
color: color === NotifyColor.Danger ? "accent" : "primary"
},
duration: duration,
verticalPosition: 'top',
horizontalPosition: 'center',
panelClass: [this.colorClass]
})
;
}
}

View File

@ -10,194 +10,22 @@ body {
font-family: Roboto, "Helvetica Neue", sans-serif; font-family: Roboto, "Helvetica Neue", sans-serif;
} }
/* based on angular-toastr css https://github.com/Foxandxss/angular-toastr/blob/cb508fe6801d6b288d3afc525bb40fee1b101650/dist/angular-toastr.css */ .green-snackbar {
/* position */ --mdc-snackbar-container-color: #8CBA51;
.toast-center-center { color: black;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.toast-top-center {
top: 0;
right: 0;
width: 100%;
}
.toast-bottom-center {
bottom: 0;
right: 0;
width: 100%;
}
.toast-top-full-width {
top: 0;
right: 0;
width: 100%;
}
.toast-bottom-full-width {
bottom: 0;
right: 0;
width: 100%;
}
.toast-top-left {
top: 12px;
left: 12px;
}
.toast-top-right {
top: 12px;
right: 12px;
}
.toast-bottom-right {
right: 12px;
bottom: 12px;
}
.toast-bottom-left {
bottom: 12px;
left: 12px;
} }
/* toast styles */ .red-snackbar {
.toast-title { --mdc-snackbar-container-color: #E20338;
font-weight: bold; color: white;
} }
.toast-message {
word-wrap: break-word; .yellow-snackbar {
--mdc-snackbar-container-color: #FFD600;
color: black;
} }
.toast-message a,
.toast-message label { .snackbar {
color: #FFFFFF; --mdc-snackbar-container-color: inherit;
} color: inherit;
.toast-message a:hover {
color: #CCCCCC;
text-decoration: none;
}
.toast-close-button {
position: relative;
right: -0.3em;
top: -0.3em;
float: right;
font-size: 20px;
font-weight: bold;
color: #FFFFFF;
text-shadow: 0 1px 0 #ffffff;
/* opacity: 0.8; */
}
.toast-close-button:hover,
.toast-close-button:focus {
color: #000000;
text-decoration: none;
cursor: pointer;
opacity: 0.4;
}
/*Additional properties for button version
iOS requires the button element instead of an anchor tag.
If you want the anchor version, it requires `href="#"`.*/
button.toast-close-button {
padding: 0;
cursor: pointer;
background: transparent;
border: 0;
}
.toast-container {
pointer-events: none;
position: fixed;
z-index: 999999;
}
.toast-container * {
box-sizing: border-box;
}
.toast-container .ngx-toastr {
position: relative;
overflow: hidden;
margin: 0 0 6px;
padding: 15px 15px 15px 50px;
width: 300px;
border-radius: 3px 3px 3px 3px;
background-position: 15px center;
background-repeat: no-repeat;
background-size: 24px;
box-shadow: 0 0 12px #999999;
color: #FFFFFF;
}
.toast-container .ngx-toastr:hover {
box-shadow: 0 0 12px #000000;
opacity: 1;
cursor: pointer;
}
/* https://github.com/FortAwesome/Font-Awesome-Pro/blob/master/advanced-options/raw-svg/regular/info-circle.svg */
.toast-info {
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCA1MTIgNTEyJyB3aWR0aD0nNTEyJyBoZWlnaHQ9JzUxMic+PHBhdGggZmlsbD0ncmdiKDI1NSwyNTUsMjU1KScgZD0nTTI1NiA4QzExOS4wNDMgOCA4IDExOS4wODMgOCAyNTZjMCAxMzYuOTk3IDExMS4wNDMgMjQ4IDI0OCAyNDhzMjQ4LTExMS4wMDMgMjQ4LTI0OEM1MDQgMTE5LjA4MyAzOTIuOTU3IDggMjU2IDh6bTAgMTEwYzIzLjE5NiAwIDQyIDE4LjgwNCA0MiA0MnMtMTguODA0IDQyLTQyIDQyLTQyLTE4LjgwNC00Mi00MiAxOC44MDQtNDIgNDItNDJ6bTU2IDI1NGMwIDYuNjI3LTUuMzczIDEyLTEyIDEyaC04OGMtNi42MjcgMC0xMi01LjM3My0xMi0xMnYtMjRjMC02LjYyNyA1LjM3My0xMiAxMi0xMmgxMnYtNjRoLTEyYy02LjYyNyAwLTEyLTUuMzczLTEyLTEydi0yNGMwLTYuNjI3IDUuMzczLTEyIDEyLTEyaDY0YzYuNjI3IDAgMTIgNS4zNzMgMTIgMTJ2MTAwaDEyYzYuNjI3IDAgMTIgNS4zNzMgMTIgMTJ2MjR6Jy8+PC9zdmc+");
}
/* https://github.com/FortAwesome/Font-Awesome-Pro/blob/master/advanced-options/raw-svg/regular/times-circle.svg */
.toast-error {
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCA1MTIgNTEyJyB3aWR0aD0nNTEyJyBoZWlnaHQ9JzUxMic+PHBhdGggZmlsbD0ncmdiKDI1NSwyNTUsMjU1KScgZD0nTTI1NiA4QzExOSA4IDggMTE5IDggMjU2czExMSAyNDggMjQ4IDI0OCAyNDgtMTExIDI0OC0yNDhTMzkzIDggMjU2IDh6bTEyMS42IDMxMy4xYzQuNyA0LjcgNC43IDEyLjMgMCAxN0wzMzggMzc3LjZjLTQuNyA0LjctMTIuMyA0LjctMTcgMEwyNTYgMzEybC02NS4xIDY1LjZjLTQuNyA0LjctMTIuMyA0LjctMTcgMEwxMzQuNCAzMzhjLTQuNy00LjctNC43LTEyLjMgMC0xN2w2NS42LTY1LTY1LjYtNjUuMWMtNC43LTQuNy00LjctMTIuMyAwLTE3bDM5LjYtMzkuNmM0LjctNC43IDEyLjMtNC43IDE3IDBsNjUgNjUuNyA2NS4xLTY1LjZjNC43LTQuNyAxMi4zLTQuNyAxNyAwbDM5LjYgMzkuNmM0LjcgNC43IDQuNyAxMi4zIDAgMTdMMzEyIDI1Nmw2NS42IDY1LjF6Jy8+PC9zdmc+");
}
/* https://github.com/FortAwesome/Font-Awesome-Pro/blob/master/advanced-options/raw-svg/regular/check.svg */
.toast-success {
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCA1MTIgNTEyJyB3aWR0aD0nNTEyJyBoZWlnaHQ9JzUxMic+PHBhdGggZmlsbD0ncmdiKDI1NSwyNTUsMjU1KScgZD0nTTE3My44OTggNDM5LjQwNGwtMTY2LjQtMTY2LjRjLTkuOTk3LTkuOTk3LTkuOTk3LTI2LjIwNiAwLTM2LjIwNGwzNi4yMDMtMzYuMjA0YzkuOTk3LTkuOTk4IDI2LjIwNy05Ljk5OCAzNi4yMDQgMEwxOTIgMzEyLjY5IDQzMi4wOTUgNzIuNTk2YzkuOTk3LTkuOTk3IDI2LjIwNy05Ljk5NyAzNi4yMDQgMGwzNi4yMDMgMzYuMjA0YzkuOTk3IDkuOTk3IDkuOTk3IDI2LjIwNiAwIDM2LjIwNGwtMjk0LjQgMjk0LjQwMWMtOS45OTggOS45OTctMjYuMjA3IDkuOTk3LTM2LjIwNC0uMDAxeicvPjwvc3ZnPg==");
}
/* https://github.com/FortAwesome/Font-Awesome-Pro/blob/master/advanced-options/raw-svg/regular/exclamation-triangle.svg */
.toast-warning {
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCA1NzYgNTEyJyB3aWR0aD0nNTc2JyBoZWlnaHQ9JzUxMic+PHBhdGggZmlsbD0ncmdiKDI1NSwyNTUsMjU1KScgZD0nTTU2OS41MTcgNDQwLjAxM0M1ODcuOTc1IDQ3Mi4wMDcgNTY0LjgwNiA1MTIgNTI3Ljk0IDUxMkg0OC4wNTRjLTM2LjkzNyAwLTU5Ljk5OS00MC4wNTUtNDEuNTc3LTcxLjk4N0wyNDYuNDIzIDIzLjk4NWMxOC40NjctMzIuMDA5IDY0LjcyLTMxLjk1MSA4My4xNTQgMGwyMzkuOTQgNDE2LjAyOHpNMjg4IDM1NGMtMjUuNDA1IDAtNDYgMjAuNTk1LTQ2IDQ2czIwLjU5NSA0NiA0NiA0NiA0Ni0yMC41OTUgNDYtNDYtMjAuNTk1LTQ2LTQ2LTQ2em0tNDMuNjczLTE2NS4zNDZsNy40MTggMTM2Yy4zNDcgNi4zNjQgNS42MDkgMTEuMzQ2IDExLjk4MiAxMS4zNDZoNDguNTQ2YzYuMzczIDAgMTEuNjM1LTQuOTgyIDExLjk4Mi0xMS4zNDZsNy40MTgtMTM2Yy4zNzUtNi44NzQtNS4wOTgtMTIuNjU0LTExLjk4Mi0xMi42NTRoLTYzLjM4M2MtNi44ODQgMC0xMi4zNTYgNS43OC0xMS45ODEgMTIuNjU0eicvPjwvc3ZnPg==");
}
.toast-container.toast-top-center .ngx-toastr,
.toast-container.toast-bottom-center .ngx-toastr {
width: 300px;
margin-left: auto;
margin-right: auto;
}
.toast-container.toast-top-full-width .ngx-toastr,
.toast-container.toast-bottom-full-width .ngx-toastr {
width: 96%;
margin-left: auto;
margin-right: auto;
}
.ngx-toastr {
background-color: #030303;
pointer-events: auto;
}
.toast-success {
background-color: #51A351;
}
.toast-error {
background-color: #BD362F;
}
.toast-info {
background-color: #2F96B4;
}
.toast-warning {
background-color: #F89406;
}
.toast-progress {
position: absolute;
left: 0;
bottom: 0;
height: 4px;
background-color: #000000;
opacity: 0.4;
}
/* Responsive Design */
@media all and (max-width: 240px) {
.toast-container .ngx-toastr.div {
padding: 8px 8px 8px 50px;
width: 11em;
}
.toast-container .toast-close-button {
right: -0.2em;
top: -0.2em;
}
}
@media all and (min-width: 241px) and (max-width: 480px) {
.toast-container .ngx-toastr.div {
padding: 8px 8px 8px 50px;
width: 18em;
}
.toast-container .toast-close-button {
right: -0.2em;
top: -0.2em;
}
}
@media all and (min-width: 481px) and (max-width: 768px) {
.toast-container .ngx-toastr.div {
padding: 15px 15px 15px 50px;
width: 25em;
}
} }