diff --git a/front-update.py b/front-update.py index 97eba8b..c8239e2 100644 --- a/front-update.py +++ b/front-update.py @@ -23,7 +23,7 @@ logging.basicConfig(level=logging.INFO) log = logging.getLogger("updater") log.setLevel(logging.INFO) -API_URL="http://host.docker.internal:8181" +API_URL="http://192.168.1.26:8181" Config_File="/conf/server-conf.json" Version_File="/usr/share/nginx/html/version.json" # Example usage diff --git a/nginx.conf b/nginx.conf index 418d1e1..e5519ef 100644 --- a/nginx.conf +++ b/nginx.conf @@ -18,7 +18,7 @@ server { try_files $uri $uri/ /index.html =404; } location /api { - proxy_pass http://host.docker.internal:8181; + proxy_pass http://192.168.1.26:8181; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $realip_remote_addr; diff --git a/package-lock.json b/package-lock.json index 2ad6060..86e98ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,13 @@ { - "name": "coreui-free-angular-admin-template", - "version": "4.5.27", + "name": "MikroWizard", + "version": "1.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "coreui-free-angular-admin-template", - "version": "4.5.27", - "license": "MIT", + "name": "MikroWizard", + "version": "1.0.1", + "license": "AGPL", "dependencies": { "@angular/animations": "^17.3.5", "@angular/cdk": "^16.2.9", @@ -20,6 +20,8 @@ "@angular/platform-browser": "^17.3.5", "@angular/platform-browser-dynamic": "^17.3.5", "@angular/router": "^17.3.5", + "@azure/msal-angular": "^4.0.12", + "@azure/msal-browser": "^4.12.0", "@coreui/angular": "~4.5.27", "@coreui/angular-chartjs": "~4.5.27", "@coreui/chartjs": "^3.1.2", @@ -28,25 +30,27 @@ "@coreui/icons-angular": "~4.5.27", "@coreui/utils": "^2.0.2", "@easyfonts/font-awesome-v6": "^6.0.6", - "@fortawesome/angular-fontawesome": "^0.13.0", - "@fortawesome/fontawesome-svg-core": "^6.4.2", - "@fortawesome/free-brands-svg-icons": "^6.4.2", - "@fortawesome/free-regular-svg-icons": "^6.4.2", - "@fortawesome/free-solid-svg-icons": "^6.4.2", + "@fortawesome/angular-fontawesome": "^0.15.0", "@generic-ui/fabric": "^0.19.0", "@generic-ui/hermes": "^0.19.0", "@generic-ui/ngx-grid": "^0.19.0", + "apple-signin-auth": "^2.0.0", "chart.js": "^3.9.1", "date-fns": "^3.6.0", "date-fns-jalali": "^3.6.0-0", "date-fns-tz": "^3.1.3", + "diff-match-patch-ts": "^0.6.0", "font-awesome": "^4.7.0", "install": "^0.13.0", + "jwt-decode": "^4.0.0", "lodash-es": "^4.17.21", "mat-progress-buttons": "^9.3.1", "ngx-cron-editor": "^0.8.1", "ngx-date-fns": "^11.0.0", + "ngx-diff": "^9.0.0", + "ngx-highlight-js": "^18.0.0", "ngx-highlightjs": "^12.0.0", + "ngx-infinite-scroll": "^18.0.0", "ngx-mat-select-search": "^7.0.6", "ngx-material-date-fns-adapter": "^18.0.0", "ngx-scrollbar": "^13.0.3", @@ -754,6 +758,37 @@ "rxjs": "^6.5.3 || ^7.4.0" } }, + "node_modules/@azure/msal-angular": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/@azure/msal-angular/-/msal-angular-4.0.12.tgz", + "integrity": "sha512-J6wV84d0hcKjiH/VSCMDcigYiJ9bcrMuM3uFrfEATVn7ANziKq+skp9buwcr0s6e60Z3R7Juxb8wOnI1HemXGw==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@azure/msal-browser": "^4.12.0", + "rxjs": "^7.0.0" + } + }, + "node_modules/@azure/msal-browser": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-4.12.0.tgz", + "integrity": "sha512-WD1lmVWchg7wn1mI7Tr4v7QPyTwK+8Nuyje3jRpOFENLRLEBsdK8VVdTw3C+TypZmYn4cOAdj3zREnuFXgvfIA==", + "dependencies": { + "@azure/msal-common": "15.6.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-common": { + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-15.6.0.tgz", + "integrity": "sha512-EotmBz42apYGjqiIV9rDUdptaMptpTn4TdGf3JfjLvFvinSe9BJ6ywU92K9ky+t/b0ghbeTSe9RfqlgLh8f2jA==", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.24.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", @@ -2972,15 +3007,15 @@ } }, "node_modules/@fortawesome/angular-fontawesome": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@fortawesome/angular-fontawesome/-/angular-fontawesome-0.13.0.tgz", - "integrity": "sha512-gzSPRdveOXNO7NIiMgTyB46aiHG0i98KinnAEqHXi8qzraM/kCcHn/0y3f4MhemX6kftwsFli0IU8RyHmtXlSQ==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@fortawesome/angular-fontawesome/-/angular-fontawesome-0.15.0.tgz", + "integrity": "sha512-oxmJDYGNSym5ycFR0LX4ZOPAU+wWmMAznYpkm5DNAtWWkhMLcrZl15eZQmVIEE+qruQ7JiVrg3tpo8bEkFlDgw==", "dependencies": { - "tslib": "^2.4.1" + "@fortawesome/fontawesome-svg-core": "^6.5.2", + "tslib": "^2.6.2" }, "peerDependencies": { - "@angular/core": "^16.0.0", - "@fortawesome/fontawesome-svg-core": "~1.2.27 || ~1.3.0-beta2 || ^6.1.0" + "@angular/core": "^18.0.0" } }, "node_modules/@fortawesome/fontawesome-common-types": { @@ -3004,42 +3039,6 @@ "node": ">=6" } }, - "node_modules/@fortawesome/free-brands-svg-icons": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.5.2.tgz", - "integrity": "sha512-zi5FNYdmKLnEc0jc0uuHH17kz/hfYTg4Uei0wMGzcoCL/4d3WM3u1VMc0iGGa31HuhV5i7ZK8ZlTCQrHqRHSGQ==", - "hasInstallScript": true, - "dependencies": { - "@fortawesome/fontawesome-common-types": "6.5.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/free-regular-svg-icons": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.5.2.tgz", - "integrity": "sha512-iabw/f5f8Uy2nTRtJ13XZTS1O5+t+anvlamJ3zJGLEVE2pKsAWhPv2lq01uQlfgCX7VaveT3EVs515cCN9jRbw==", - "hasInstallScript": true, - "dependencies": { - "@fortawesome/fontawesome-common-types": "6.5.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/free-solid-svg-icons": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.2.tgz", - "integrity": "sha512-QWFZYXFE7O1Gr1dTIp+D6UcFUF0qElOnZptpi7PBUMylJh+vFmIedVe1Ir6RM1t2tEQLLSV1k7bR4o92M+uqlw==", - "hasInstallScript": true, - "dependencies": { - "@fortawesome/fontawesome-common-types": "6.5.2" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/@generic-ui/fabric": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@generic-ui/fabric/-/fabric-0.19.1.tgz", @@ -5390,6 +5389,19 @@ "node": ">= 8" } }, + "node_modules/apple-signin-auth": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/apple-signin-auth/-/apple-signin-auth-2.0.0.tgz", + "integrity": "sha512-/O5gvAby7OU2K7baYQCzY0e0tCiHzhFkzt9L2v3bMd2I2w0ckCZ/4hdVUOrbolRGMppME+Zo8TAKPVru8aYnzg==", + "license": "MIT", + "dependencies": { + "jsonwebtoken": "^9.0.0", + "node-rsa": "^1.1.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -5405,6 +5417,15 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "dev": true }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, "node_modules/autoprefixer": { "version": "10.4.18", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.18.tgz", @@ -5770,6 +5791,12 @@ "ieee754": "^1.1.13" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -6735,6 +6762,11 @@ "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", "dev": true }, + "node_modules/diff-match-patch-ts": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/diff-match-patch-ts/-/diff-match-patch-ts-0.6.0.tgz", + "integrity": "sha512-U0uPIJ+wJqgaBoVw2MFSFpGIk7q3mJJ+/sehbxDZFv4Gx6a1GOmrsSLmxVDDrGtRL4Q9de084aa5lVpCHn+eUw==" + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -6832,6 +6864,15 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -8824,6 +8865,58 @@ "node >= 0.2.0" ] }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/karma": { "version": "6.4.3", "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.3.tgz", @@ -9178,6 +9271,48 @@ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -9728,8 +9863,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/multicast-dns": { "version": "7.2.5", @@ -9757,6 +9891,7 @@ "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, "funding": [ { "type": "github", @@ -9846,6 +9981,28 @@ "date-fns": ">=3" } }, + "node_modules/ngx-diff": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/ngx-diff/-/ngx-diff-9.1.0.tgz", + "integrity": "sha512-hD54tOsQLNU6ltbS9gV4wDrnZrMfxjF2AlxnUrp+/n2+T/nLK2bQMiiQT2IEe6CXZ1dl/doKD1qGoQnX0mSoIw==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": ">=18.0.0", + "@angular/core": ">=18.0.0", + "diff-match-patch-ts": ">=0.5.0" + } + }, + "node_modules/ngx-highlight-js": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/ngx-highlight-js/-/ngx-highlight-js-18.0.0.tgz", + "integrity": "sha512-r/LSijb5Ju95ZGm89+4e905kFWkDt1XdGCg2prR1wleTE77uROscjZMht0D40WSRbxmOg+J2zw9OOZvsWSLeeg==", + "dependencies": { + "highlight.js": "^11.9.0", + "tslib": "^2.3.0" + } + }, "node_modules/ngx-highlightjs": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/ngx-highlightjs/-/ngx-highlightjs-12.0.0.tgz", @@ -9859,6 +10016,18 @@ "@angular/core": ">=17.0.0" } }, + "node_modules/ngx-infinite-scroll": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/ngx-infinite-scroll/-/ngx-infinite-scroll-18.0.0.tgz", + "integrity": "sha512-D183TDwpsd9Zl56UmItsl3RzHdN25srAISfg6lc3A8mEKkEgOq0s7ZzRAYcx8DHsAkMgtZqjIPEvMifD3DOB/g==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": ">=18.0.0 <19.0.0", + "@angular/core": ">=18.0.0 <19.0.0" + } + }, "node_modules/ngx-mat-select-search": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/ngx-mat-select-search/-/ngx-mat-select-search-7.0.6.tgz", @@ -10030,6 +10199,15 @@ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, + "node_modules/node-rsa": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/node-rsa/-/node-rsa-1.1.1.tgz", + "integrity": "sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw==", + "license": "MIT", + "dependencies": { + "asn1": "^0.2.4" + } + }, "node_modules/nopt": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", @@ -10663,7 +10841,8 @@ "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true }, "node_modules/picomatch": { "version": "2.3.1", @@ -10715,6 +10894,7 @@ "version": "8.4.35", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "dev": true, "funding": [ { "type": "opencollective", @@ -11446,7 +11626,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -11465,8 +11644,7 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/safevalues": { "version": "0.3.4", @@ -11579,7 +11757,6 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -11594,7 +11771,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -11605,8 +11781,7 @@ "node_modules/semver/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/send": { "version": "0.18.0", @@ -11997,6 +12172,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -14207,6 +14383,27 @@ "tslib": "^2.3.0" } }, + "@azure/msal-angular": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/@azure/msal-angular/-/msal-angular-4.0.12.tgz", + "integrity": "sha512-J6wV84d0hcKjiH/VSCMDcigYiJ9bcrMuM3uFrfEATVn7ANziKq+skp9buwcr0s6e60Z3R7Juxb8wOnI1HemXGw==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@azure/msal-browser": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-4.12.0.tgz", + "integrity": "sha512-WD1lmVWchg7wn1mI7Tr4v7QPyTwK+8Nuyje3jRpOFENLRLEBsdK8VVdTw3C+TypZmYn4cOAdj3zREnuFXgvfIA==", + "requires": { + "@azure/msal-common": "15.6.0" + } + }, + "@azure/msal-common": { + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-15.6.0.tgz", + "integrity": "sha512-EotmBz42apYGjqiIV9rDUdptaMptpTn4TdGf3JfjLvFvinSe9BJ6ywU92K9ky+t/b0ghbeTSe9RfqlgLh8f2jA==" + }, "@babel/code-frame": { "version": "7.24.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", @@ -14580,8 +14777,7 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, - "requires": {} + "dev": true }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", @@ -15659,11 +15855,12 @@ "optional": true }, "@fortawesome/angular-fontawesome": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@fortawesome/angular-fontawesome/-/angular-fontawesome-0.13.0.tgz", - "integrity": "sha512-gzSPRdveOXNO7NIiMgTyB46aiHG0i98KinnAEqHXi8qzraM/kCcHn/0y3f4MhemX6kftwsFli0IU8RyHmtXlSQ==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@fortawesome/angular-fontawesome/-/angular-fontawesome-0.15.0.tgz", + "integrity": "sha512-oxmJDYGNSym5ycFR0LX4ZOPAU+wWmMAznYpkm5DNAtWWkhMLcrZl15eZQmVIEE+qruQ7JiVrg3tpo8bEkFlDgw==", "requires": { - "tslib": "^2.4.1" + "@fortawesome/fontawesome-svg-core": "^6.5.2", + "tslib": "^2.6.2" } }, "@fortawesome/fontawesome-common-types": { @@ -15679,30 +15876,6 @@ "@fortawesome/fontawesome-common-types": "6.5.2" } }, - "@fortawesome/free-brands-svg-icons": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.5.2.tgz", - "integrity": "sha512-zi5FNYdmKLnEc0jc0uuHH17kz/hfYTg4Uei0wMGzcoCL/4d3WM3u1VMc0iGGa31HuhV5i7ZK8ZlTCQrHqRHSGQ==", - "requires": { - "@fortawesome/fontawesome-common-types": "6.5.2" - } - }, - "@fortawesome/free-regular-svg-icons": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.5.2.tgz", - "integrity": "sha512-iabw/f5f8Uy2nTRtJ13XZTS1O5+t+anvlamJ3zJGLEVE2pKsAWhPv2lq01uQlfgCX7VaveT3EVs515cCN9jRbw==", - "requires": { - "@fortawesome/fontawesome-common-types": "6.5.2" - } - }, - "@fortawesome/free-solid-svg-icons": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.2.tgz", - "integrity": "sha512-QWFZYXFE7O1Gr1dTIp+D6UcFUF0qElOnZptpi7PBUMylJh+vFmIedVe1Ir6RM1t2tEQLLSV1k7bR4o92M+uqlw==", - "requires": { - "@fortawesome/fontawesome-common-types": "6.5.2" - } - }, "@generic-ui/fabric": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@generic-ui/fabric/-/fabric-0.19.1.tgz", @@ -16676,8 +16849,7 @@ "version": "17.3.5", "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.5.tgz", "integrity": "sha512-0heI0yHUckdGI8uywu/wkp24KR/tdYMKYJOaYIU+9JydyN1zJRpbR7x0thddl7+k/zu2ZGbfFdv1779Ecw/xdA==", - "dev": true, - "requires": {} + "dev": true }, "@nodelib/fs.scandir": { "version": "2.1.5", @@ -17380,8 +17552,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.1.0.tgz", "integrity": "sha512-wO4Dk/rm8u7RNhOf95ZzcEmC9rYOncYgvq4z3duaJrCgjN8BxAnDVyndanfcJZ0O6XZzHz6Q0hTimxTg8Y9g/A==", - "dev": true, - "requires": {} + "dev": true }, "@webassemblyjs/ast": { "version": "1.12.1", @@ -17573,8 +17744,7 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "requires": {} + "dev": true }, "adjust-sourcemap-loader": { "version": "4.0.0", @@ -17694,6 +17864,15 @@ "picomatch": "^2.0.4" } }, + "apple-signin-auth": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/apple-signin-auth/-/apple-signin-auth-2.0.0.tgz", + "integrity": "sha512-/O5gvAby7OU2K7baYQCzY0e0tCiHzhFkzt9L2v3bMd2I2w0ckCZ/4hdVUOrbolRGMppME+Zo8TAKPVru8aYnzg==", + "requires": { + "jsonwebtoken": "^9.0.0", + "node-rsa": "^1.1.1" + } + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -17709,6 +17888,14 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "dev": true }, + "asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, "autoprefixer": { "version": "10.4.18", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.18.tgz", @@ -17961,6 +18148,11 @@ "ieee754": "^1.1.13" } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -18596,8 +18788,7 @@ "date-fns-tz": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-3.1.3.tgz", - "integrity": "sha512-ZfbMu+nbzW0mEzC8VZrLiSWvUIaI3aRHeq33mTe7Y38UctKukgqPR4nTDwcwS4d64Gf8GghnVsroBuMY3eiTeA==", - "requires": {} + "integrity": "sha512-ZfbMu+nbzW0mEzC8VZrLiSWvUIaI3aRHeq33mTe7Y38UctKukgqPR4nTDwcwS4d64Gf8GghnVsroBuMY3eiTeA==" }, "date-format": { "version": "4.0.14", @@ -18673,6 +18864,11 @@ "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", "dev": true }, + "diff-match-patch-ts": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/diff-match-patch-ts/-/diff-match-patch-ts-0.6.0.tgz", + "integrity": "sha512-U0uPIJ+wJqgaBoVw2MFSFpGIk7q3mJJ+/sehbxDZFv4Gx6a1GOmrsSLmxVDDrGtRL4Q9de084aa5lVpCHn+eUw==" + }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -18746,6 +18942,14 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -18826,8 +19030,7 @@ "version": "8.11.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "dev": true, - "requires": {} + "dev": true } } }, @@ -19677,8 +19880,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "requires": {} + "dev": true }, "ieee754": { "version": "1.2.1", @@ -20226,6 +20428,47 @@ "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", "dev": true }, + "jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + } + }, + "jwa": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "requires": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==" + }, "karma": { "version": "6.4.3", "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.3.tgz", @@ -20374,8 +20617,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-2.1.0.tgz", "integrity": "sha512-sPQE1+nlsn6Hwb5t+HHwyy0A1FNCVKuL1192b+XNauMYWThz2kweiBVW1DqloRpVvZIJkIoHVB7XRpK78n1xbQ==", - "dev": true, - "requires": {} + "dev": true }, "karma-source-map-support": { "version": "1.4.0", @@ -20497,6 +20739,41 @@ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -20917,8 +21194,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "multicast-dns": { "version": "7.2.5", @@ -20939,7 +21215,8 @@ "nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==" + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true }, "needle": { "version": "3.3.1", @@ -20992,6 +21269,23 @@ "tslib": "^2.3.0" } }, + "ngx-diff": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/ngx-diff/-/ngx-diff-9.1.0.tgz", + "integrity": "sha512-hD54tOsQLNU6ltbS9gV4wDrnZrMfxjF2AlxnUrp+/n2+T/nLK2bQMiiQT2IEe6CXZ1dl/doKD1qGoQnX0mSoIw==", + "requires": { + "tslib": "^2.0.0" + } + }, + "ngx-highlight-js": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/ngx-highlight-js/-/ngx-highlight-js-18.0.0.tgz", + "integrity": "sha512-r/LSijb5Ju95ZGm89+4e905kFWkDt1XdGCg2prR1wleTE77uROscjZMht0D40WSRbxmOg+J2zw9OOZvsWSLeeg==", + "requires": { + "highlight.js": "^11.9.0", + "tslib": "^2.3.0" + } + }, "ngx-highlightjs": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/ngx-highlightjs/-/ngx-highlightjs-12.0.0.tgz", @@ -21001,6 +21295,14 @@ "tslib": "^2.3.0" } }, + "ngx-infinite-scroll": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/ngx-infinite-scroll/-/ngx-infinite-scroll-18.0.0.tgz", + "integrity": "sha512-D183TDwpsd9Zl56UmItsl3RzHdN25srAISfg6lc3A8mEKkEgOq0s7ZzRAYcx8DHsAkMgtZqjIPEvMifD3DOB/g==", + "requires": { + "tslib": "^2.3.0" + } + }, "ngx-mat-select-search": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/ngx-mat-select-search/-/ngx-mat-select-search-7.0.6.tgz", @@ -21121,6 +21423,14 @@ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, + "node-rsa": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/node-rsa/-/node-rsa-1.1.1.tgz", + "integrity": "sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw==", + "requires": { + "asn1": "^0.2.4" + } + }, "nopt": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", @@ -21585,7 +21895,8 @@ "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true }, "picomatch": { "version": "2.3.1", @@ -21622,6 +21933,7 @@ "version": "8.4.35", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "dev": true, "requires": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", @@ -21657,8 +21969,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, - "requires": {} + "dev": true }, "postcss-modules-local-by-default": { "version": "4.0.5", @@ -22137,14 +22448,12 @@ "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "safevalues": { "version": "0.3.4", @@ -22210,7 +22519,6 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, "requires": { "lru-cache": "^6.0.0" }, @@ -22219,7 +22527,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } @@ -22227,8 +22534,7 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -22490,8 +22796,7 @@ "version": "8.11.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "dev": true, - "requires": {} + "dev": true } } }, @@ -22546,7 +22851,8 @@ "source-map-js": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==" + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true }, "source-map-loader": { "version": "5.0.0", @@ -22849,8 +23155,7 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} + "dev": true }, "json-schema-traverse": { "version": "0.4.1", @@ -23399,8 +23704,7 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} + "dev": true }, "json-schema-traverse": { "version": "0.4.1", @@ -23637,8 +23941,7 @@ "version": "8.16.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, - "requires": {} + "dev": true }, "y18n": { "version": "5.0.8", diff --git a/package.json b/package.json index a390bf6..88e8413 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ }, "scripts": { "ng": "ng", - "start": "ng serve --proxy-config proxy.conf.json --host 0.0.0.0", + "start": "ng serve --proxy-config proxy.conf.json", "startnp": "ng serve --proxy-config=./proxy.conf.ts --host 0.0.0.0", "build": "ng build", "watch": "ng build --watch --configuration development", @@ -30,6 +30,8 @@ "@angular/platform-browser": "^17.3.5", "@angular/platform-browser-dynamic": "^17.3.5", "@angular/router": "^17.3.5", + "@azure/msal-angular": "^4.0.12", + "@azure/msal-browser": "^4.12.0", "@coreui/angular": "~4.5.27", "@coreui/angular-chartjs": "~4.5.27", "@coreui/chartjs": "^3.1.2", @@ -42,6 +44,7 @@ "@generic-ui/fabric": "^0.19.0", "@generic-ui/hermes": "^0.19.0", "@generic-ui/ngx-grid": "^0.19.0", + "apple-signin-auth": "^2.0.0", "chart.js": "^3.9.1", "date-fns": "^3.6.0", "date-fns-jalali": "^3.6.0-0", @@ -49,6 +52,7 @@ "diff-match-patch-ts": "^0.6.0", "font-awesome": "^4.7.0", "install": "^0.13.0", + "jwt-decode": "^4.0.0", "lodash-es": "^4.17.21", "mat-progress-buttons": "^9.3.1", "ngx-cron-editor": "^0.8.1", diff --git a/proxy.conf.json b/proxy.conf.json index b6b8647..38adad1 100644 --- a/proxy.conf.json +++ b/proxy.conf.json @@ -1,8 +1,9 @@ { "/api": { - "target": "http://172.17.0.1:8181/", + "target": "http://localhost:3000", "secure": false, "changeOrigin": true, + "logLevel": "debug", "pathRewrite": {"^/api" : ""} } } \ No newline at end of file diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 3c4186a..c41f77c 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -5,6 +5,7 @@ import { DefaultLayoutComponent } from './containers'; import { Page404Component } from './views/pages/page404/page404.component'; import { Page500Component } from './views/pages/page500/page500.component'; import { LoginComponent } from './views/pages/login/login.component'; +import { SignupComponent } from './views/pages/signup/signup.component'; const routes: Routes = [ { @@ -132,6 +133,13 @@ const routes: Routes = [ title: 'Login Page' } }, + { + path: 'signup', + component: SignupComponent, + data: { + title: 'Signup Page' + } + }, {path: '**', redirectTo: 'dashboard'} ]; diff --git a/src/app/app.module.ts b/src/app/app.module.ts index bb74798..dfebcf2 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,8 +1,12 @@ -import { NgModule ,APP_INITIALIZER} from '@angular/core'; +import { NgModule, APP_INITIALIZER } from '@angular/core'; import { HashLocationStrategy, LocationStrategy, PathLocationStrategy } from '@angular/common'; import { BrowserModule, Title } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { ReactiveFormsModule,FormsModule } from '@angular/forms'; +import { ReactiveFormsModule, FormsModule } from '@angular/forms'; +import { MsalModule, MsalService, MSAL_INSTANCE, MsalGuard, MsalInterceptor, MsalGuardConfiguration, MsalInterceptorConfiguration } from '@azure/msal-angular'; +import { IPublicClientApplication, PublicClientApplication, InteractionType } from '@azure/msal-browser'; +import { msalConfig } from './auth/msal-config'; +import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { NgScrollbarModule } from 'ngx-scrollbar'; import { HttpClientModule } from '@angular/common/http'; @@ -54,12 +58,36 @@ const APP_CONTAINERS = [ export function loginStatusProviderFactory(provider: loginChecker) { return () => provider.load(); } + +export function MSALInstanceFactory(): IPublicClientApplication { + const msalInstance = new PublicClientApplication(msalConfig); + msalInstance.initialize().catch(error => { + console.error('MSAL initialization failed:', error); + }); + return msalInstance; +} + +const guardConfig: MsalGuardConfiguration = { + interactionType: InteractionType.Popup, + authRequest: { + scopes: ['User.Read', 'profile', 'email', 'openid'] + } +}; + +const interceptorConfig: MsalInterceptorConfiguration = { + interactionType: InteractionType.Popup, + protectedResourceMap: new Map([ + ['https://graph.microsoft.com/v1.0/me', ['User.Read']] + ]) +}; + @NgModule({ declarations: [AppComponent, ...APP_CONTAINERS], imports: [ BrowserModule, BrowserAnimationsModule, AppRoutingModule, + MsalModule.forRoot(MSALInstanceFactory(), guardConfig, interceptorConfig), AvatarModule, BreadcrumbModule, FooterModule, @@ -94,6 +122,17 @@ export function loginStatusProviderFactory(provider: loginChecker) { provide: LocationStrategy, useClass: HashLocationStrategy }, + { + provide: MSAL_INSTANCE, + useFactory: MSALInstanceFactory + }, + { + provide: HTTP_INTERCEPTORS, + useClass: MsalInterceptor, + multi: true + }, + MsalService, + MsalGuard, MikroWizardProvider, dataProvider, loginChecker, diff --git a/src/app/auth/apple-config.ts b/src/app/auth/apple-config.ts new file mode 100644 index 0000000..e7b7493 --- /dev/null +++ b/src/app/auth/apple-config.ts @@ -0,0 +1,7 @@ +export const appleConfig = { + clientId: 'ca.circleprotect.cnode', // Your Apple Service ID + redirectURI: "https://30c8-2402-a00-162-359c-1499-994a-62e-7eda.ngrok-free.app/auth/apple/callback", + scope: 'name email', + state: 'apple-signin', + usePopup: true +}; \ No newline at end of file diff --git a/src/app/auth/msal-config.ts b/src/app/auth/msal-config.ts new file mode 100644 index 0000000..4d4eeb6 --- /dev/null +++ b/src/app/auth/msal-config.ts @@ -0,0 +1,19 @@ +import { Configuration, PopupRequest } from "@azure/msal-browser"; + +// MSAL configuration +export const msalConfig: Configuration = { + auth: { + clientId: "fdbc76a1-2553-4efb-871f-56afdd3dd894", // Replace with your Azure AD application client ID + authority: "https://login.microsoftonline.com/common", + redirectUri: window.location.origin, + }, + cache: { + cacheLocation: "sessionStorage", + storeAuthStateInCookie: false, + } +}; + +// Add here scopes for id token to be used at MS Identity Platform endpoints. +export const loginRequest: PopupRequest = { + scopes: ["User.Read", "profile", "email", "openid"] +}; \ No newline at end of file diff --git a/src/app/icons/icon-subset.ts b/src/app/icons/icon-subset.ts index 5407905..167fb98 100644 --- a/src/app/icons/icon-subset.ts +++ b/src/app/icons/icon-subset.ts @@ -89,7 +89,8 @@ import { cilUserFemale, cilUserFollow, cilUserUnfollow, - cilExitToApp + cilExitToApp, + cilBuilding } from '@coreui/icons'; export const iconSubset = { @@ -183,7 +184,8 @@ export const iconSubset = { cilUserFemale, cilUserFollow, cilUserUnfollow, - cilExitToApp + cilExitToApp, + cilBuilding }; export enum IconSubset { @@ -277,5 +279,6 @@ export enum IconSubset { cilUserFemale = 'cilUserFemale', cilUserFollow = 'cilUserFollow', cilUserUnfollow = 'cilUserUnfollow', - cilExitToApp = 'cilExitToApp' + cilExitToApp = 'cilExitToApp', + cilBuilding = 'cilBuilding' } diff --git a/src/app/providers/login_checker.ts b/src/app/providers/login_checker.ts index 36becec..d3e8b63 100644 --- a/src/app/providers/login_checker.ts +++ b/src/app/providers/login_checker.ts @@ -1,28 +1,47 @@ import { Injectable } from '@angular/core'; +import { Router, NavigationEnd } from '@angular/router'; import { dataProvider } from './mikrowizard/data'; @Injectable() export class loginChecker { - private logged_in: boolean = false; - private pinging: boolean = false; + private is_logged_in: boolean = false; + private public_routes = ['/login', '/signup']; - constructor(private data_provider: dataProvider) { + constructor( + private router: Router, + private data_provider: dataProvider + ) { + this.router.events.subscribe((event) => { + if (event instanceof NavigationEnd) { + const currentRoute = event.url; + if (!this.is_logged_in && !this.public_routes.includes(currentRoute)) { + this.router.navigate(['/login']); + } + } + }); } - public isLoggedIn(): boolean { - return this.logged_in; + + isLoggedIn() { + return this.is_logged_in; } + + setStatus(status: boolean) { + this.is_logged_in = status; + } + load() { - var _self = this; - return this.data_provider.isLoggedIn().then(result => { - _self.logged_in = result; - }).catch(err => { - _self.logged_in = false; - }) - } - setStatus(status: boolean): void { - this.logged_in = status; - } - setPinging(ping: boolean): void { - this.pinging = ping; + return new Promise((resolve, reject) => { + this.data_provider.getSessionInfo().then(res => { + if ('uid' in res && res['uid']) { + this.is_logged_in = true; + } else { + this.is_logged_in = false; + } + resolve(true); + }).catch(err => { + this.is_logged_in = false; + resolve(true); + }); + }); } } \ No newline at end of file diff --git a/src/app/providers/mikrowizard/data.ts b/src/app/providers/mikrowizard/data.ts index ba6c8a4..f1d51f5 100644 --- a/src/app/providers/mikrowizard/data.ts +++ b/src/app/providers/mikrowizard/data.ts @@ -1,5 +1,5 @@ - import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; // import { MikroWizardrpcProvider } from '../MikroWizardrpc/MikroWizardrpc'; import { MikroWizardProvider } from './provider'; @@ -10,13 +10,15 @@ import { User } from './user'; export class dataProvider { // public serverUrl: string = "/api"; - public serverUrl: string = ""; + public serverUrl: string = "http://localhost:3000"; private db: string = "NothingImportant"; + private apiUrl: string = "/api"; constructor( // private http: HTTP, // public MikroWizardRPC: MikroWizardrpcProvider, public MikroWizardRPC: MikroWizardProvider, + private http: HttpClient ) { this.MikroWizardRPC.init({ MikroWizard_server: this.serverUrl @@ -628,4 +630,33 @@ export class dataProvider { getFullUrl(url: any) { return this.serverUrl + url; } + + signup(username: string, organization: string, email: string, password: string) { + var data = { + 'username': username, + 'organization': organization, + 'email': email, + 'password': password + } + return this.MikroWizardRPC.sendJsonRequest("/api/signup", data); + } + + async loginWithOffice365(tokenClaims: any): Promise { + try { + const data = { + tokenClaims: tokenClaims + }; + return this.MikroWizardRPC.sendJsonRequest("/api/auth/office365", data); + } catch (error) { + throw error; + } + } + + async singSignonLoginForUser(data: any): Promise { + try { + return this.MikroWizardRPC.sendJsonRequest("/api/single-signon/user/create", data); + } catch (error) { + throw error; + } + } } diff --git a/src/app/providers/mikrowizard/provider.ts b/src/app/providers/mikrowizard/provider.ts index ac7deb4..6542332 100644 --- a/src/app/providers/mikrowizard/provider.ts +++ b/src/app/providers/mikrowizard/provider.ts @@ -124,7 +124,7 @@ export class MikroWizardProvider { let headers = { "Content-Type": "application/json", }; - return this.http.post(url, params, + return this.http.post(this.MikroWizard_server + url, params, {headers:this.headers,withCredentials:true} ).toPromise() .then(this.handleRequestErrors) @@ -145,7 +145,7 @@ export class MikroWizardProvider { let headers = { "Content-Type": "application/x-www-form-urlencoded", }; - return this.http.get( url, + return this.http.get( this.MikroWizard_server + url, { responseType: 'json' } ).toPromise() } diff --git a/src/app/views/dashboard/dashboard.component.html b/src/app/views/dashboard/dashboard.component.html index af6b2e9..2556092 100644 --- a/src/app/views/dashboard/dashboard.component.html +++ b/src/app/views/dashboard/dashboard.component.html @@ -1,224 +1,260 @@ - - - - Past 24 Hour Statics - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +
+
+

Dashboard

+
+ + +
+
+
+ + +
+ + +
+
+ + + + Past 24 Hour Statistics + + + + - -
-
Total users
-
{{stats['Users']}}
-
+ + + + + + - -
-
Total Devices
-
{{stats['Devices']}}
-
+ + + + + + - -
-
Total Events
-
{{stats['Events']}}
-
+ + + + + + - -
-
Total Auth Logs
-
{{stats['Auth']}}
-
+ + + + + + - -
-
Total Acc Logs
-
{{stats['Acc']}}
-
+ + + + + +
- - -
- - + + +
+
- - - - -

Total Devices Traffic

-
- -
- - - + +
+
+ + + +

Total Devices Traffic

+ +
+ + + + + + + + + + + + + + + +
+
+
- - - - - - - -
- -
-
- - -
-
- - - -
-

Version and Serial information

- -
-
-
- Serial: {{ stats['serial'] }} - Copy -
- Not Registred - License Validation failed -
-
-
- Serial: {{ stats['serial'] }} - Copy -
- Unable connect to server/Check server internet connection -
-
-
- Serial: {{ stats['serial'] }} - Copy -
- Registred - License Type : {{stats['license']}} - Manual update - Auto update -
-
- Your Mikroman version : {{stats['version']}} - - - - - Your Mikrofront version : {{front_version}} - - - - -
-

License User name is not set in settings read more!

-

Serial number not submitedread more!

- - -
-
- - - - - - - {{slide.title}} -
-
{{slide.title}}
-

+ +
+
+ + + +
{{widget.title}}
+ +
+ + +
+
+ +

{{widget.data?.usage || 0}}%

+

CPU Usage

- - - - - - - - +
+ + +
+
+
+ {{widget.data?.usage || 0}}% +
+
+

Memory Usage: {{widget.data?.used || 0}}GB / {{widget.data?.total || 0}}GB

+
+ + +
+
+
+ {{widget.data?.usage || 0}}% +
+
+

Disk Usage: {{widget.data?.used || 0}}GB / {{widget.data?.total || 0}}GB

+
+ + +
+
+
+

{{widget.data?.download || 0}}

+ Download +
+
+

{{widget.data?.upload || 0}}

+ Upload +
+
+
+
+
+
+
+ +
+
+ + + +
{{view.name}}
+ +
+ +

Custom view content will be loaded here...

+
+ +
+
+
+
+
+ +
+ + + + +
ADD WIZARD
+ +
+ +
+
+ + +
+
+ + +
+
+
+ + + + +
+ + + + +
ADD VIEW
+ +
+ +
+
+ + +
+
+ + +
+
+
+ + + + +
+ +
Please Confirm Mikroman Update
@@ -246,9 +282,7 @@
- - + + \ No newline at end of file diff --git a/src/app/views/dashboard/dashboard.component.scss b/src/app/views/dashboard/dashboard.component.scss new file mode 100644 index 0000000..257b694 --- /dev/null +++ b/src/app/views/dashboard/dashboard.component.scss @@ -0,0 +1,443 @@ +// Dashboard Header Styles +.dashboard-header { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + padding: 25px; + border-radius: 12px; + margin-bottom: 25px; + box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4); + + h2 { + margin: 0; + font-weight: 600; + text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + } +} + +.dashboard-controls { + .dropdown-toggle { + background: rgba(255, 255, 255, 0.2); + border: 2px solid rgba(255, 255, 255, 0.3); + color: white; + border-radius: 25px; + padding: 12px 24px; + font-weight: 500; + transition: all 0.3s ease; + backdrop-filter: blur(10px); + + &:hover { + background: rgba(255, 255, 255, 0.3); + border-color: rgba(255, 255, 255, 0.5); + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); + } + + i { + margin-right: 8px; + } + } + + .dropdown-menu { + border: none; + border-radius: 12px; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15); + padding: 8px 0; + margin-top: 8px; + + .dropdown-item { + padding: 12px 20px; + font-weight: 500; + transition: all 0.2s ease; + + &:hover { + background: #f8f9fa; + color: #495057; + } + + i { + margin-right: 10px; + width: 16px; + } + + &.text-danger:hover { + background: #dc3545; + color: white; + } + } + } +} + +// Dashboard Grid Layout +.dashboard-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + grid-gap: 20px; + grid-auto-rows: minmax(250px, auto); + margin-bottom: 20px; + + @media (max-width: 768px) { + grid-template-columns: 1fr; + grid-gap: 15px; + } +} + +// Widget Styles +.dashboard-widget { + position: relative; + transition: all 0.3s ease; + + &:hover { + transform: translateY(-2px); + } +} + +.widget-container { + position: relative; + height: 100%; + transition: all 0.3s ease; + + .card { + border: none; + border-radius: 12px; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); + transition: all 0.3s ease; + overflow: hidden; + + &:hover { + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); + } + + .card-header { + background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); + border-bottom: 1px solid #dee2e6; + padding: 15px 20px; + font-weight: 600; + color: #495057; + } + + .card-body { + padding: 20px; + } + } +} + +.widget-remove-btn { + position: absolute; + top: 15px; + right: 15px; + z-index: 10; + border-radius: 50%; + width: 32px; + height: 32px; + padding: 0; + display: flex; + align-items: center; + justify-content: center; + border: none; + background: #dc3545; + color: white; + font-size: 14px; + opacity: 0; + transition: all 0.3s ease; + transform: scale(0.8); + + &:hover { + background: #c82333; + transform: scale(1.1); + } +} + +.widget-drag-handle { + cursor: move; + color: #6c757d; + transition: color 0.2s ease; + + &:hover { + color: #495057; + } +} + +// Remove Mode Styles +.remove-mode { + .widget-container { + border: 2px dashed #dc3545; + border-radius: 12px; + background: rgba(220, 53, 69, 0.05); + + &:hover { + background: rgba(220, 53, 69, 0.1); + } + } + + .widget-remove-btn { + opacity: 1; + transform: scale(1); + } +} + +// Custom Widget Styles +.cpu-widget, .memory-widget, .disk-widget, .network-widget { + .progress { + border-radius: 8px; + overflow: hidden; + + .progress-bar { + transition: width 0.6s ease; + } + } + + canvas { + max-width: 100%; + height: auto; + } + + h3 { + color: #495057; + font-weight: 700; + margin: 0; + } + + .text-muted { + color: #6c757d !important; + font-size: 0.9rem; + } +} + +.network-widget { + .row > div { + padding: 15px; + border-radius: 8px; + margin: 5px; + background: #f8f9fa; + transition: all 0.3s ease; + + &:hover { + background: #e9ecef; + transform: translateY(-2px); + } + + h4 { + margin: 0; + font-weight: 600; + } + } +} + +// Modal Styles +.modal-content { + border: none; + border-radius: 12px; + overflow: hidden; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); +} + +.modal-header { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border-bottom: none; + padding: 20px 25px; + + h5 { + margin: 0; + font-weight: 600; + } + + .btn-close { + filter: brightness(0) invert(1); + opacity: 0.8; + + &:hover { + opacity: 1; + } + } +} + +.modal-body { + padding: 25px; + + .form-label { + font-weight: 600; + color: #495057; + margin-bottom: 8px; + } + + .form-control, .form-select { + border-radius: 8px; + border: 2px solid #e9ecef; + padding: 12px 15px; + transition: all 0.3s ease; + + &:focus { + border-color: #667eea; + box-shadow: 0 0 0 0.2rem rgba(102, 126, 234, 0.25); + } + } +} + +.modal-footer { + border-top: 1px solid #e9ecef; + padding: 20px 25px; + + .btn { + border-radius: 8px; + padding: 10px 20px; + font-weight: 500; + transition: all 0.3s ease; + + &.btn-primary { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + border: none; + + &:hover:not(:disabled) { + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4); + } + } + + &.btn-secondary { + border: 2px solid #6c757d; + color: #6c757d; + background: transparent; + + &:hover { + background: #6c757d; + color: white; + } + } + } +} + +// Stats Widget Specific Styles +.stats-widget { + .card-footer { + background: #f8f9fa; + border-top: 1px solid #dee2e6; + padding: 20px; + + .border-start { + border-left-width: 4px !important; + transition: all 0.3s ease; + + &:hover { + transform: translateX(5px); + } + } + } +} + +// Traffic Chart Widget +.traffic-widget { + .btn-group { + .btn { + border-radius: 6px; + font-size: 0.875rem; + padding: 8px 12px; + transition: all 0.3s ease; + + &.active { + background: #667eea; + border-color: #667eea; + } + } + } +} + +// Responsive Design +@media (max-width: 1200px) { + .dashboard-grid { + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + } +} + +@media (max-width: 768px) { + .dashboard-header { + padding: 20px; + text-align: center; + + .d-flex { + flex-direction: column; + gap: 15px; + } + } + + .dashboard-grid { + grid-template-columns: 1fr; + grid-gap: 15px; + } + + .widget-container .card { + .card-header { + padding: 12px 15px; + } + + .card-body { + padding: 15px; + } + } +} + +// Animation Keyframes +@keyframes slideInUp { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes pulse { + 0% { + transform: scale(1); + } + 50% { + transform: scale(1.05); + } + 100% { + transform: scale(1); + } +} + +// Apply animations +.dashboard-widget { + animation: slideInUp 0.5s ease-out; +} + +.widget-remove-btn:hover { + animation: pulse 0.3s ease-in-out; +} + +// Loading States +.loading-widget { + .card-body { + display: flex; + align-items: center; + justify-content: center; + min-height: 200px; + + .spinner-border { + color: #667eea; + } + } +} + +// Success/Error States +.widget-success { + .card { + border-left: 4px solid #28a745; + } +} + +.widget-warning { + .card { + border-left: 4px solid #ffc107; + } +} + +.widget-error { + .card { + border-left: 4px solid #dc3545; + } +} \ No newline at end of file diff --git a/src/app/views/dashboard/dashboard.component.ts b/src/app/views/dashboard/dashboard.component.ts index f5cc1a7..d756aa8 100644 --- a/src/app/views/dashboard/dashboard.component.ts +++ b/src/app/views/dashboard/dashboard.component.ts @@ -1,14 +1,43 @@ import { Component, OnInit } from "@angular/core"; -import { UntypedFormControl, UntypedFormGroup } from "@angular/forms"; +import { UntypedFormControl, UntypedFormGroup, FormBuilder, Validators } from "@angular/forms"; import { dataProvider } from "../../providers/mikrowizard/data"; import { loginChecker } from "../../providers/login_checker"; import { Router } from "@angular/router"; import { formatInTimeZone } from "date-fns-tz"; +interface DashboardWidget { + enabled: boolean; + position: { + col: string; + row: string; + }; +} + +interface CustomWidget { + id: string; + type: string; + title: string; + position: { + col: string; + row: string; + }; + data?: any; +} + +interface CustomView { + id: string; + name: string; + description?: string; + position: { + col: string; + row: string; + }; +} + @Component({ templateUrl: "dashboard.component.html", + styleUrls: ["./dashboard.component.scss"] }) - export class DashboardComponent implements OnInit { public uid: number; public uname: string; @@ -16,11 +45,29 @@ export class DashboardComponent implements OnInit { public copy_msg: any = false; public ConfirmModalVisible: boolean = false; public action: string = ""; - front_version=require('../../../../package.json').version; + public front_version = require('../../../../package.json').version; + + // Dashboard customization properties + public isRemoveMode: boolean = false; + public wizardModalVisible: boolean = false; + public viewModalVisible: boolean = false; + public wizardForm: UntypedFormGroup; + public viewForm: UntypedFormGroup; + + // Widget management + public widgets: { [key: string]: DashboardWidget } = { + stats: { enabled: true, position: { col: '1 / -1', row: '1' } }, + traffic: { enabled: true, position: { col: '1 / -1', row: '2' } } + }; + + public customWidgets: CustomWidget[] = []; + public customViews: CustomView[] = []; + constructor( private data_provider: dataProvider, private router: Router, - private login_checker: loginChecker + private login_checker: loginChecker, + private fb: FormBuilder ) { var _self = this; if (!this.login_checker.isLoggedIn()) { @@ -28,23 +75,33 @@ export class DashboardComponent implements OnInit { _self.router.navigate(["login"]); }, 100); } + this.data_provider.getSessionInfo().then((res) => { _self.uid = res.uid; _self.uname = res.name; _self.tz = res.tz; - const userId = _self.uid; }); - //get datagrid data - function isNotEmpty(value: any): boolean { - return value !== undefined && value !== null && value !== ""; - } + + // Initialize forms + this.wizardForm = this.fb.group({ + wizardType: ['', Validators.required], + wizardTitle: ['', Validators.required] + }); + + this.viewForm = this.fb.group({ + viewName: ['', Validators.required], + viewDescription: [''] + }); + + // Load saved dashboard configuration + this.loadDashboardConfig(); } public trafficRadioGroup = new UntypedFormGroup({ trafficRadio: new UntypedFormControl("5m"), }); + public chart_data: any = {}; - public Chartoptions = { responsive: true, plugins: { @@ -55,7 +112,6 @@ export class DashboardComponent implements OnInit { let label = context.dataset.label || ""; var res = context.parsed.y; let unitIndex = 0; - // if (res>8) res /=8; while (res >= 1024 && unitIndex < units.length - 1) { res /= 1024; unitIndex++; @@ -63,19 +119,14 @@ export class DashboardComponent implements OnInit { switch (context.dataset.unit) { case "rx": return "rx/s :" + res.toFixed(3) + " " + units[unitIndex]; - break; case "tx": return "tx/s :" + res.toFixed(3) + " " + units[unitIndex]; - break; case "rxp": return "rxp/s :" + context.parsed.y; - break; case "txp": return "txp/s :" + context.parsed.y; - break; default: return context.parsed.y; - break; } }, }, @@ -161,6 +212,7 @@ export class DashboardComponent implements OnInit { }, }, }; + public options: any; public delta: string = "5m"; public stats: any = false; @@ -169,8 +221,159 @@ export class DashboardComponent implements OnInit { this.options = this.Chartoptions; this.initStats(); this.initTrafficChart(); + this.startDataRefresh(); } + // Dashboard customization methods + showWizardModal(): void { + this.wizardModalVisible = true; + this.wizardForm.reset(); + } + + showViewModal(): void { + this.viewModalVisible = true; + this.viewForm.reset(); + } + + toggleRemoveMode(): void { + this.isRemoveMode = !this.isRemoveMode; + } + + commitWizard(): void { + if (this.wizardForm.valid) { + const formValue = this.wizardForm.value; + const newWidget: CustomWidget = { + id: this.generateId(), + type: formValue.wizardType, + title: formValue.wizardTitle, + position: this.getNextAvailablePosition(), + data: this.getInitialWidgetData(formValue.wizardType) + }; + + this.customWidgets.push(newWidget); + this.saveDashboardConfig(); + this.wizardModalVisible = false; + this.startWidgetDataRefresh(newWidget); + } + } + + commitView(): void { + if (this.viewForm.valid) { + const formValue = this.viewForm.value; + const newView: CustomView = { + id: this.generateId(), + name: formValue.viewName, + description: formValue.viewDescription, + position: this.getNextAvailablePosition() + }; + + this.customViews.push(newView); + this.saveDashboardConfig(); + this.viewModalVisible = false; + } + } + + removeWidget(widgetType: string): void { + this.widgets[widgetType].enabled = false; + this.saveDashboardConfig(); + } + + removeCustomWidget(index: number): void { + this.customWidgets.splice(index, 1); + this.saveDashboardConfig(); + } + + removeCustomView(index: number): void { + this.customViews.splice(index, 1); + this.saveDashboardConfig(); + } + + // Helper methods + private generateId(): string { + return 'widget_' + Math.random().toString(36).substr(2, 9); + } + + private getNextAvailablePosition(): { col: string; row: string } { + const totalWidgets = Object.keys(this.widgets).filter(key => this.widgets[key].enabled).length + + this.customWidgets.length + this.customViews.length; + const row = Math.floor(totalWidgets / 2) + 3; // Start after default widgets + const col = (totalWidgets % 2) === 0 ? '1 / 2' : '2 / 3'; + return { col, row: row.toString() }; + } + + private getInitialWidgetData(type: string): any { + switch (type) { + case 'cpu': + return { usage: 0 }; + case 'memory': + return { usage: 0, used: 0, total: 0 }; + case 'disk': + return { usage: 0, used: 0, total: 0 }; + case 'network': + return { download: '0 MB/s', upload: '0 MB/s' }; + default: + return {}; + } + } + + private loadDashboardConfig(): void { + const saved = localStorage.getItem('dashboard_config'); + if (saved) { + try { + const config = JSON.parse(saved); + this.widgets = { ...this.widgets, ...config.widgets }; + this.customWidgets = config.customWidgets || []; + this.customViews = config.customViews || []; + } catch (e) { + console.error('Error loading dashboard config:', e); + } + } + } + + private saveDashboardConfig(): void { + const config = { + widgets: this.widgets, + customWidgets: this.customWidgets, + customViews: this.customViews + }; + localStorage.setItem('dashboard_config', JSON.stringify(config)); + } + + private startDataRefresh(): void { + // Refresh widget data every 5 seconds + setInterval(() => { + this.customWidgets.forEach(widget => this.updateWidgetData(widget)); + }, 5000); + } + + private startWidgetDataRefresh(widget: CustomWidget): void { + this.updateWidgetData(widget); + } + + private updateWidgetData(widget: CustomWidget): void { + // Simulate data updates - in real implementation, fetch from API + switch (widget.type) { + case 'cpu': + widget.data.usage = Math.floor(Math.random() * 100); + break; + case 'memory': + widget.data.usage = Math.floor(Math.random() * 100); + widget.data.used = (Math.random() * 16).toFixed(1); + widget.data.total = 16; + break; + case 'disk': + widget.data.usage = Math.floor(Math.random() * 100); + widget.data.used = (Math.random() * 500).toFixed(1); + widget.data.total = 500; + break; + case 'network': + widget.data.download = (Math.random() * 100).toFixed(1) + ' MB/s'; + widget.data.upload = (Math.random() * 50).toFixed(1) + ' MB/s'; + break; + } + } + + // Original methods initTrafficChart(): void { var _self = this; this.data_provider.dashboard_traffic(this.delta).then((res) => { @@ -184,44 +387,45 @@ export class DashboardComponent implements OnInit { _self.chart_data = { datasets: res["data"]["datasets"], labels: labels }; }); } - initStats() { + + initStats(): void { var _self = this; - this.data_provider.dashboard_stats(true,this.front_version).then((res) => { + this.data_provider.dashboard_stats(true, this.front_version).then((res) => { _self.stats = res; }); } - copy_this() { - //show text copy to clipboard for 3 seconds + copy_this(): void { this.copy_msg = true; setTimeout(() => { this.copy_msg = false; }, 3000); } - // Traffic Chart setTrafficPeriod(value: string): void { this.trafficRadioGroup.setValue({ trafficRadio: value }); this.delta = value; this.initTrafficChart(); } - showConfirmModal(action: string) { + + showConfirmModal(action: string): void { this.action = action; - this.ConfirmModalVisible = true + this.ConfirmModalVisible = true; } - ConfirmAction() { + + ConfirmAction(): void { var _self = this; - this.data_provider.apply_update(this.action).then((res) => { - if (res["status"]=='success') { - if (_self.action=='update_mikroman') { - _self.stats['update_inprogress']=true; - } - if (_self.action=='update_mikrofront') { - _self.stats['front_update_inprogress']=true; - } - _self.action=""; - _self.ConfirmModalVisible = false; + this.data_provider.apply_update(this.action).then((res) => { + if (res["status"] == 'success') { + if (_self.action == 'update_mikroman') { + _self.stats['update_inprogress'] = true; } - }); + if (_self.action == 'update_mikrofront') { + _self.stats['front_update_inprogress'] = true; + } + _self.action = ""; + _self.ConfirmModalVisible = false; + } + }); } } diff --git a/src/app/views/pages/login/login.component.html b/src/app/views/pages/login/login.component.html index 77a0218..ef20267 100644 --- a/src/app/views/pages/login/login.component.html +++ b/src/app/views/pages/login/login.component.html @@ -1,62 +1,74 @@
- - - - - - - - - - - -
-

Login

-

Sign In to your account

- - - - - - - - - - - - - - - - - - - {{error_msg}} - - - - - -
-
-
+ + + + + + + + + + + +
+

Sign in

+

Don't have an account?

+ + + + + + + + + + + + + + + + + + + {{error_msg}} + + + + + +

or continue with

+
+ + + + + + +
+
+
+
-
-
-
-
-
+ +
+
+ + \ No newline at end of file diff --git a/src/app/views/pages/login/login.component.scss b/src/app/views/pages/login/login.component.scss index e69de29..41b0c81 100644 --- a/src/app/views/pages/login/login.component.scss +++ b/src/app/views/pages/login/login.component.scss @@ -0,0 +1,38 @@ +$primary-color: #303c54; +$secondary-color: #ffffff; +$border-color: #000000; +$hover-bg-color: #f8f9fa; +$signin-bg-color: #635DFF; +$signin-hover-color: #4a46d1; + +.btn-social { + color: $primary-color; + background-color: $secondary-color; + border: 1px solid $border-color; + + &:hover { + background-color: $hover-bg-color; + } +} + +.signup-link { + color: $primary-color; + text-decoration: none; + font-weight: bold; +} + +.heading-text { + font-size: 1.5rem; + font-weight: bold; + color: $primary-color; +} + +.btn-signin { + background-color: $signin-bg-color; + color: $secondary-color; + font-weight: bold; + + &:hover { + background-color: $signin-hover-color; + } +} diff --git a/src/app/views/pages/login/login.component.ts b/src/app/views/pages/login/login.component.ts index b3910e7..b60b74d 100644 --- a/src/app/views/pages/login/login.component.ts +++ b/src/app/views/pages/login/login.component.ts @@ -1,15 +1,26 @@ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { dataProvider } from '../../../providers/mikrowizard/data'; import { loginChecker } from '../../../providers/login_checker'; import { Validators, FormControl, FormGroup} from '@angular/forms'; +import { MsalService } from '@azure/msal-angular'; +import { loginRequest } from '../../../auth/msal-config'; +import { appleConfig } from '../../../auth/apple-config'; +import appleSignin from 'apple-signin-auth'; +import { MikroWizardUtils } from '../../../../components/utils/common-functions'; + +declare global { + interface Window { + AppleID: any; + } +} @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.scss'] }) -export class LoginComponent { +export class LoginComponent implements OnInit { public loginForm: FormGroup; public forgotForm: FormGroup; public error_msg: string = ""; @@ -24,10 +35,22 @@ export class LoginComponent { private router: Router, private data_provider: dataProvider, private login_checker: loginChecker, + private msalService: MsalService + ) { this.createForm(); }; + ngOnInit() { + // Check if user is already logged in with MSAL + if (this.msalService.instance.getActiveAccount()) { + // this.handleMsalLogin(); + } + + // Initialize Apple Sign In + this.initializeAppleSignIn(); + } + createForm() { this.loginForm = new FormGroup({ username: new FormControl(''), @@ -64,4 +87,93 @@ export class LoginComponent { }); } + loginWithOffice365() { + this.msalService.loginPopup(loginRequest) + .subscribe({ + next: (result) => { + console.log(result) + this.handleMsalLogin(result?.account); + }, + error: (error) => { + this.error_msg = "Error during Office 365 login: " + error.message; + console.error('MSAL login error:', error); + } + }); + } + + private handleMsalLogin(request: any) { + if (request) { + let data = { + email:request?.username, + username:request?.username, + first_name:request?.name?.split(" ")[0], + last_name:request?.name?.split(" ")[1] + } + console.log(">>>>>>>>>>>>>>> data from token >>>>>>", data) + this.data_provider.singSignonLoginForUser(data) + .then(res => { + if ('uid' in res && res['uid']) { + this.error_msg = ""; + this.login_checker.setStatus(true); + this.router.navigate(['/'], { replaceUrl: true }); + } else { + this.error_msg = 'Error: Problem with Office 365 login'; + } + }) + .catch(err => { + this.error_msg = "Connection with backend broken!"; + console.error('Backend error:', err); + }); + } + } + + private initializeAppleSignIn() { + // Load Apple Sign In script + const script = document.createElement('script'); + script.src = 'https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js'; + script.onload = () => { + window.AppleID.auth.init({ + clientId: appleConfig.clientId, + scope: appleConfig.scope, + redirectURI: appleConfig.redirectURI, + state: appleConfig.state, + usePopup: appleConfig.usePopup + }); + }; + document.body.appendChild(script); + console.log(appleConfig); + } + + + + + loginWithApple() { + window.AppleID.auth.signIn() + .then((response: any) => { + // Handle successful sign in + this.handleAppleLogin(response); + }) + .catch((error: any) => { + this.error_msg = "Error during Apple login: " + error.message; + console.error('Apple login error:', error); + }); + } + + private handleAppleLogin(response: any) { + console.log(JSON.stringify(response)); + this.data_provider.singSignonLoginForUser(response) + .then(res => { + if ('uid' in res && res['uid']) { + this.error_msg = ""; + this.login_checker.setStatus(true); + this.router.navigate(['/'], { replaceUrl: true }); + } else { + this.error_msg = 'Error: Problem with Apple login'; + } + }) + .catch(err => { + this.error_msg = "Connection with backend broken!"; + console.error('Backend error:', err); + }); + } } diff --git a/src/app/views/pages/pages-routing.module.ts b/src/app/views/pages/pages-routing.module.ts index b72022b..8cf6d83 100644 --- a/src/app/views/pages/pages-routing.module.ts +++ b/src/app/views/pages/pages-routing.module.ts @@ -3,6 +3,7 @@ import { RouterModule, Routes } from '@angular/router'; import { Page404Component } from './page404/page404.component'; import { Page500Component } from './page500/page500.component'; import { LoginComponent } from './login/login.component'; +import { SignupComponent } from './signup/signup.component'; const routes: Routes = [ { @@ -26,6 +27,13 @@ const routes: Routes = [ title: 'Login Page' } }, + { + path: 'signup', + component: SignupComponent, + data: { + title: 'Signup Page' + } + }, ]; @NgModule({ diff --git a/src/app/views/pages/pages.module.ts b/src/app/views/pages/pages.module.ts index 6c3250f..9778d57 100644 --- a/src/app/views/pages/pages.module.ts +++ b/src/app/views/pages/pages.module.ts @@ -3,16 +3,17 @@ import { CommonModule } from '@angular/common'; import { PagesRoutingModule } from './pages-routing.module'; import { LoginComponent } from './login/login.component'; +import { SignupComponent } from './signup/signup.component'; import { Page404Component } from './page404/page404.component'; import { Page500Component } from './page500/page500.component'; import { ButtonModule, CardModule, FormModule, GridModule } from '@coreui/angular'; import { IconModule } from '@coreui/icons-angular'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; - @NgModule({ declarations: [ LoginComponent, + SignupComponent, Page404Component, Page500Component ], diff --git a/src/app/views/pages/signup/signup.component.html b/src/app/views/pages/signup/signup.component.html new file mode 100644 index 0000000..1e6fb51 --- /dev/null +++ b/src/app/views/pages/signup/signup.component.html @@ -0,0 +1,115 @@ +
+ + + + + + + + + + + +
+

Create your account

+

Already have an account?

+ + + + + + + +
+ Username is required +
+ + + + + + + +
+ Organization field is required +
+ + + + + + + +
+ Email is + required + Please enter a valid + email +
+ + + + + + + +
+ Password is + required + Password must be at + least 6 characters +
+ + + + + + + +
+ Please confirm your password +
+ + {{error_msg}} + {{success_msg}} + + + + + +

or continue with

+
+ + + + + + +
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/src/app/views/pages/signup/signup.component.scss b/src/app/views/pages/signup/signup.component.scss new file mode 100644 index 0000000..a028390 --- /dev/null +++ b/src/app/views/pages/signup/signup.component.scss @@ -0,0 +1,38 @@ +$primary-color: #303c54; +$secondary-color: #ffffff; +$border-color: #000000; +$hover-bg-color: #f8f9fa; +$signin-bg-color: #635DFF; +$signin-hover-color: #4a46d1; + +.signup-link { + color: $primary-color; + text-decoration: none; + font-weight: bold; +} + +.heading-text { + font-size: 1.5rem; + font-weight: bold; + color: $primary-color; +} + +.btn-signin { + background-color: $signin-bg-color; + color: $secondary-color; + font-weight: bold; + + &:hover { + background-color: $signin-hover-color; + } +} + +.btn-social { + color: $primary-color; + background-color: $secondary-color; + border: 1px solid $border-color; + + &:hover { + background-color: $hover-bg-color; + } +} \ No newline at end of file diff --git a/src/app/views/pages/signup/signup.component.ts b/src/app/views/pages/signup/signup.component.ts new file mode 100644 index 0000000..3b1c8df --- /dev/null +++ b/src/app/views/pages/signup/signup.component.ts @@ -0,0 +1,61 @@ +import { Component } from '@angular/core'; +import { Router } from '@angular/router'; +import { dataProvider } from '../../../providers/mikrowizard/data'; +import { Validators, FormControl, FormGroup } from '@angular/forms'; + +@Component({ + selector: 'app-signup', + templateUrl: './signup.component.html', + styleUrls: ['./signup.component.scss'] +}) +export class SignupComponent { + public signupForm: FormGroup; + public error_msg: string = ""; + public success_msg: string = ""; + public submitted = false; + + constructor( + private router: Router, + private data_provider: dataProvider, + ) { + this.createForm(); + } + + createForm() { + this.signupForm = new FormGroup({ + username: new FormControl('', [Validators.required]), + organization: new FormControl('', [Validators.required]), + email: new FormControl('', [Validators.required, Validators.email]), + password: new FormControl('', [Validators.required, Validators.minLength(6)]), + confirmPassword: new FormControl('', [Validators.required]) + }); + } + + onClickSubmit() { + this.submitted = true; + if (this.signupForm.invalid) { + return; + } + + const formData = this.signupForm.value; + if (formData.password !== formData.confirmPassword) { + this.error_msg = "Passwords do not match"; + return; + } + + this.data_provider.signup(formData.username, formData.organization, formData.email, formData.password) + .then(res => { + if (res['status'] === 'success') { + this.success_msg = "Registration successful! Please login."; + setTimeout(() => { + this.router.navigate(['/login']); + }, 2000); + } else { + this.error_msg = res['err'] || 'Registration failed'; + } + }) + .catch(err => { + this.error_msg = "Connection with backend broken!"; + }); + } +} \ No newline at end of file diff --git a/src/assets/Pause GIF Image.gif b/src/assets/Pause GIF Image.gif new file mode 100644 index 0000000..b2ddfa1 Binary files /dev/null and b/src/assets/Pause GIF Image.gif differ diff --git a/src/components/utils/common-functions.ts b/src/components/utils/common-functions.ts new file mode 100644 index 0000000..9e75914 --- /dev/null +++ b/src/components/utils/common-functions.ts @@ -0,0 +1,27 @@ +// your.component.ts or service.ts +import { Injectable } from '@angular/core'; +import {jwtDecode} from 'jwt-decode'; + +interface JwtPayload { + // Define keys you expect from the JWT payload + sub?: string; + name?: string; + email?: string; + exp?: number; + [key: string]: any; // to allow additional keys +} + +export class MikroWizardUtils { + + public static decodeJWT(token: any) { + try { + const decoded = jwtDecode(token); + console.log('Decoded JWT:', decoded); + console.log('User email:', decoded['unique_name']); + return decoded; + } catch (error) { + console.error('Invalid JWT token:', error); + return null; + } + } +}