Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
portal-apps-manage
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
angular
portal-apps-manage
Commits
23e076c8
Commit
23e076c8
authored
Sep 14, 2025
by
Ooh-Ao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
menu
parent
63435617
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1010 additions
and
98 deletions
+1010
-98
package-lock.json
package-lock.json
+67
-67
login.component.ts
src/app/authentication/login/login.component.ts
+97
-4
home.component.html
src/app/portal-manage/home/home.component.html
+1
-0
home.component.ts
src/app/portal-manage/home/home.component.ts
+180
-27
jwt-token.model.ts
src/app/portal-manage/models/jwt-token.model.ts
+77
-0
employee-auth.service.ts
src/app/portal-manage/services/employee-auth.service.ts
+364
-0
jwt.service.ts
src/app/portal-manage/services/jwt.service.ts
+224
-0
employeelist.json
src/assets/data/employeelist.json
+0
-0
No files found.
package-lock.json
View file @
23e076c8
...
@@ -130,6 +130,7 @@
...
@@ -130,6 +130,7 @@
"version"
:
"5.2.0"
,
"version"
:
"5.2.0"
,
"resolved"
:
"https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz"
,
"integrity"
:
"sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="
,
"integrity"
:
"sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"engines"
:
{
"engines"
:
{
"node"
:
">=10"
"node"
:
">=10"
...
@@ -615,6 +616,7 @@
...
@@ -615,6 +616,7 @@
"version"
:
"17.3.12"
,
"version"
:
"17.3.12"
,
"resolved"
:
"https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-17.3.12.tgz"
,
"resolved"
:
"https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-17.3.12.tgz"
,
"integrity"
:
"sha512-1F8M7nWfChzurb7obbvuE7mJXlHtY1UG58pcwcomVtpPb+kPavgAO8OEvJHYBMV+bzSxkXt5UIwL9lt9jHUxZA=="
,
"integrity"
:
"sha512-1F8M7nWfChzurb7obbvuE7mJXlHtY1UG58pcwcomVtpPb+kPavgAO8OEvJHYBMV+bzSxkXt5UIwL9lt9jHUxZA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"@babel/core"
:
"7.23.9"
,
"@babel/core"
:
"7.23.9"
,
...
@@ -643,6 +645,7 @@
...
@@ -643,6 +645,7 @@
"version"
:
"7.23.9"
,
"version"
:
"7.23.9"
,
"resolved"
:
"https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz"
,
"resolved"
:
"https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz"
,
"integrity"
:
"sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw=="
,
"integrity"
:
"sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"@ampproject/remapping"
:
"^2.2.0"
,
"@ampproject/remapping"
:
"^2.2.0"
,
...
@@ -673,12 +676,14 @@
...
@@ -673,12 +676,14 @@
"version"
:
"2.0.0"
,
"version"
:
"2.0.0"
,
"resolved"
:
"https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz"
,
"integrity"
:
"sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="
,
"integrity"
:
"sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="
,
"dev"
:
true
,
"license"
:
"MIT"
"license"
:
"MIT"
},
},
"node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver"
:
{
"node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver"
:
{
"version"
:
"6.3.1"
,
"version"
:
"6.3.1"
,
"resolved"
:
"https://registry.npmjs.org/semver/-/semver-6.3.1.tgz"
,
"resolved"
:
"https://registry.npmjs.org/semver/-/semver-6.3.1.tgz"
,
"integrity"
:
"sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
,
"integrity"
:
"sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"license"
:
"ISC"
,
"bin"
:
{
"bin"
:
{
"semver"
:
"bin/semver.js"
"semver"
:
"bin/semver.js"
...
@@ -1090,6 +1095,7 @@
...
@@ -1090,6 +1095,7 @@
"version"
:
"7.26.10"
,
"version"
:
"7.26.10"
,
"resolved"
:
"https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz"
,
"resolved"
:
"https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz"
,
"integrity"
:
"sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ=="
,
"integrity"
:
"sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"@ampproject/remapping"
:
"^2.2.0"
,
"@ampproject/remapping"
:
"^2.2.0"
,
...
@@ -1120,12 +1126,14 @@
...
@@ -1120,12 +1126,14 @@
"version"
:
"2.0.0"
,
"version"
:
"2.0.0"
,
"resolved"
:
"https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz"
,
"integrity"
:
"sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="
,
"integrity"
:
"sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="
,
"dev"
:
true
,
"license"
:
"MIT"
"license"
:
"MIT"
},
},
"node_modules/@babel/core/node_modules/semver"
:
{
"node_modules/@babel/core/node_modules/semver"
:
{
"version"
:
"6.3.1"
,
"version"
:
"6.3.1"
,
"resolved"
:
"https://registry.npmjs.org/semver/-/semver-6.3.1.tgz"
,
"resolved"
:
"https://registry.npmjs.org/semver/-/semver-6.3.1.tgz"
,
"integrity"
:
"sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
,
"integrity"
:
"sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"license"
:
"ISC"
,
"bin"
:
{
"bin"
:
{
"semver"
:
"bin/semver.js"
"semver"
:
"bin/semver.js"
...
@@ -3779,16 +3787,6 @@
...
@@ -3779,16 +3787,6 @@
"@fortawesome/fontawesome-svg-core"
:
"~1.2.27 || ~1.3.0-beta2 || ^6.1.0"
"@fortawesome/fontawesome-svg-core"
:
"~1.2.27 || ~1.3.0-beta2 || ^6.1.0"
}
}
},
},
"node_modules/@fortawesome/fontawesome-common-types"
:
{
"version"
:
"6.7.2"
,
"resolved"
:
"https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz"
,
"integrity"
:
"sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg=="
,
"license"
:
"MIT"
,
"peer"
:
true
,
"engines"
:
{
"node"
:
">=6"
}
},
"node_modules/@fortawesome/fontawesome-free"
:
{
"node_modules/@fortawesome/fontawesome-free"
:
{
"version"
:
"7.0.0"
,
"version"
:
"7.0.0"
,
"resolved"
:
"https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-7.0.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-7.0.0.tgz"
,
...
@@ -3798,19 +3796,6 @@
...
@@ -3798,19 +3796,6 @@
"node"
:
">=6"
"node"
:
">=6"
}
}
},
},
"node_modules/@fortawesome/fontawesome-svg-core"
:
{
"version"
:
"6.7.2"
,
"resolved"
:
"https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.7.2.tgz"
,
"integrity"
:
"sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA=="
,
"license"
:
"MIT"
,
"peer"
:
true
,
"dependencies"
:
{
"@fortawesome/fontawesome-common-types"
:
"6.7.2"
},
"engines"
:
{
"node"
:
">=6"
}
},
"node_modules/@grpc/grpc-js"
:
{
"node_modules/@grpc/grpc-js"
:
{
"version"
:
"1.9.15"
,
"version"
:
"1.9.15"
,
"resolved"
:
"https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz"
,
"resolved"
:
"https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz"
,
...
@@ -3885,6 +3870,7 @@
...
@@ -3885,6 +3870,7 @@
"version"
:
"8.0.2"
,
"version"
:
"8.0.2"
,
"resolved"
:
"https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz"
,
"resolved"
:
"https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz"
,
"integrity"
:
"sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="
,
"integrity"
:
"sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"license"
:
"ISC"
,
"dependencies"
:
{
"dependencies"
:
{
"string-width"
:
"^5.1.2"
,
"string-width"
:
"^5.1.2"
,
...
@@ -3902,6 +3888,7 @@
...
@@ -3902,6 +3888,7 @@
"version"
:
"6.2.0"
,
"version"
:
"6.2.0"
,
"resolved"
:
"https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz"
,
"integrity"
:
"sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg=="
,
"integrity"
:
"sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"engines"
:
{
"engines"
:
{
"node"
:
">=12"
"node"
:
">=12"
...
@@ -3914,6 +3901,7 @@
...
@@ -3914,6 +3901,7 @@
"version"
:
"6.2.1"
,
"version"
:
"6.2.1"
,
"resolved"
:
"https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz"
,
"resolved"
:
"https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz"
,
"integrity"
:
"sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="
,
"integrity"
:
"sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"engines"
:
{
"engines"
:
{
"node"
:
">=12"
"node"
:
">=12"
...
@@ -3926,12 +3914,14 @@
...
@@ -3926,12 +3914,14 @@
"version"
:
"9.2.2"
,
"version"
:
"9.2.2"
,
"resolved"
:
"https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz"
,
"resolved"
:
"https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz"
,
"integrity"
:
"sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
,
"integrity"
:
"sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
,
"dev"
:
true
,
"license"
:
"MIT"
"license"
:
"MIT"
},
},
"node_modules/@isaacs/cliui/node_modules/string-width"
:
{
"node_modules/@isaacs/cliui/node_modules/string-width"
:
{
"version"
:
"5.1.2"
,
"version"
:
"5.1.2"
,
"resolved"
:
"https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz"
,
"resolved"
:
"https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz"
,
"integrity"
:
"sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="
,
"integrity"
:
"sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"eastasianwidth"
:
"^0.2.0"
,
"eastasianwidth"
:
"^0.2.0"
,
...
@@ -3949,6 +3939,7 @@
...
@@ -3949,6 +3939,7 @@
"version"
:
"7.1.0"
,
"version"
:
"7.1.0"
,
"resolved"
:
"https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz"
,
"integrity"
:
"sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="
,
"integrity"
:
"sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"ansi-regex"
:
"^6.0.1"
"ansi-regex"
:
"^6.0.1"
...
@@ -3964,6 +3955,7 @@
...
@@ -3964,6 +3955,7 @@
"version"
:
"8.1.0"
,
"version"
:
"8.1.0"
,
"resolved"
:
"https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz"
,
"integrity"
:
"sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="
,
"integrity"
:
"sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"ansi-styles"
:
"^6.1.0"
,
"ansi-styles"
:
"^6.1.0"
,
...
@@ -4083,13 +4075,6 @@
...
@@ -4083,13 +4075,6 @@
"rxjs"
:
">=7.5.0"
"rxjs"
:
">=7.5.0"
}
}
},
},
"node_modules/@kurkle/color"
:
{
"version"
:
"0.3.4"
,
"resolved"
:
"https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz"
,
"integrity"
:
"sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w=="
,
"license"
:
"MIT"
,
"peer"
:
true
},
"node_modules/@leichtgewicht/ip-codec"
:
{
"node_modules/@leichtgewicht/ip-codec"
:
{
"version"
:
"2.0.5"
,
"version"
:
"2.0.5"
,
"resolved"
:
"https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz"
,
"resolved"
:
"https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz"
,
...
@@ -5700,6 +5685,7 @@
...
@@ -5700,6 +5685,7 @@
"version"
:
"0.11.0"
,
"version"
:
"0.11.0"
,
"resolved"
:
"https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz"
,
"integrity"
:
"sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="
,
"integrity"
:
"sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"optional"
:
true
,
"optional"
:
true
,
"engines"
:
{
"engines"
:
{
...
@@ -6940,16 +6926,6 @@
...
@@ -6940,16 +6926,6 @@
"dev"
:
true
,
"dev"
:
true
,
"license"
:
"MIT"
"license"
:
"MIT"
},
},
"node_modules/@types/jquery"
:
{
"version"
:
"3.5.33"
,
"resolved"
:
"https://registry.npmjs.org/@types/jquery/-/jquery-3.5.33.tgz"
,
"integrity"
:
"sha512-SeyVJXlCZpEki5F0ghuYe+L+PprQta6nRZqhONt9F13dWBtR/ftoaIbdRQ7cis7womE+X2LKhsDdDtkkDhJS6g=="
,
"license"
:
"MIT"
,
"peer"
:
true
,
"dependencies"
:
{
"@types/sizzle"
:
"*"
}
},
"node_modules/@types/json-schema"
:
{
"node_modules/@types/json-schema"
:
{
"version"
:
"7.0.15"
,
"version"
:
"7.0.15"
,
"resolved"
:
"https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz"
,
"resolved"
:
"https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz"
,
...
@@ -7076,13 +7052,6 @@
...
@@ -7076,13 +7052,6 @@
"@types/send"
:
"*"
"@types/send"
:
"*"
}
}
},
},
"node_modules/@types/sizzle"
:
{
"version"
:
"2.3.10"
,
"resolved"
:
"https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.10.tgz"
,
"integrity"
:
"sha512-TC0dmN0K8YcWEAEfiPi5gJP14eJe30TTGjkvek3iM/1NdHHsdCA/Td6GvNndMOo/iSnIsZ4HuuhrYPDAmbxzww=="
,
"license"
:
"MIT"
,
"peer"
:
true
},
"node_modules/@types/sockjs"
:
{
"node_modules/@types/sockjs"
:
{
"version"
:
"0.3.36"
,
"version"
:
"0.3.36"
,
"resolved"
:
"https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz"
,
"resolved"
:
"https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz"
,
...
@@ -7612,6 +7581,7 @@
...
@@ -7612,6 +7581,7 @@
"version"
:
"1.3.0"
,
"version"
:
"1.3.0"
,
"resolved"
:
"https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz"
,
"integrity"
:
"sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
,
"integrity"
:
"sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
,
"dev"
:
true
,
"license"
:
"MIT"
"license"
:
"MIT"
},
},
"node_modules/anymatch"
:
{
"node_modules/anymatch"
:
{
...
@@ -7643,6 +7613,7 @@
...
@@ -7643,6 +7613,7 @@
"version"
:
"5.0.2"
,
"version"
:
"5.0.2"
,
"resolved"
:
"https://registry.npmjs.org/arg/-/arg-5.0.2.tgz"
,
"resolved"
:
"https://registry.npmjs.org/arg/-/arg-5.0.2.tgz"
,
"integrity"
:
"sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="
,
"integrity"
:
"sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="
,
"dev"
:
true
,
"license"
:
"MIT"
"license"
:
"MIT"
},
},
"node_modules/argparse"
:
{
"node_modules/argparse"
:
{
...
@@ -7796,6 +7767,7 @@
...
@@ -7796,6 +7767,7 @@
"version"
:
"1.0.2"
,
"version"
:
"1.0.2"
,
"resolved"
:
"https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
,
"resolved"
:
"https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
,
"integrity"
:
"sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
,
"integrity"
:
"sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
,
"dev"
:
true
,
"license"
:
"MIT"
"license"
:
"MIT"
},
},
"node_modules/base64-js"
:
{
"node_modules/base64-js"
:
{
...
@@ -8179,6 +8151,7 @@
...
@@ -8179,6 +8151,7 @@
"version"
:
"2.0.1"
,
"version"
:
"2.0.1"
,
"resolved"
:
"https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz"
,
"resolved"
:
"https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz"
,
"integrity"
:
"sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="
,
"integrity"
:
"sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"engines"
:
{
"engines"
:
{
"node"
:
">= 6"
"node"
:
">= 6"
...
@@ -8227,19 +8200,6 @@
...
@@ -8227,19 +8200,6 @@
"dev"
:
true
,
"dev"
:
true
,
"license"
:
"MIT"
"license"
:
"MIT"
},
},
"node_modules/chart.js"
:
{
"version"
:
"4.5.0"
,
"resolved"
:
"https://registry.npmjs.org/chart.js/-/chart.js-4.5.0.tgz"
,
"integrity"
:
"sha512-aYeC/jDgSEx8SHWZvANYMioYMZ2KX02W6f6uVfyteuCGcadDLcYVHdfdygsTQkQ4TKn5lghoojAsPj5pu0SnvQ=="
,
"license"
:
"MIT"
,
"peer"
:
true
,
"dependencies"
:
{
"@kurkle/color"
:
"^0.3.0"
},
"engines"
:
{
"pnpm"
:
">=8"
}
},
"node_modules/chokidar"
:
{
"node_modules/chokidar"
:
{
"version"
:
"3.6.0"
,
"version"
:
"3.6.0"
,
"resolved"
:
"https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz"
,
...
@@ -8457,6 +8417,7 @@
...
@@ -8457,6 +8417,7 @@
"version"
:
"4.1.1"
,
"version"
:
"4.1.1"
,
"resolved"
:
"https://registry.npmjs.org/commander/-/commander-4.1.1.tgz"
,
"resolved"
:
"https://registry.npmjs.org/commander/-/commander-4.1.1.tgz"
,
"integrity"
:
"sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="
,
"integrity"
:
"sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"engines"
:
{
"engines"
:
{
"node"
:
">= 6"
"node"
:
">= 6"
...
@@ -8595,6 +8556,7 @@
...
@@ -8595,6 +8556,7 @@
"version"
:
"1.9.0"
,
"version"
:
"1.9.0"
,
"resolved"
:
"https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz"
,
"integrity"
:
"sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
,
"integrity"
:
"sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
,
"dev"
:
true
,
"license"
:
"MIT"
"license"
:
"MIT"
},
},
"node_modules/cookie"
:
{
"node_modules/cookie"
:
{
...
@@ -8773,6 +8735,7 @@
...
@@ -8773,6 +8735,7 @@
"version"
:
"7.0.6"
,
"version"
:
"7.0.6"
,
"resolved"
:
"https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz"
,
"resolved"
:
"https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz"
,
"integrity"
:
"sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="
,
"integrity"
:
"sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"path-key"
:
"^3.1.0"
,
"path-key"
:
"^3.1.0"
,
...
@@ -8787,6 +8750,7 @@
...
@@ -8787,6 +8750,7 @@
"version"
:
"2.0.2"
,
"version"
:
"2.0.2"
,
"resolved"
:
"https://registry.npmjs.org/which/-/which-2.0.2.tgz"
,
"resolved"
:
"https://registry.npmjs.org/which/-/which-2.0.2.tgz"
,
"integrity"
:
"sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="
,
"integrity"
:
"sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"license"
:
"ISC"
,
"dependencies"
:
{
"dependencies"
:
{
"isexe"
:
"^2.0.0"
"isexe"
:
"^2.0.0"
...
@@ -8868,6 +8832,7 @@
...
@@ -8868,6 +8832,7 @@
"version"
:
"3.0.0"
,
"version"
:
"3.0.0"
,
"resolved"
:
"https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz"
,
"integrity"
:
"sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="
,
"integrity"
:
"sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"bin"
:
{
"bin"
:
{
"cssesc"
:
"bin/cssesc"
"cssesc"
:
"bin/cssesc"
...
@@ -9110,6 +9075,7 @@
...
@@ -9110,6 +9075,7 @@
"version"
:
"1.2.2"
,
"version"
:
"1.2.2"
,
"resolved"
:
"https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz"
,
"resolved"
:
"https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz"
,
"integrity"
:
"sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="
,
"integrity"
:
"sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="
,
"dev"
:
true
,
"license"
:
"Apache-2.0"
"license"
:
"Apache-2.0"
},
},
"node_modules/dir-glob"
:
{
"node_modules/dir-glob"
:
{
...
@@ -9129,6 +9095,7 @@
...
@@ -9129,6 +9095,7 @@
"version"
:
"1.1.3"
,
"version"
:
"1.1.3"
,
"resolved"
:
"https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz"
,
"resolved"
:
"https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz"
,
"integrity"
:
"sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
,
"integrity"
:
"sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
,
"dev"
:
true
,
"license"
:
"MIT"
"license"
:
"MIT"
},
},
"node_modules/dns-packet"
:
{
"node_modules/dns-packet"
:
{
...
@@ -9249,6 +9216,7 @@
...
@@ -9249,6 +9216,7 @@
"version"
:
"0.2.0"
,
"version"
:
"0.2.0"
,
"resolved"
:
"https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz"
,
"integrity"
:
"sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
,
"integrity"
:
"sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
,
"dev"
:
true
,
"license"
:
"MIT"
"license"
:
"MIT"
},
},
"node_modules/echarts"
:
{
"node_modules/echarts"
:
{
...
@@ -9316,6 +9284,7 @@
...
@@ -9316,6 +9284,7 @@
"version"
:
"0.1.13"
,
"version"
:
"0.1.13"
,
"resolved"
:
"https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz"
,
"resolved"
:
"https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz"
,
"integrity"
:
"sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A=="
,
"integrity"
:
"sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"optional"
:
true
,
"optional"
:
true
,
"dependencies"
:
{
"dependencies"
:
{
...
@@ -9326,6 +9295,7 @@
...
@@ -9326,6 +9295,7 @@
"version"
:
"0.6.3"
,
"version"
:
"0.6.3"
,
"resolved"
:
"https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz"
,
"resolved"
:
"https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz"
,
"integrity"
:
"sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="
,
"integrity"
:
"sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"optional"
:
true
,
"optional"
:
true
,
"dependencies"
:
{
"dependencies"
:
{
...
@@ -10187,6 +10157,7 @@
...
@@ -10187,6 +10157,7 @@
"version"
:
"3.3.1"
,
"version"
:
"3.3.1"
,
"resolved"
:
"https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz"
,
"resolved"
:
"https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz"
,
"integrity"
:
"sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="
,
"integrity"
:
"sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"license"
:
"ISC"
,
"dependencies"
:
{
"dependencies"
:
{
"cross-spawn"
:
"^7.0.6"
,
"cross-spawn"
:
"^7.0.6"
,
...
@@ -10203,6 +10174,7 @@
...
@@ -10203,6 +10174,7 @@
"version"
:
"4.1.0"
,
"version"
:
"4.1.0"
,
"resolved"
:
"https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz"
,
"integrity"
:
"sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="
,
"integrity"
:
"sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"license"
:
"ISC"
,
"engines"
:
{
"engines"
:
{
"node"
:
">=14"
"node"
:
">=14"
...
@@ -11295,6 +11267,7 @@
...
@@ -11295,6 +11267,7 @@
"version"
:
"2.0.0"
,
"version"
:
"2.0.0"
,
"resolved"
:
"https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz"
,
"integrity"
:
"sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
,
"integrity"
:
"sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
,
"dev"
:
true
,
"license"
:
"ISC"
"license"
:
"ISC"
},
},
"node_modules/isobject"
:
{
"node_modules/isobject"
:
{
...
@@ -11402,6 +11375,7 @@
...
@@ -11402,6 +11375,7 @@
"version"
:
"3.4.3"
,
"version"
:
"3.4.3"
,
"resolved"
:
"https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz"
,
"resolved"
:
"https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz"
,
"integrity"
:
"sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="
,
"integrity"
:
"sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="
,
"dev"
:
true
,
"license"
:
"BlueOak-1.0.0"
,
"license"
:
"BlueOak-1.0.0"
,
"dependencies"
:
{
"dependencies"
:
{
"@isaacs/cliui"
:
"^8.0.2"
"@isaacs/cliui"
:
"^8.0.2"
...
@@ -11455,6 +11429,7 @@
...
@@ -11455,6 +11429,7 @@
"version"
:
"1.21.7"
,
"version"
:
"1.21.7"
,
"resolved"
:
"https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz"
,
"resolved"
:
"https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz"
,
"integrity"
:
"sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="
,
"integrity"
:
"sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"bin"
:
{
"bin"
:
{
"jiti"
:
"bin/jiti.js"
"jiti"
:
"bin/jiti.js"
...
@@ -11944,6 +11919,7 @@
...
@@ -11944,6 +11919,7 @@
"version"
:
"1.2.4"
,
"version"
:
"1.2.4"
,
"resolved"
:
"https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz"
,
"resolved"
:
"https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz"
,
"integrity"
:
"sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
,
"integrity"
:
"sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
,
"dev"
:
true
,
"license"
:
"MIT"
"license"
:
"MIT"
},
},
"node_modules/loader-runner"
:
{
"node_modules/loader-runner"
:
{
...
@@ -12354,6 +12330,7 @@
...
@@ -12354,6 +12330,7 @@
"version"
:
"7.1.2"
,
"version"
:
"7.1.2"
,
"resolved"
:
"https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz"
,
"resolved"
:
"https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz"
,
"integrity"
:
"sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="
,
"integrity"
:
"sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"license"
:
"ISC"
,
"engines"
:
{
"engines"
:
{
"node"
:
">=16 || 14 >=14.17"
"node"
:
">=16 || 14 >=14.17"
...
@@ -12620,6 +12597,7 @@
...
@@ -12620,6 +12597,7 @@
"version"
:
"2.7.0"
,
"version"
:
"2.7.0"
,
"resolved"
:
"https://registry.npmjs.org/mz/-/mz-2.7.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/mz/-/mz-2.7.0.tgz"
,
"integrity"
:
"sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="
,
"integrity"
:
"sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"any-promise"
:
"^1.0.0"
,
"any-promise"
:
"^1.0.0"
,
...
@@ -13225,13 +13203,6 @@
...
@@ -13225,13 +13203,6 @@
"node"
:
">=0.10.0"
"node"
:
">=0.10.0"
}
}
},
},
"node_modules/nouislider"
:
{
"version"
:
"15.8.1"
,
"resolved"
:
"https://registry.npmjs.org/nouislider/-/nouislider-15.8.1.tgz"
,
"integrity"
:
"sha512-93TweAi8kqntHJSPiSWQ1o/uZ29VWOmal9YKb6KKGGlCkugaNfAupT7o1qTHqdJvNQ7S0su5rO6qRFCjP8fxtw=="
,
"license"
:
"MIT"
,
"peer"
:
true
},
"node_modules/npm"
:
{
"node_modules/npm"
:
{
"version"
:
"10.9.3"
,
"version"
:
"10.9.3"
,
"resolved"
:
"https://registry.npmjs.org/npm/-/npm-10.9.3.tgz"
,
"resolved"
:
"https://registry.npmjs.org/npm/-/npm-10.9.3.tgz"
,
...
@@ -15847,6 +15818,7 @@
...
@@ -15847,6 +15818,7 @@
"version"
:
"4.1.1"
,
"version"
:
"4.1.1"
,
"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
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"engines"
:
{
"engines"
:
{
"node"
:
">=0.10.0"
"node"
:
">=0.10.0"
...
@@ -15856,6 +15828,7 @@
...
@@ -15856,6 +15828,7 @@
"version"
:
"3.0.0"
,
"version"
:
"3.0.0"
,
"resolved"
:
"https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz"
,
"integrity"
:
"sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="
,
"integrity"
:
"sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"engines"
:
{
"engines"
:
{
"node"
:
">= 6"
"node"
:
">= 6"
...
@@ -16102,6 +16075,7 @@
...
@@ -16102,6 +16075,7 @@
"version"
:
"1.0.1"
,
"version"
:
"1.0.1"
,
"resolved"
:
"https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz"
,
"resolved"
:
"https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz"
,
"integrity"
:
"sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="
,
"integrity"
:
"sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="
,
"dev"
:
true
,
"license"
:
"BlueOak-1.0.0"
"license"
:
"BlueOak-1.0.0"
},
},
"node_modules/pacote"
:
{
"node_modules/pacote"
:
{
...
@@ -16280,6 +16254,7 @@
...
@@ -16280,6 +16254,7 @@
"version"
:
"3.1.1"
,
"version"
:
"3.1.1"
,
"resolved"
:
"https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz"
,
"resolved"
:
"https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz"
,
"integrity"
:
"sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
,
"integrity"
:
"sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"engines"
:
{
"engines"
:
{
"node"
:
">=8"
"node"
:
">=8"
...
@@ -16295,6 +16270,7 @@
...
@@ -16295,6 +16270,7 @@
"version"
:
"1.11.1"
,
"version"
:
"1.11.1"
,
"resolved"
:
"https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz"
,
"resolved"
:
"https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz"
,
"integrity"
:
"sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="
,
"integrity"
:
"sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="
,
"dev"
:
true
,
"license"
:
"BlueOak-1.0.0"
,
"license"
:
"BlueOak-1.0.0"
,
"dependencies"
:
{
"dependencies"
:
{
"lru-cache"
:
"^10.2.0"
,
"lru-cache"
:
"^10.2.0"
,
...
@@ -16311,6 +16287,7 @@
...
@@ -16311,6 +16287,7 @@
"version"
:
"10.4.3"
,
"version"
:
"10.4.3"
,
"resolved"
:
"https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz"
,
"resolved"
:
"https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz"
,
"integrity"
:
"sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="
,
"integrity"
:
"sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="
,
"dev"
:
true
,
"license"
:
"ISC"
"license"
:
"ISC"
},
},
"node_modules/path-to-regexp"
:
{
"node_modules/path-to-regexp"
:
{
...
@@ -16361,6 +16338,7 @@
...
@@ -16361,6 +16338,7 @@
"version"
:
"4.0.7"
,
"version"
:
"4.0.7"
,
"resolved"
:
"https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz"
,
"resolved"
:
"https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz"
,
"integrity"
:
"sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="
,
"integrity"
:
"sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"engines"
:
{
"engines"
:
{
"node"
:
">= 6"
"node"
:
">= 6"
...
@@ -16597,6 +16575,7 @@
...
@@ -16597,6 +16575,7 @@
"version"
:
"4.0.1"
,
"version"
:
"4.0.1"
,
"resolved"
:
"https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz"
,
"resolved"
:
"https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz"
,
"integrity"
:
"sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw=="
,
"integrity"
:
"sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"camelcase-css"
:
"^2.0.1"
"camelcase-css"
:
"^2.0.1"
...
@@ -16757,6 +16736,7 @@
...
@@ -16757,6 +16736,7 @@
"version"
:
"6.2.0"
,
"version"
:
"6.2.0"
,
"resolved"
:
"https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz"
,
"integrity"
:
"sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="
,
"integrity"
:
"sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="
,
"dev"
:
true
,
"funding"
:
[
"funding"
:
[
{
{
"type"
:
"opencollective"
,
"type"
:
"opencollective"
,
...
@@ -16782,6 +16762,7 @@
...
@@ -16782,6 +16762,7 @@
"version"
:
"6.1.2"
,
"version"
:
"6.1.2"
,
"resolved"
:
"https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz"
,
"resolved"
:
"https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz"
,
"integrity"
:
"sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="
,
"integrity"
:
"sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"cssesc"
:
"^3.0.0"
,
"cssesc"
:
"^3.0.0"
,
...
@@ -17322,6 +17303,7 @@
...
@@ -17322,6 +17303,7 @@
"version"
:
"0.2.2"
,
"version"
:
"0.2.2"
,
"resolved"
:
"https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz"
,
"resolved"
:
"https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz"
,
"integrity"
:
"sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q=="
,
"integrity"
:
"sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q=="
,
"dev"
:
true
,
"license"
:
"Apache-2.0"
"license"
:
"Apache-2.0"
},
},
"node_modules/regenerate"
:
{
"node_modules/regenerate"
:
{
...
@@ -18147,6 +18129,7 @@
...
@@ -18147,6 +18129,7 @@
"version"
:
"2.0.0"
,
"version"
:
"2.0.0"
,
"resolved"
:
"https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz"
,
"integrity"
:
"sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="
,
"integrity"
:
"sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"shebang-regex"
:
"^3.0.0"
"shebang-regex"
:
"^3.0.0"
...
@@ -18159,6 +18142,7 @@
...
@@ -18159,6 +18142,7 @@
"version"
:
"3.0.0"
,
"version"
:
"3.0.0"
,
"resolved"
:
"https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz"
,
"integrity"
:
"sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
,
"integrity"
:
"sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"engines"
:
{
"engines"
:
{
"node"
:
">=8"
"node"
:
">=8"
...
@@ -18709,6 +18693,7 @@
...
@@ -18709,6 +18693,7 @@
"version"
:
"4.2.3"
,
"version"
:
"4.2.3"
,
"resolved"
:
"https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
,
"resolved"
:
"https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
,
"integrity"
:
"sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="
,
"integrity"
:
"sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"emoji-regex"
:
"^8.0.0"
,
"emoji-regex"
:
"^8.0.0"
,
...
@@ -18736,6 +18721,7 @@
...
@@ -18736,6 +18721,7 @@
"version"
:
"6.0.1"
,
"version"
:
"6.0.1"
,
"resolved"
:
"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
,
"resolved"
:
"https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
,
"integrity"
:
"sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="
,
"integrity"
:
"sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"ansi-regex"
:
"^5.0.1"
"ansi-regex"
:
"^5.0.1"
...
@@ -18758,6 +18744,7 @@
...
@@ -18758,6 +18744,7 @@
"version"
:
"3.35.0"
,
"version"
:
"3.35.0"
,
"resolved"
:
"https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz"
,
"integrity"
:
"sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA=="
,
"integrity"
:
"sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"@jridgewell/gen-mapping"
:
"^0.3.2"
,
"@jridgewell/gen-mapping"
:
"^0.3.2"
,
...
@@ -18780,6 +18767,7 @@
...
@@ -18780,6 +18767,7 @@
"version"
:
"2.0.2"
,
"version"
:
"2.0.2"
,
"resolved"
:
"https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz"
,
"resolved"
:
"https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz"
,
"integrity"
:
"sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="
,
"integrity"
:
"sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"balanced-match"
:
"^1.0.0"
"balanced-match"
:
"^1.0.0"
...
@@ -18789,6 +18777,7 @@
...
@@ -18789,6 +18777,7 @@
"version"
:
"10.4.5"
,
"version"
:
"10.4.5"
,
"resolved"
:
"https://registry.npmjs.org/glob/-/glob-10.4.5.tgz"
,
"resolved"
:
"https://registry.npmjs.org/glob/-/glob-10.4.5.tgz"
,
"integrity"
:
"sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="
,
"integrity"
:
"sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"license"
:
"ISC"
,
"dependencies"
:
{
"dependencies"
:
{
"foreground-child"
:
"^3.1.0"
,
"foreground-child"
:
"^3.1.0"
,
...
@@ -18809,6 +18798,7 @@
...
@@ -18809,6 +18798,7 @@
"version"
:
"9.0.5"
,
"version"
:
"9.0.5"
,
"resolved"
:
"https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz"
,
"resolved"
:
"https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz"
,
"integrity"
:
"sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="
,
"integrity"
:
"sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"license"
:
"ISC"
,
"dependencies"
:
{
"dependencies"
:
{
"brace-expansion"
:
"^2.0.1"
"brace-expansion"
:
"^2.0.1"
...
@@ -18909,6 +18899,7 @@
...
@@ -18909,6 +18899,7 @@
"version"
:
"3.4.17"
,
"version"
:
"3.4.17"
,
"resolved"
:
"https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz"
,
"resolved"
:
"https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz"
,
"integrity"
:
"sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og=="
,
"integrity"
:
"sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"@alloc/quick-lru"
:
"^5.2.0"
,
"@alloc/quick-lru"
:
"^5.2.0"
,
...
@@ -18946,6 +18937,7 @@
...
@@ -18946,6 +18937,7 @@
"version"
:
"6.0.2"
,
"version"
:
"6.0.2"
,
"resolved"
:
"https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz"
,
"resolved"
:
"https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz"
,
"integrity"
:
"sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="
,
"integrity"
:
"sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"license"
:
"ISC"
,
"dependencies"
:
{
"dependencies"
:
{
"is-glob"
:
"^4.0.3"
"is-glob"
:
"^4.0.3"
...
@@ -18958,6 +18950,7 @@
...
@@ -18958,6 +18950,7 @@
"version"
:
"15.1.0"
,
"version"
:
"15.1.0"
,
"resolved"
:
"https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz"
,
"integrity"
:
"sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew=="
,
"integrity"
:
"sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"postcss-value-parser"
:
"^4.0.0"
,
"postcss-value-parser"
:
"^4.0.0"
,
...
@@ -18975,6 +18968,7 @@
...
@@ -18975,6 +18968,7 @@
"version"
:
"4.0.2"
,
"version"
:
"4.0.2"
,
"resolved"
:
"https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz"
,
"resolved"
:
"https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz"
,
"integrity"
:
"sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ=="
,
"integrity"
:
"sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ=="
,
"dev"
:
true
,
"funding"
:
[
"funding"
:
[
{
{
"type"
:
"opencollective"
,
"type"
:
"opencollective"
,
...
@@ -19010,6 +19004,7 @@
...
@@ -19010,6 +19004,7 @@
"version"
:
"6.1.2"
,
"version"
:
"6.1.2"
,
"resolved"
:
"https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz"
,
"resolved"
:
"https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz"
,
"integrity"
:
"sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="
,
"integrity"
:
"sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"cssesc"
:
"^3.0.0"
,
"cssesc"
:
"^3.0.0"
,
...
@@ -19225,6 +19220,7 @@
...
@@ -19225,6 +19220,7 @@
"version"
:
"3.3.1"
,
"version"
:
"3.3.1"
,
"resolved"
:
"https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz"
,
"resolved"
:
"https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz"
,
"integrity"
:
"sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="
,
"integrity"
:
"sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"any-promise"
:
"^1.0.0"
"any-promise"
:
"^1.0.0"
...
@@ -19234,6 +19230,7 @@
...
@@ -19234,6 +19230,7 @@
"version"
:
"1.6.0"
,
"version"
:
"1.6.0"
,
"resolved"
:
"https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz"
,
"integrity"
:
"sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="
,
"integrity"
:
"sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"thenify"
:
">= 3.1.0 < 4"
"thenify"
:
">= 3.1.0 < 4"
...
@@ -19347,6 +19344,7 @@
...
@@ -19347,6 +19344,7 @@
"version"
:
"0.1.13"
,
"version"
:
"0.1.13"
,
"resolved"
:
"https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz"
,
"resolved"
:
"https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz"
,
"integrity"
:
"sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
,
"integrity"
:
"sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
,
"dev"
:
true
,
"license"
:
"Apache-2.0"
"license"
:
"Apache-2.0"
},
},
"node_modules/tslib"
:
{
"node_modules/tslib"
:
{
...
@@ -19407,6 +19405,7 @@
...
@@ -19407,6 +19405,7 @@
"version"
:
"5.2.2"
,
"version"
:
"5.2.2"
,
"resolved"
:
"https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz"
,
"resolved"
:
"https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz"
,
"integrity"
:
"sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w=="
,
"integrity"
:
"sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w=="
,
"dev"
:
true
,
"license"
:
"Apache-2.0"
,
"license"
:
"Apache-2.0"
,
"bin"
:
{
"bin"
:
{
"tsc"
:
"bin/tsc"
,
"tsc"
:
"bin/tsc"
,
...
@@ -20595,6 +20594,7 @@
...
@@ -20595,6 +20594,7 @@
"version"
:
"7.0.0"
,
"version"
:
"7.0.0"
,
"resolved"
:
"https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
,
"integrity"
:
"sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="
,
"integrity"
:
"sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"MIT"
,
"dependencies"
:
{
"dependencies"
:
{
"ansi-styles"
:
"^4.0.0"
,
"ansi-styles"
:
"^4.0.0"
,
...
...
src/app/authentication/login/login.component.ts
View file @
23e076c8
...
@@ -17,12 +17,14 @@ import { LoginModel } from '../../shared/user-auth.model';
...
@@ -17,12 +17,14 @@ import { LoginModel } from '../../shared/user-auth.model';
import
{
HttpClientModule
}
from
'@angular/common/http'
;
import
{
HttpClientModule
}
from
'@angular/common/http'
;
import
{
Validators
}
from
'ngx-editor'
;
import
{
Validators
}
from
'ngx-editor'
;
import
{
EmployeeService
}
from
'../../portal-manage/services/employee.service'
;
import
{
EmployeeService
}
from
'../../portal-manage/services/employee.service'
;
import
{
EmployeeAuthService
}
from
'../../portal-manage/services/employee-auth.service'
;
import
{
JwtService
}
from
'../../portal-manage/services/jwt.service'
;
@
Component
({
@
Component
({
selector
:
'app-login'
,
selector
:
'app-login'
,
standalone
:
true
,
standalone
:
true
,
imports
:
[
SharedModule
,
CarouselModule
,
CommonModule
,
RouterModule
,
FormsModule
,
HttpClientModule
,
ReactiveFormsModule
],
imports
:
[
SharedModule
,
CarouselModule
,
CommonModule
,
RouterModule
,
FormsModule
,
HttpClientModule
,
ReactiveFormsModule
],
providers
:
[
AuthService
,
{
provide
:
ToastrService
,
useClass
:
ToastrService
}],
providers
:
[
AuthService
,
EmployeeAuthService
,
JwtService
,
{
provide
:
ToastrService
,
useClass
:
ToastrService
}],
templateUrl
:
'./login.component.html'
,
templateUrl
:
'./login.component.html'
,
styleUrl
:
'./login.component.scss'
styleUrl
:
'./login.component.scss'
})
})
...
@@ -43,7 +45,9 @@ export class LoginComponent {
...
@@ -43,7 +45,9 @@ export class LoginComponent {
private
routes
:
Router
,
private
routes
:
Router
,
private
formBuilder
:
FormBuilder
,
private
formBuilder
:
FormBuilder
,
public
authService
:
AuthService
,
public
authService
:
AuthService
,
private
empServie
:
EmployeeService
private
empServie
:
EmployeeService
,
private
employeeAuthService
:
EmployeeAuthService
,
private
jwtService
:
JwtService
)
{
)
{
localStorage
.
clear
()
localStorage
.
clear
()
}
}
...
@@ -135,22 +139,111 @@ export class LoginComponent {
...
@@ -135,22 +139,111 @@ export class LoginComponent {
let
loginCredentials
:
LoginModel
=
new
LoginModel
();
let
loginCredentials
:
LoginModel
=
new
LoginModel
();
loginCredentials
.
username
=
this
.
loginForm
.
controls
[
'username'
].
value
;
loginCredentials
.
username
=
this
.
loginForm
.
controls
[
'username'
].
value
;
loginCredentials
.
password
=
this
.
loginForm
.
controls
[
'password'
].
value
;
loginCredentials
.
password
=
this
.
loginForm
.
controls
[
'password'
].
value
;
this
.
authService
.
login
(
loginCredentials
).
subscribe
({
this
.
authService
.
login
(
loginCredentials
).
subscribe
({
next
:
(
response
)
=>
{
next
:
(
response
)
=>
{
console
.
log
(
'Login successful'
,
response
);
console
.
log
(
'Login successful'
,
response
);
// Assuming your API returns a token, store it
// บันทึก token ใน TokenService
if
(
response
.
accessToken
)
{
if
(
response
.
accessToken
)
{
this
.
tokenService
.
saveToken
(
response
.
accessToken
);
this
.
tokenService
.
saveToken
(
response
.
accessToken
);
}
}
// ตรวจสอบว่าเป็น JWT token หรือไม่
if
(
response
.
accessToken
&&
this
.
isJwtToken
(
response
.
accessToken
))
{
console
.
log
(
'JWT token detected, processing...'
);
this
.
processJwtToken
(
response
.
accessToken
);
}
else
{
console
.
log
(
'Regular token, using traditional auth...'
);
this
.
processRegularToken
(
response
);
}
this
.
routes
.
navigate
([
'/home'
]);
this
.
routes
.
navigate
([
'/home'
]);
},
},
error
:
(
error
)
=>
{
error
:
(
error
)
=>
{
console
.
error
(
'Login failed'
,
error
);
console
.
error
(
'Login failed'
,
error
);
// Handle login error, e.g., display an error message to the user
this
.
showLoader
=
false
;
this
.
error
=
'Username หรือ Password ไม่ถูกต้อง'
;
}
}
});
});
}
}
/**
* ตรวจสอบว่าเป็น JWT token หรือไม่
*/
private
isJwtToken
(
token
:
string
):
boolean
{
try
{
const
parts
=
token
.
split
(
'.'
);
return
parts
.
length
===
3
;
}
catch
{
return
false
;
}
}
/**
* ประมวลผล JWT token
*/
private
processJwtToken
(
jwtToken
:
string
):
void
{
try
{
// ตรวจสอบความถูกต้องของ JWT token
const
decoded
=
this
.
jwtService
.
decodeToken
(
jwtToken
);
if
(
decoded
.
isValid
&&
!
decoded
.
isExpired
&&
decoded
.
payload
)
{
console
.
log
(
'JWT token is valid:'
,
decoded
.
payload
);
// บันทึก JWT token ใน localStorage
localStorage
.
setItem
(
'jwtToken'
,
jwtToken
);
// Authenticate ด้วย JWT
this
.
employeeAuthService
.
authenticateByJwtToken
(
jwtToken
).
subscribe
(
jwtEmployee
=>
{
if
(
jwtEmployee
)
{
console
.
log
(
'JWT Employee authenticated successfully:'
,
jwtEmployee
);
this
.
showLoader
=
false
;
}
else
{
console
.
error
(
'JWT authentication failed'
);
this
.
showLoader
=
false
;
this
.
error
=
'การยืนยันตัวตนล้มเหลว'
;
}
});
}
else
{
console
.
error
(
'Invalid or expired JWT token:'
,
decoded
.
error
);
this
.
showLoader
=
false
;
this
.
error
=
'Token ไม่ถูกต้องหรือหมดอายุ'
;
}
}
catch
(
error
)
{
console
.
error
(
'JWT processing error:'
,
error
);
this
.
showLoader
=
false
;
this
.
error
=
'เกิดข้อผิดพลาดในการประมวลผล Token'
;
}
}
/**
* ประมวลผล regular token
*/
private
processRegularToken
(
response
:
any
):
void
{
try
{
// ใช้ traditional authentication
if
(
response
.
userId
||
response
.
employeeId
)
{
const
employeeId
=
response
.
employeeId
||
response
.
userId
;
this
.
employeeAuthService
.
authenticateByEmployeeId
(
employeeId
).
subscribe
(
employee
=>
{
if
(
employee
)
{
console
.
log
(
'Employee authenticated successfully:'
,
employee
);
this
.
showLoader
=
false
;
}
else
{
console
.
log
(
'Employee not found, using default authentication'
);
this
.
showLoader
=
false
;
}
});
}
else
{
console
.
log
(
'No employee ID found, using default authentication'
);
this
.
showLoader
=
false
;
}
}
catch
(
error
)
{
console
.
error
(
'Regular token processing error:'
,
error
);
this
.
showLoader
=
false
;
}
}
// adminCompanyList(memberId: string) {
// adminCompanyList(memberId: string) {
// this.empServie.getCompanyAdmin(memberId).subscribe(result => {
// this.empServie.getCompanyAdmin(memberId).subscribe(result => {
// if (result.length > 0) {
// if (result.length > 0) {
...
...
src/app/portal-manage/home/home.component.html
View file @
23e076c8
...
@@ -61,6 +61,7 @@
...
@@ -61,6 +61,7 @@
<div
class=
"font-bold text-gray-800 text-lg"
>
{{ userInfo.fullName }}
</div>
<div
class=
"font-bold text-gray-800 text-lg"
>
{{ userInfo.fullName }}
</div>
<div
class=
"text-sm text-gray-600"
>
{{ userInfo.department }}
</div>
<div
class=
"text-sm text-gray-600"
>
{{ userInfo.department }}
</div>
<div
class=
"text-xs text-gray-500"
>
{{ userInfo.position }}
</div>
<div
class=
"text-xs text-gray-500"
>
{{ userInfo.position }}
</div>
<div
class=
"text-xs text-blue-600 font-medium"
>
รหัส: {{ userInfo.employeeId }}
</div>
</div>
</div>
</div>
</div>
<button
<button
...
...
src/app/portal-manage/home/home.component.ts
View file @
23e076c8
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
Router
,
RouterLink
,
RouterModule
}
from
'@angular/router'
;
import
{
Router
,
RouterLink
,
RouterModule
}
from
'@angular/router'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
CommonModule
}
from
'@angular/common'
;
import
{
Observable
,
combineLatest
}
from
'rxjs'
;
import
{
Observable
,
combineLatest
,
of
}
from
'rxjs'
;
import
{
map
}
from
'rxjs/operators'
;
import
{
map
}
from
'rxjs/operators'
;
import
{
TokenService
}
from
'../../shared/services/token.service'
;
import
{
TokenService
}
from
'../../shared/services/token.service'
;
import
{
MenuPermissionService
}
from
'../services/menu-permission.service'
;
import
{
MenuPermissionService
}
from
'../services/menu-permission.service'
;
import
{
UserRoleService
}
from
'../services/user-role.service'
;
import
{
UserRoleService
}
from
'../services/user-role.service'
;
import
{
EmployeeAuthService
,
Employee
}
from
'../services/employee-auth.service'
;
import
{
EmployeeFromJwt
}
from
'../models/jwt-token.model'
;
interface
AppModule
{
interface
AppModule
{
id
:
string
;
id
:
string
;
...
@@ -25,6 +27,19 @@ interface AppModule {
...
@@ -25,6 +27,19 @@ interface AppModule {
};
};
}
}
interface
UserInfo
{
fullName
:
string
;
email
:
string
;
department
:
string
;
position
:
string
;
employeeId
:
string
;
phone
:
string
;
picture
:
string
;
username
?:
string
;
userLevel
?:
string
;
companyName
?:
string
;
}
@
Component
({
@
Component
({
selector
:
'app-home'
,
selector
:
'app-home'
,
templateUrl
:
'./home.component.html'
,
templateUrl
:
'./home.component.html'
,
...
@@ -34,42 +49,149 @@ interface AppModule {
...
@@ -34,42 +49,149 @@ interface AppModule {
})
})
export
class
HomeComponent
implements
OnInit
{
export
class
HomeComponent
implements
OnInit
{
accessibleApps$
:
Observable
<
AppModule
[]
>
;
accessibleApps$
:
Observable
<
AppModule
[]
>
;
userInfo$
:
Observable
<
any
>
;
userInfo$
:
Observable
<
UserInfo
>
;
currentEmployee$
:
Observable
<
Employee
|
null
>
;
currentJwtEmployee$
:
Observable
<
EmployeeFromJwt
|
null
>
;
constructor
(
constructor
(
private
router
:
Router
,
private
router
:
Router
,
private
tokenService
:
TokenService
,
private
tokenService
:
TokenService
,
private
menuPermissionService
:
MenuPermissionService
,
private
menuPermissionService
:
MenuPermissionService
,
private
userRoleService
:
UserRoleService
private
userRoleService
:
UserRoleService
,
private
employeeAuthService
:
EmployeeAuthService
)
{
}
)
{
}
ngOnInit
():
void
{
ngOnInit
():
void
{
this
.
loadAccessibleApps
();
this
.
loadAccessibleApps
();
this
.
loadUserInfo
();
this
.
loadUserInfo
();
this
.
initializeAuth
();
}
private
initializeAuth
():
void
{
// ตรวจสอบ JWT token ก่อน
this
.
employeeAuthService
.
authenticateFromStoredJwt
().
subscribe
(
jwtEmployee
=>
{
if
(
jwtEmployee
)
{
console
.
log
(
'JWT Employee authenticated:'
,
jwtEmployee
);
this
.
currentJwtEmployee$
=
this
.
employeeAuthService
.
currentJwtEmployee$
;
return
;
}
});
// ถ้าไม่มี JWT token ให้ตรวจสอบ auth-token
const
authToken
=
localStorage
.
getItem
(
'authToken'
)
||
sessionStorage
.
getItem
(
'authToken'
);
if
(
authToken
)
{
this
.
employeeAuthService
.
authenticateByToken
(
authToken
).
subscribe
(
employee
=>
{
if
(
employee
)
{
console
.
log
(
'Employee authenticated:'
,
employee
);
}
else
{
console
.
log
(
'Invalid auth token'
);
this
.
logout
();
}
});
}
else
{
// ถ้าไม่มี auth-token ให้ใช้รหัสพนักงานเริ่มต้น
this
.
employeeAuthService
.
authenticateByEmployeeId
(
'20180210'
).
subscribe
(
employee
=>
{
if
(
employee
)
{
console
.
log
(
'Employee authenticated by ID:'
,
employee
);
}
});
}
this
.
currentEmployee$
=
this
.
employeeAuthService
.
currentEmployee$
;
this
.
currentJwtEmployee$
=
this
.
employeeAuthService
.
currentJwtEmployee$
;
}
}
private
loadAccessibleApps
():
void
{
private
loadAccessibleApps
():
void
{
this
.
accessibleApps$
=
combineLatest
([
// แสดงทุกเมนูก่อน โดยไม่ต้องตรวจสอบสิทธิ์
this
.
menuPermissionService
.
getAccessibleMenus
(),
this
.
accessibleApps$
=
of
(
this
.
getAppModules
());
this
.
menuPermissionService
.
menuPermissions$
]).
pipe
(
// หลังจากนี้สามารถเพิ่มการตรวจสอบสิทธิ์ได้
map
(([
accessibleMenus
,
allMenus
])
=>
{
// this.accessibleApps$ = combineLatest([
return
this
.
getAppModules
().
filter
(
app
=>
{
// this.employeeAuthService.currentEmployee$,
const
menu
=
this
.
findMenuByPath
(
allMenus
,
app
.
path
);
// this.employeeAuthService.currentJwtEmployee$,
return
menu
&&
menu
.
isVisible
&&
menu
.
permissions
.
view
;
// this.menuPermissionService.getAccessibleMenus(),
});
// this.menuPermissionService.menuPermissions$
})
// ]).pipe(
);
// map(([currentEmployee, currentJwtEmployee, accessibleMenus, allMenus]) => {
// // ตรวจสอบ JWT employee ก่อน
// if (currentJwtEmployee) {
// return this.getAppModules().filter(app => {
// const hasJwtPermission = this.employeeAuthService.hasJwtMenuPermission(app.id, 'view');
// return hasJwtPermission;
// });
// }
// // ถ้าไม่มี JWT ให้ใช้ employee permissions
// if (!currentEmployee) {
// return [];
// }
// return this.getAppModules().filter(app => {
// // ตรวจสอบสิทธิ์จาก employee permissions
// const hasPermission = this.employeeAuthService.hasMenuPermission(app.id, 'view');
// // ตรวจสอบสิทธิ์จาก menu permissions
// const menu = this.findMenuByPath(allMenus, app.path);
// const hasMenuPermission = menu && menu.isVisible && menu.permissions.view;
// return hasPermission || hasMenuPermission;
// });
// })
// );
}
}
private
loadUserInfo
():
void
{
private
loadUserInfo
():
void
{
// Load current user info
// Load current user info from JWT employee หรือ employee auth service
this
.
userInfo$
=
this
.
userRoleService
.
getUserById
(
'current-user'
).
pipe
(
this
.
userInfo$
=
combineLatest
([
map
(
user
=>
user
||
{
this
.
employeeAuthService
.
currentJwtEmployee$
,
fullName
:
'ผู้ใช้ปัจจุบัน'
,
this
.
employeeAuthService
.
currentEmployee$
email
:
'user@company.com'
,
]).
pipe
(
department
:
'IT'
,
map
(([
jwtEmployee
,
employee
])
=>
{
position
:
'System User'
// ใช้ JWT employee ก่อน
if
(
jwtEmployee
)
{
return
{
fullName
:
jwtEmployee
.
fullName
,
email
:
jwtEmployee
.
email
,
department
:
jwtEmployee
.
department
,
position
:
jwtEmployee
.
position
,
employeeId
:
jwtEmployee
.
employeeId
,
phone
:
''
,
// JWT ไม่มี phone
picture
:
'default.jpg'
,
username
:
jwtEmployee
.
username
,
userLevel
:
jwtEmployee
.
userLevel
,
companyName
:
jwtEmployee
.
companyName
};
}
// ถ้าไม่มี JWT ให้ใช้ employee
if
(
employee
)
{
return
{
fullName
:
`
${
employee
.
fname
}
${
employee
.
lname
}
`
,
email
:
employee
.
email
,
department
:
employee
.
bu1
.
tdesc
,
position
:
employee
.
position
.
tdesc
,
employeeId
:
employee
.
employeeId
,
phone
:
employee
.
phone
,
picture
:
employee
.
picture
,
username
:
''
,
userLevel
:
''
,
companyName
:
''
};
}
return
{
fullName
:
'ผู้ใช้ปัจจุบัน'
,
email
:
'user@company.com'
,
department
:
'IT'
,
position
:
'System User'
,
employeeId
:
'00000000'
,
phone
:
'000-000-0000'
,
picture
:
'default.jpg'
,
username
:
''
,
userLevel
:
''
,
companyName
:
''
};
})
})
);
);
}
}
...
@@ -147,7 +269,17 @@ export class HomeComponent implements OnInit {
...
@@ -147,7 +269,17 @@ export class HomeComponent implements OnInit {
permissions
:
{
view
:
true
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
,
import
:
false
}
permissions
:
{
view
:
true
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
,
import
:
false
}
},
},
{
{
id
:
'permission-management'
,
id
:
'dashboard'
,
name
:
'dashboard'
,
displayName
:
'Dashboard'
,
description
:
'แดชบอร์ดหลัก'
,
icon
:
'./assets/images/icons/dashboard.png'
,
path
:
'/dashboard'
,
isVisible
:
true
,
permissions
:
{
view
:
true
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
,
import
:
false
}
},
{
id
:
'permissionManagement'
,
name
:
'permission-management'
,
name
:
'permission-management'
,
displayName
:
'Permission Management'
,
displayName
:
'Permission Management'
,
description
:
'ระบบจัดการสิทธิ์และบทบาท'
,
description
:
'ระบบจัดการสิทธิ์และบทบาท'
,
...
@@ -157,7 +289,17 @@ export class HomeComponent implements OnInit {
...
@@ -157,7 +289,17 @@ export class HomeComponent implements OnInit {
permissions
:
{
view
:
true
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
,
import
:
false
}
permissions
:
{
view
:
true
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
,
import
:
false
}
},
},
{
{
id
:
'menu-permission-management'
,
id
:
'roleManagement'
,
name
:
'role-management'
,
displayName
:
'Role Management'
,
description
:
'ระบบจัดการบทบาท'
,
icon
:
'./assets/images/icons/users.png'
,
path
:
'/portal-manage/role-management'
,
isVisible
:
true
,
permissions
:
{
view
:
true
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
,
import
:
false
}
},
{
id
:
'menuPermissionManagement'
,
name
:
'menu-permission-management'
,
name
:
'menu-permission-management'
,
displayName
:
'Menu Permission'
,
displayName
:
'Menu Permission'
,
description
:
'ระบบจัดการสิทธิ์เมนู'
,
description
:
'ระบบจัดการสิทธิ์เมนู'
,
...
@@ -167,7 +309,7 @@ export class HomeComponent implements OnInit {
...
@@ -167,7 +309,7 @@ export class HomeComponent implements OnInit {
permissions
:
{
view
:
true
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
,
import
:
false
}
permissions
:
{
view
:
true
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
,
import
:
false
}
},
},
{
{
id
:
'user
-role-m
anagement'
,
id
:
'user
M
anagement'
,
name
:
'user-role-management'
,
name
:
'user-role-management'
,
displayName
:
'User & Role Management'
,
displayName
:
'User & Role Management'
,
description
:
'ระบบจัดการผู้ใช้และบทบาท'
,
description
:
'ระบบจัดการผู้ใช้และบทบาท'
,
...
@@ -177,7 +319,7 @@ export class HomeComponent implements OnInit {
...
@@ -177,7 +319,7 @@ export class HomeComponent implements OnInit {
permissions
:
{
view
:
true
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
,
import
:
false
}
permissions
:
{
view
:
true
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
,
import
:
false
}
},
},
{
{
id
:
'meeting
-b
ooking'
,
id
:
'meeting
B
ooking'
,
name
:
'meeting-booking'
,
name
:
'meeting-booking'
,
displayName
:
'Meeting Booking'
,
displayName
:
'Meeting Booking'
,
description
:
'ระบบจองห้องประชุม'
,
description
:
'ระบบจองห้องประชุม'
,
...
@@ -187,7 +329,7 @@ export class HomeComponent implements OnInit {
...
@@ -187,7 +329,7 @@ export class HomeComponent implements OnInit {
permissions
:
{
view
:
true
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
,
import
:
false
}
permissions
:
{
view
:
true
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
,
import
:
false
}
},
},
{
{
id
:
'company
-m
anagement'
,
id
:
'company
M
anagement'
,
name
:
'company-management'
,
name
:
'company-management'
,
displayName
:
'Company Management'
,
displayName
:
'Company Management'
,
description
:
'ระบบจัดการบริษัท'
,
description
:
'ระบบจัดการบริษัท'
,
...
@@ -197,7 +339,17 @@ export class HomeComponent implements OnInit {
...
@@ -197,7 +339,17 @@ export class HomeComponent implements OnInit {
permissions
:
{
view
:
true
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
,
import
:
false
}
permissions
:
{
view
:
true
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
,
import
:
false
}
},
},
{
{
id
:
'dashboard-management'
,
id
:
'widgetManagement'
,
name
:
'widget-management'
,
displayName
:
'Widget Management'
,
description
:
'ระบบจัดการวิดเจ็ต'
,
icon
:
'./assets/images/icons/widget.png'
,
path
:
'/portal-manage/widget-management'
,
isVisible
:
true
,
permissions
:
{
view
:
true
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
,
import
:
false
}
},
{
id
:
'dashboardManagement'
,
name
:
'dashboard-management'
,
name
:
'dashboard-management'
,
displayName
:
'Dashboard Management'
,
displayName
:
'Dashboard Management'
,
description
:
'ระบบจัดการแดชบอร์ด'
,
description
:
'ระบบจัดการแดชบอร์ด'
,
...
@@ -223,6 +375,7 @@ export class HomeComponent implements OnInit {
...
@@ -223,6 +375,7 @@ export class HomeComponent implements OnInit {
}
}
logout
()
{
logout
()
{
this
.
employeeAuthService
.
logout
();
this
.
tokenService
.
signOut
();
this
.
tokenService
.
signOut
();
}
}
...
...
src/app/portal-manage/models/jwt-token.model.ts
0 → 100644
View file @
23e076c8
export
interface
JwtTokenPayload
{
schema
:
string
;
encode
:
string
;
sub
:
string
;
companyName
:
string
;
dbName
:
string
;
roles
:
string
[];
workarea
:
string
;
iss
:
string
;
zmlogin
:
string
;
role_level
:
string
;
employeeid
:
string
;
branch
:
string
;
emp_position
:
string
;
user_role
:
string
;
uid
:
string
;
companyid
:
string
;
actorid
:
string
;
lang
:
string
;
ad
:
string
;
firstlogin
:
string
;
url_myhr
:
string
;
app_name
:
string
;
regionallty
:
string
;
token_zeeme
:
string
;
user_level
:
string
;
fullname
:
string
;
comid
:
string
;
job
:
string
;
user
:
string
;
zm_user
:
string
;
username
:
string
;
memberid
:
string
;
}
export
interface
JwtTokenHeader
{
alg
:
string
;
typ
:
string
;
}
export
interface
JwtToken
{
header
:
JwtTokenHeader
;
payload
:
JwtTokenPayload
;
signature
:
string
;
}
export
interface
DecodedJwtToken
{
isValid
:
boolean
;
isExpired
:
boolean
;
payload
:
JwtTokenPayload
|
null
;
error
?:
string
;
}
export
interface
EmployeeFromJwt
{
employeeId
:
string
;
fullName
:
string
;
username
:
string
;
email
:
string
;
position
:
string
;
job
:
string
;
department
:
string
;
companyName
:
string
;
companyId
:
string
;
branch
:
string
;
workarea
:
string
;
userLevel
:
string
;
roles
:
string
[];
language
:
string
;
isFirstLogin
:
boolean
;
isAdUser
:
boolean
;
urlMyhr
:
string
;
appName
:
string
;
regionallty
:
string
;
tokenZeeme
:
string
;
zmUser
:
string
;
memberId
:
string
;
}
src/app/portal-manage/services/employee-auth.service.ts
0 → 100644
View file @
23e076c8
import
{
Injectable
}
from
'@angular/core'
;
import
{
HttpClient
}
from
'@angular/common/http'
;
import
{
BehaviorSubject
,
Observable
,
of
}
from
'rxjs'
;
import
{
map
,
tap
,
catchError
}
from
'rxjs/operators'
;
import
{
JwtService
}
from
'./jwt.service'
;
import
{
EmployeeFromJwt
}
from
'../models/jwt-token.model'
;
export
interface
Employee
{
employeeId
:
string
;
authToken
:
string
;
bossId
:
string
;
fname
:
string
;
lname
:
string
;
efname
:
string
;
elname
:
string
;
email
:
string
;
phone
:
string
;
bu1
:
{
bu1id
:
string
;
tdesc
:
string
;
edesc
:
string
;
};
bu2
:
{
bu2id
:
string
;
tdesc
:
string
;
edesc
:
string
;
parent
:
string
|
null
;
};
bu3
:
{
bu3id
:
string
;
tdesc
:
string
;
edesc
:
string
;
parent
:
string
|
null
;
};
position
:
{
positionId
:
string
;
tdesc
:
string
;
edesc
:
string
;
consolidate
:
string
;
shortName
:
string
;
};
pl
:
{
plId
:
string
;
tdesc
:
string
;
edesc
:
string
;
};
picture
:
string
;
busNo
:
string
;
status
:
{
active
:
boolean
;
lastLogin
:
string
;
loginCount
:
number
;
};
menuPermissions
:
{
[
key
:
string
]:
{
view
:
boolean
;
create
?:
boolean
;
edit
?:
boolean
;
delete
?:
boolean
;
export
?:
boolean
;
};
};
}
@
Injectable
({
providedIn
:
'root'
})
export
class
EmployeeAuthService
{
private
currentEmployeeSubject
=
new
BehaviorSubject
<
Employee
|
null
>
(
null
);
public
currentEmployee$
=
this
.
currentEmployeeSubject
.
asObservable
();
private
currentJwtEmployeeSubject
=
new
BehaviorSubject
<
EmployeeFromJwt
|
null
>
(
null
);
public
currentJwtEmployee$
=
this
.
currentJwtEmployeeSubject
.
asObservable
();
private
employeesSubject
=
new
BehaviorSubject
<
Employee
[]
>
([]);
public
employees$
=
this
.
employeesSubject
.
asObservable
();
constructor
(
private
http
:
HttpClient
,
private
jwtService
:
JwtService
)
{
this
.
loadEmployees
();
}
/**
* โหลดข้อมูลพนักงานทั้งหมด
*/
private
loadEmployees
():
void
{
this
.
http
.
get
<
Employee
[]
>
(
'/assets/data/employeelist.json'
)
.
pipe
(
tap
(
employees
=>
this
.
employeesSubject
.
next
(
employees
)),
catchError
(
error
=>
{
console
.
error
(
'Error loading employees:'
,
error
);
return
of
([]);
})
)
.
subscribe
();
}
/**
* ตรวจสอบ auth-token และดึงข้อมูลพนักงาน
*/
authenticateByToken
(
authToken
:
string
):
Observable
<
Employee
|
null
>
{
return
this
.
employees$
.
pipe
(
map
(
employees
=>
{
const
employee
=
employees
.
find
(
emp
=>
emp
.
authToken
===
authToken
);
if
(
employee
)
{
this
.
currentEmployeeSubject
.
next
(
employee
);
return
employee
;
}
return
null
;
})
);
}
/**
* ตรวจสอบ JWT token และดึงข้อมูลพนักงาน
*/
authenticateByJwtToken
(
jwtToken
:
string
):
Observable
<
EmployeeFromJwt
|
null
>
{
try
{
const
jwtEmployee
=
this
.
jwtService
.
getEmployeeFromToken
(
jwtToken
);
if
(
jwtEmployee
)
{
this
.
currentJwtEmployeeSubject
.
next
(
jwtEmployee
);
// บันทึก token ใน localStorage
localStorage
.
setItem
(
'jwtToken'
,
jwtToken
);
return
of
(
jwtEmployee
);
}
else
{
this
.
currentJwtEmployeeSubject
.
next
(
null
);
return
of
(
null
);
}
}
catch
(
error
)
{
console
.
error
(
'JWT authentication error:'
,
error
);
this
.
currentJwtEmployeeSubject
.
next
(
null
);
return
of
(
null
);
}
}
/**
* ตรวจสอบ JWT token จาก localStorage
*/
authenticateFromStoredJwt
():
Observable
<
EmployeeFromJwt
|
null
>
{
const
storedToken
=
localStorage
.
getItem
(
'jwtToken'
)
||
sessionStorage
.
getItem
(
'jwtToken'
);
if
(
storedToken
)
{
return
this
.
authenticateByJwtToken
(
storedToken
);
}
return
of
(
null
);
}
/**
* ตรวจสอบ auth-token โดยใช้รหัสพนักงาน
*/
authenticateByEmployeeId
(
employeeId
:
string
):
Observable
<
Employee
|
null
>
{
return
this
.
employees$
.
pipe
(
map
(
employees
=>
{
const
employee
=
employees
.
find
(
emp
=>
emp
.
employeeId
===
employeeId
);
if
(
employee
)
{
this
.
currentEmployeeSubject
.
next
(
employee
);
return
employee
;
}
return
null
;
})
);
}
/**
* ดึงข้อมูลพนักงานปัจจุบัน
*/
getCurrentEmployee
():
Employee
|
null
{
return
this
.
currentEmployeeSubject
.
value
;
}
/**
* ดึงข้อมูลพนักงานจาก JWT
*/
getCurrentJwtEmployee
():
EmployeeFromJwt
|
null
{
return
this
.
currentJwtEmployeeSubject
.
value
;
}
/**
* ตรวจสอบสิทธิ์การเข้าถึงเมนูจาก JWT
*/
hasJwtMenuPermission
(
menuKey
:
string
,
action
:
string
=
'view'
):
boolean
{
const
currentJwtEmployee
=
this
.
getCurrentJwtEmployee
();
if
(
!
currentJwtEmployee
)
{
return
false
;
}
// ตรวจสอบจาก user level
const
userLevel
=
currentJwtEmployee
.
userLevel
;
const
isAdmin
=
userLevel
.
includes
(
'Admin'
)
||
userLevel
.
includes
(
'Manager'
)
||
userLevel
.
includes
(
'Executive'
);
if
(
isAdmin
)
{
return
true
;
// Admin มีสิทธิ์ทุกอย่าง
}
// ตรวจสอบจาก roles
const
roles
=
currentJwtEmployee
.
roles
;
if
(
roles
.
includes
(
'ADMIN'
)
||
roles
.
includes
(
'MANAGER'
))
{
return
true
;
}
// ตรวจสอบสิทธิ์ตาม menu
const
menuPermissions
=
this
.
getJwtMenuPermissions
();
if
(
menuPermissions
[
menuKey
])
{
return
menuPermissions
[
menuKey
][
action
as
keyof
typeof
menuPermissions
[
typeof
menuKey
]]
===
true
;
}
return
false
;
}
/**
* ดึงสิทธิ์การเข้าถึงเมนูจาก JWT
*/
getJwtMenuPermissions
():
{
[
key
:
string
]:
any
}
{
const
currentJwtEmployee
=
this
.
getCurrentJwtEmployee
();
if
(
!
currentJwtEmployee
)
{
return
{};
}
const
userLevel
=
currentJwtEmployee
.
userLevel
;
const
isAdmin
=
userLevel
.
includes
(
'Admin'
)
||
userLevel
.
includes
(
'Manager'
)
||
userLevel
.
includes
(
'Executive'
);
if
(
isAdmin
)
{
// Admin มีสิทธิ์ทุกอย่าง
return
{
dashboard
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
},
userManagement
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
},
roleManagement
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
},
permissionManagement
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
},
menuPermissionManagement
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
},
meetingBooking
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
},
companyManagement
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
},
widgetManagement
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
},
dashboardManagement
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
true
,
export
:
true
}
};
}
// Employee มีสิทธิ์จำกัด
return
{
dashboard
:
{
view
:
true
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
},
userManagement
:
{
view
:
true
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
},
roleManagement
:
{
view
:
false
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
},
permissionManagement
:
{
view
:
false
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
},
menuPermissionManagement
:
{
view
:
false
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
},
meetingBooking
:
{
view
:
true
,
create
:
true
,
edit
:
true
,
delete
:
false
,
export
:
false
},
companyManagement
:
{
view
:
false
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
},
widgetManagement
:
{
view
:
false
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
},
dashboardManagement
:
{
view
:
false
,
create
:
false
,
edit
:
false
,
delete
:
false
,
export
:
false
}
};
}
/**
* ตรวจสอบสิทธิ์การเข้าถึงเมนู
*/
hasMenuPermission
(
menuKey
:
string
,
action
:
string
=
'view'
):
boolean
{
const
currentEmployee
=
this
.
getCurrentEmployee
();
if
(
!
currentEmployee
||
!
currentEmployee
.
menuPermissions
[
menuKey
])
{
return
false
;
}
const
permission
=
currentEmployee
.
menuPermissions
[
menuKey
];
return
permission
[
action
as
keyof
typeof
permission
]
===
true
;
}
/**
* ดึงสิทธิ์การเข้าถึงเมนูทั้งหมด
*/
getMenuPermissions
():
{
[
key
:
string
]:
any
}
|
null
{
const
currentEmployee
=
this
.
getCurrentEmployee
();
return
currentEmployee
?
currentEmployee
.
menuPermissions
:
null
;
}
/**
* ตรวจสอบว่าพนักงานมีสิทธิ์เข้าถึงโมดูลหรือไม่
*/
canAccessModule
(
moduleKey
:
string
):
boolean
{
return
this
.
hasMenuPermission
(
moduleKey
,
'view'
);
}
/**
* ดึงรายการโมดูลที่เข้าถึงได้
*/
getAccessibleModules
():
string
[]
{
const
permissions
=
this
.
getMenuPermissions
();
if
(
!
permissions
)
return
[];
return
Object
.
keys
(
permissions
).
filter
(
moduleKey
=>
this
.
canAccessModule
(
moduleKey
)
);
}
/**
* ออกจากระบบ
*/
logout
():
void
{
this
.
currentEmployeeSubject
.
next
(
null
);
this
.
currentJwtEmployeeSubject
.
next
(
null
);
localStorage
.
removeItem
(
'jwtToken'
);
sessionStorage
.
removeItem
(
'jwtToken'
);
}
/**
* ตรวจสอบสถานะการล็อกอิน
*/
isLoggedIn
():
boolean
{
return
this
.
currentEmployeeSubject
.
value
!==
null
;
}
/**
* ดึงข้อมูลพนักงานตามรหัสพนักงาน
*/
getEmployeeById
(
employeeId
:
string
):
Observable
<
Employee
|
null
>
{
return
this
.
employees$
.
pipe
(
map
(
employees
=>
employees
.
find
(
emp
=>
emp
.
employeeId
===
employeeId
)
||
null
)
);
}
/**
* ดึงข้อมูลพนักงานทั้งหมด
*/
getAllEmployees
():
Observable
<
Employee
[]
>
{
return
this
.
employees$
;
}
/**
* อัปเดตข้อมูลพนักงาน
*/
updateEmployee
(
employeeId
:
string
,
updatedData
:
Partial
<
Employee
>
):
Observable
<
boolean
>
{
return
this
.
employees$
.
pipe
(
map
(
employees
=>
{
const
index
=
employees
.
findIndex
(
emp
=>
emp
.
employeeId
===
employeeId
);
if
(
index
!==
-
1
)
{
employees
[
index
]
=
{
...
employees
[
index
],
...
updatedData
};
this
.
employeesSubject
.
next
([...
employees
]);
return
true
;
}
return
false
;
})
);
}
/**
* ตรวจสอบรหัสพนักงานที่ระบุ
*/
validateEmployeeIds
(
employeeIds
:
string
[]):
Observable
<
{
valid
:
string
[],
invalid
:
string
[]
}
>
{
return
this
.
employees$
.
pipe
(
map
(
employees
=>
{
const
validIds
:
string
[]
=
[];
const
invalidIds
:
string
[]
=
[];
employeeIds
.
forEach
(
id
=>
{
const
exists
=
employees
.
some
(
emp
=>
emp
.
employeeId
===
id
);
if
(
exists
)
{
validIds
.
push
(
id
);
}
else
{
invalidIds
.
push
(
id
);
}
});
return
{
valid
:
validIds
,
invalid
:
invalidIds
};
})
);
}
}
src/app/portal-manage/services/jwt.service.ts
0 → 100644
View file @
23e076c8
import
{
Injectable
}
from
'@angular/core'
;
import
{
JwtTokenPayload
,
DecodedJwtToken
,
EmployeeFromJwt
}
from
'../models/jwt-token.model'
;
@
Injectable
({
providedIn
:
'root'
})
export
class
JwtService
{
constructor
()
{
}
/**
* Decode JWT token โดยไม่ต้องใช้ library ภายนอก
*/
decodeToken
(
token
:
string
):
DecodedJwtToken
{
try
{
if
(
!
token
)
{
return
{
isValid
:
false
,
isExpired
:
false
,
payload
:
null
,
error
:
'Token is empty'
};
}
// แยก JWT token เป็น 3 ส่วน
const
parts
=
token
.
split
(
'.'
);
if
(
parts
.
length
!==
3
)
{
return
{
isValid
:
false
,
isExpired
:
false
,
payload
:
null
,
error
:
'Invalid token format'
};
}
// Decode header
const
header
=
this
.
base64UrlDecode
(
parts
[
0
]);
const
decodedHeader
=
JSON
.
parse
(
header
);
// Decode payload
const
payload
=
this
.
base64UrlDecode
(
parts
[
1
]);
const
decodedPayload
:
JwtTokenPayload
=
JSON
.
parse
(
payload
);
// ตรวจสอบว่า token หมดอายุหรือไม่
const
isExpired
=
this
.
isTokenExpired
(
decodedPayload
);
return
{
isValid
:
true
,
isExpired
:
isExpired
,
payload
:
decodedPayload
,
error
:
isExpired
?
'Token expired'
:
undefined
};
}
catch
(
error
)
{
return
{
isValid
:
false
,
isExpired
:
false
,
payload
:
null
,
error
:
`Token decode error:
${
error
}
`
};
}
}
/**
* Decode base64url string
*/
private
base64UrlDecode
(
str
:
string
):
string
{
// แปลง base64url เป็น base64
let
base64
=
str
.
replace
(
/-/g
,
'+'
).
replace
(
/_/g
,
'/'
);
// เพิ่ม padding ถ้าจำเป็น
while
(
base64
.
length
%
4
)
{
base64
+=
'='
;
}
// Decode base64
return
decodeURIComponent
(
atob
(
base64
)
.
split
(
''
)
.
map
(
c
=>
'%'
+
(
'00'
+
c
.
charCodeAt
(
0
).
toString
(
16
)).
slice
(
-
2
))
.
join
(
''
)
);
}
/**
* ตรวจสอบว่า token หมดอายุหรือไม่
*/
private
isTokenExpired
(
payload
:
JwtTokenPayload
):
boolean
{
// ตรวจสอบ exp claim ถ้ามี
if
(
'exp'
in
payload
)
{
const
exp
=
(
payload
as
any
).
exp
;
if
(
exp
)
{
const
currentTime
=
Math
.
floor
(
Date
.
now
()
/
1000
);
return
exp
<
currentTime
;
}
}
// ตรวจสอบ iat claim ถ้ามี
if
(
'iat'
in
payload
)
{
const
iat
=
(
payload
as
any
).
iat
;
if
(
iat
)
{
const
currentTime
=
Math
.
floor
(
Date
.
now
()
/
1000
);
// ถ้า token อายุเกิน 24 ชั่วโมงให้ถือว่า expired
const
maxAge
=
24
*
60
*
60
;
// 24 hours
return
(
currentTime
-
iat
)
>
maxAge
;
}
}
return
false
;
}
/**
* แปลง JWT payload เป็น Employee object
*/
convertToEmployee
(
payload
:
JwtTokenPayload
):
EmployeeFromJwt
{
return
{
employeeId
:
payload
.
employeeid
||
payload
.
uid
||
''
,
fullName
:
payload
.
fullname
||
''
,
username
:
payload
.
username
||
payload
.
user
||
''
,
email
:
`
${
payload
.
username
||
payload
.
user
||
''
}
@
${
payload
.
companyName
||
'company.com'
}
`
,
position
:
payload
.
emp_position
||
''
,
job
:
payload
.
job
||
''
,
department
:
this
.
extractDepartmentFromPosition
(
payload
.
emp_position
||
''
),
companyName
:
payload
.
companyName
||
''
,
companyId
:
payload
.
companyid
||
''
,
branch
:
payload
.
branch
||
''
,
workarea
:
payload
.
workarea
||
''
,
userLevel
:
payload
.
user_level
||
''
,
roles
:
payload
.
roles
||
[],
language
:
payload
.
lang
||
'tha'
,
isFirstLogin
:
payload
.
firstlogin
===
'true'
,
isAdUser
:
payload
.
ad
===
'true'
,
urlMyhr
:
payload
.
url_myhr
||
''
,
appName
:
payload
.
app_name
||
''
,
regionallty
:
payload
.
regionallty
||
''
,
tokenZeeme
:
payload
.
token_zeeme
||
''
,
zmUser
:
payload
.
zm_user
||
''
,
memberId
:
payload
.
memberid
||
''
};
}
/**
* แยกชื่อแผนกจากตำแหน่ง
*/
private
extractDepartmentFromPosition
(
position
:
string
):
string
{
if
(
!
position
)
return
''
;
// ตัวอย่าง: P-RD-2201 -> RD (Research & Development)
const
parts
=
position
.
split
(
'-'
);
if
(
parts
.
length
>=
2
)
{
const
deptCode
=
parts
[
1
];
const
deptMap
:
{
[
key
:
string
]:
string
}
=
{
'RD'
:
'ฝ่ายวิจัยและพัฒนา'
,
'IT'
:
'ฝ่ายเทคโนโลยีสารสนเทศ'
,
'HR'
:
'ฝ่ายทรัพยากรบุคคล'
,
'EX'
:
'ฝ่ายบริหาร'
,
'AC'
:
'ฝ่ายบัญชี'
,
'MK'
:
'ฝ่ายการตลาด'
,
'SL'
:
'ฝ่ายขาย'
,
'OP'
:
'ฝ่ายปฏิบัติการ'
};
return
deptMap
[
deptCode
]
||
deptCode
;
}
return
position
;
}
/**
* ตรวจสอบว่า token ถูกต้องและไม่หมดอายุ
*/
isTokenValid
(
token
:
string
):
boolean
{
const
decoded
=
this
.
decodeToken
(
token
);
return
decoded
.
isValid
&&
!
decoded
.
isExpired
;
}
/**
* ดึงข้อมูลพนักงานจาก token
*/
getEmployeeFromToken
(
token
:
string
):
EmployeeFromJwt
|
null
{
const
decoded
=
this
.
decodeToken
(
token
);
if
(
decoded
.
isValid
&&
!
decoded
.
isExpired
&&
decoded
.
payload
)
{
return
this
.
convertToEmployee
(
decoded
.
payload
);
}
return
null
;
}
/**
* ตรวจสอบสิทธิ์จาก roles ใน token
*/
hasRole
(
token
:
string
,
role
:
string
):
boolean
{
const
decoded
=
this
.
decodeToken
(
token
);
if
(
decoded
.
isValid
&&
decoded
.
payload
)
{
return
decoded
.
payload
.
roles
.
includes
(
role
);
}
return
false
;
}
/**
* ตรวจสอบ user level
*/
getUserLevel
(
token
:
string
):
string
{
const
decoded
=
this
.
decodeToken
(
token
);
if
(
decoded
.
isValid
&&
decoded
.
payload
)
{
return
decoded
.
payload
.
user_level
||
''
;
}
return
''
;
}
/**
* ตรวจสอบว่าเป็น admin หรือไม่
*/
isAdmin
(
token
:
string
):
boolean
{
const
userLevel
=
this
.
getUserLevel
(
token
);
return
userLevel
.
includes
(
'Admin'
)
||
userLevel
.
includes
(
'Manager'
)
||
userLevel
.
includes
(
'Executive'
);
}
/**
* ตรวจสอบว่าเป็น employee หรือไม่
*/
isEmployee
(
token
:
string
):
boolean
{
const
userLevel
=
this
.
getUserLevel
(
token
);
return
userLevel
.
includes
(
'Emp-User'
)
||
userLevel
.
includes
(
'Employee'
);
}
}
src/assets/data/employeelist.json
View file @
23e076c8
This source diff could not be displayed because it is too large. You can
view the blob
instead.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment