diff --git a/NOTICE.txt b/NOTICE.txt index 156e87e7..169ecf9d 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -20,8 +20,6 @@ The following components are provided under the MIT License (MIT). See project l GraphQL Java implementation (https://github.com/graphql-java/graphql-java) Angular (https://github.com/angular/angular) ng2-charts (https://github.com/valor-software/ng2-charts) - Angular2 Materialize (https://github.com/InfomediaLtd/angular2-materialize) - Materialize (https://github.com/Dogfalo/materialize) Chart.js (https://github.com/chartjs/Chart.js) Annotation plugin for Chart.js (https://github.com/chartjs/chartjs-plugin-annotation) angular2-moment (https://github.com/urish/angular2-moment) @@ -47,12 +45,12 @@ The following components are provided under the Apache License 2.0. See project Less (https://github.com/less/less.js) Typescript (https://github.com/Microsoft/TypeScript) - + ======================================================================== Creative Commons - Attribution-NonCommercial-NoDerivs 2.0 Generic -======================================================================== - DC Comics LEGO variant covers +======================================================================== + DC Comics LEGO variant covers Origin: https://www.flickr.com/photos/toomuchdew/albums/72157645848803730/with/14667325240 License: https://creativecommons.org/licenses/by-nc-nd/2.0/ diff --git a/build.gradle b/build.gradle index efa15d6f..00d6a036 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ app { node { download = true - version = '16.10.0' + version = '18.19.0' } dependencies { diff --git a/package-lock.json b/package-lock.json index b1cc5f90..1febf45e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,16 +6,15 @@ "": { "name": "office-league", "dependencies": { - "@angular/common": "13.2.6", - "@angular/compiler": "13.2.6", - "@angular/core": "13.2.6", - "@angular/forms": "13.2.6", - "@angular/localize": "13.2.6", - "@angular/platform-browser": "13.2.6", - "@angular/platform-browser-dynamic": "13.2.6", - "@angular/router": "13.2.6", - "angular2-materialize": "15.1.10", - "angular2-moment": "1.9.0", + "@angular/common": "15.2.10", + "@angular/compiler": "15.2.10", + "@angular/core": "^15.2.10", + "@angular/forms": "15.2.10", + "@angular/localize": "15.2.10", + "@angular/material": "14.2.7", + "@angular/platform-browser": "15.2.10", + "@angular/platform-browser-dynamic": "15.2.10", + "@angular/router": "15.2.10", "chart.js": "^3.9.1", "chartjs-plugin-annotation": "2.2.1", "core-js": "^3.35.1", @@ -23,18 +22,16 @@ "hammerjs": "^2.0.8", "jquery": "^3.7.1", "material-design-icons": "3.0.1", - "materialize-css": "1.0.0", "ng2-charts": "^3.1.2", "rxjs": "7.8.1", "ts-loader": "^9.5.1", "webpack-node-externals": "^3.0.0", - "zone.js": "~0.11.8" + "zone.js": "~0.13.0" }, "devDependencies": { - "@angular/compiler-cli": "13.2.6", - "@ngtools/webpack": "13.3.11", - "@types/materialize-css": "1.0.14", - "@types/node": "20.11.16", + "@angular/compiler-cli": "15.2.10", + "@ngtools/webpack": "15.2.10", + "@types/node": "20.11.0", "babel-loader": "^9.1.3", "copy-webpack-plugin": "12.0.2", "css-loader": "6.10.0", @@ -46,15 +43,15 @@ "raw-loader": "^4.0.0", "style-loader": "3.3.4", "to-string-loader": "1.2.0", - "typescript": "4.5.5", + "typescript": "4.8.2", "webpack": "^5.90.1", "webpack-cli": "^5.1.4", "webpack-dev-server": "^4.15.1", "webpack-merge": "5.10.0" }, "engines": { - "node": ">= 16.10.0", - "npm": ">= 7.10.0" + "node": ">= 18.19.0", + "npm": ">= 10.2.3" } }, "node_modules/@ampproject/remapping": { @@ -70,60 +67,84 @@ } }, "node_modules/@angular/animations": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-13.2.6.tgz", - "integrity": "sha512-DrjpKo68uR3lSLQQXosoTCbjKQS6IKRCpR14E2t8fo0AX8i2hkB8je4SrhdCyB7FgFN7l2kgUYo4Qa8+BOB+aA==", - "optional": true, + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-15.2.10.tgz", + "integrity": "sha512-yxfN8qQpMaukRU5LjFkJBmy85rqrOp86tYVCsf+hmPEFRiXBMUj6xYLeCMcpk3Mt1JtnWGBR34ivGx+7bNeAow==", "peer": true, "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^12.20.0 || ^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/core": "15.2.10" + } + }, + "node_modules/@angular/cdk": { + "version": "14.2.7", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-14.2.7.tgz", + "integrity": "sha512-/tEsYaUbDSnfEmKVvAMramIptmhI67O+9STjOV0i+74XR2NospeK0fkbywIANu1n3w6AHGMotvRWJrjmbCElFg==", + "peer": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "optionalDependencies": { + "parse5": "^5.0.0" }, "peerDependencies": { - "@angular/core": "13.2.6" + "@angular/common": "^14.0.0 || ^15.0.0", + "@angular/core": "^14.0.0 || ^15.0.0", + "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/common": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-13.2.6.tgz", - "integrity": "sha512-t4XRb9db4UeRcPs5aHNtGuXRKSvGBlTEr0zzSeoKzHD9TCaO4dSDISh9obS9hThaPuBmPKRUHN5KE1HFmqnSHg==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-15.2.10.tgz", + "integrity": "sha512-jdBn3fctkqoNrJn9VLsUHpcCEhCxWSczdsR+BBbD6T0oLl6vMrAVNjPwfBejnlgfWN1KoRU9kgOYsMxa5apIWQ==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^12.20.0 || ^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" }, "peerDependencies": { - "@angular/core": "13.2.6", + "@angular/core": "15.2.10", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-13.2.6.tgz", - "integrity": "sha512-LHU29J2/c/03WHkwtzUSElTBsXbzkKdYARodnNfsFdLPsWhyvzO3cqlcZYteFJxEy3dVH+ZrYDjqQ9Sp17aIgA==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-15.2.10.tgz", + "integrity": "sha512-M0XkeU0O73UlJZwDvOyp8/apetz9UKj78eTFDseMYJDLcxe6MpkbkxqpsGZnKYDj7LIep8PmCAKEkhtenE82zw==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^12.20.0 || ^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/core": "15.2.10" + }, + "peerDependenciesMeta": { + "@angular/core": { + "optional": true + } } }, "node_modules/@angular/compiler-cli": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-13.2.6.tgz", - "integrity": "sha512-QtlLKj3m6a2nkewFxhg+a3tQ2gEIBzMfI2c1laWUfAfJJ56phj79k8Z/kf2HQxypphWixyTK+ugpTlMdvvOquA==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-15.2.10.tgz", + "integrity": "sha512-mCFIxrs60XicKfA2o42hA7LrQvhybi9BQveWuZn/2iIEOXx7R62Iemz8E21pLWftAZHGxEW3NECfBrY1d3gVmA==", "dependencies": { - "@babel/core": "^7.17.2", + "@babel/core": "7.19.3", + "@jridgewell/sourcemap-codec": "^1.4.14", "chokidar": "^3.0.0", "convert-source-map": "^1.5.1", "dependency-graph": "^0.11.0", - "magic-string": "^0.26.0", + "magic-string": "^0.27.0", "reflect-metadata": "^0.1.2", "semver": "^7.0.0", - "sourcemap-codec": "^1.4.8", "tslib": "^2.3.0", "yargs": "^17.2.1" }, @@ -133,52 +154,89 @@ "ngcc": "bundles/ngcc/main-ngcc.js" }, "engines": { - "node": "^12.20.0 || ^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" }, "peerDependencies": { - "@angular/compiler": "13.2.6", - "typescript": ">=4.4.2 <4.6" + "@angular/compiler": "15.2.10", + "typescript": ">=4.8.2 <5.0" + } + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/core": { + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", + "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.3", + "@babel/helper-compilation-targets": "^7.19.3", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.3", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.3", + "@babel/types": "^7.19.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" } }, "node_modules/@angular/core": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-13.2.6.tgz", - "integrity": "sha512-ctWsxuaSO3d3afLW+wkJSyiEIA2uhaTKNps9x5wz/oZJDaUDYVa4PM4x7/UHn2bXzBjXjN9LSW8h9F31iwmcTg==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-15.2.10.tgz", + "integrity": "sha512-meGGidnitQJGDxYd9/LrqYiVlId+vGaLoiLgJdKBz+o2ZO6OmXQGuNw2VBqf17/Cc0/UjzrOY7+kILNFKkk/WQ==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^12.20.0 || ^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" }, "peerDependencies": { "rxjs": "^6.5.3 || ^7.4.0", - "zone.js": "~0.11.4" + "zone.js": "~0.11.4 || ~0.12.0 || ~0.13.0" } }, "node_modules/@angular/forms": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-13.2.6.tgz", - "integrity": "sha512-3IikvNtO0RBiGb2AWl8aYcE3ivXHPIJz+JOn9Wz9XXSkYx75D3GjuJlz+fVIgz+7Q7tJuS6Q2E5qat/ldeDmoA==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-15.2.10.tgz", + "integrity": "sha512-NIntGsNcN6o8L1txsbWXOf6f3K/CUBizdKsxsYVYGJIXEW5qU6UnWmfAZffNNXsT/XvbgUCjgDwT0cAwcqZPuQ==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^12.20.0 || ^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" }, "peerDependencies": { - "@angular/common": "13.2.6", - "@angular/core": "13.2.6", - "@angular/platform-browser": "13.2.6", + "@angular/common": "15.2.10", + "@angular/core": "15.2.10", + "@angular/platform-browser": "15.2.10", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/localize": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-13.2.6.tgz", - "integrity": "sha512-QyjOa8ptzLEFTGYTV5aFaEZ5I3fAZUU34P2+Xr9xYNn6Mv8JSoUPVZgaj3SDXxpW75Z6Xgzt841/qDe5/FYm6w==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-15.2.10.tgz", + "integrity": "sha512-RHN+mUR4H34c/LLnNPAyQbfuZME4i9JgodK5YRRX8cSAFPafYLT0SspSuLsKtcCCEDadAZNDHzb8qv5MBtzJtg==", "dependencies": { - "@babel/core": "7.17.2", - "glob": "7.2.0", + "@babel/core": "7.19.3", + "glob": "8.1.0", "yargs": "^17.2.1" }, "bin": { @@ -187,32 +245,32 @@ "localize-translate": "tools/bundles/src/translate/cli.js" }, "engines": { - "node": "^12.20.0 || ^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" }, "peerDependencies": { - "@angular/compiler": "13.2.6", - "@angular/compiler-cli": "13.2.6" + "@angular/compiler": "15.2.10", + "@angular/compiler-cli": "15.2.10" } }, "node_modules/@angular/localize/node_modules/@babel/core": { - "version": "7.17.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.2.tgz", - "integrity": "sha512-R3VH5G42VSDolRHyUO4V2cfag8WHcZyxdq5Z/m8Xyb92lW/Erm/6kM+XtRFGf3Mulre3mveni2NHfEUws8wSvw==", - "dependencies": { - "@ampproject/remapping": "^2.0.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.0", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helpers": "^7.17.2", - "@babel/parser": "^7.17.0", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.0", - "@babel/types": "^7.17.0", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", + "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.3", + "@babel/helper-compilation-targets": "^7.19.3", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.3", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.3", + "@babel/types": "^7.19.3", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", + "json5": "^2.2.1", "semver": "^6.3.0" }, "engines": { @@ -223,6 +281,43 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@angular/localize/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@angular/localize/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@angular/localize/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@angular/localize/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -231,20 +326,37 @@ "semver": "bin/semver.js" } }, + "node_modules/@angular/material": { + "version": "14.2.7", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-14.2.7.tgz", + "integrity": "sha512-WXHh8pEStpgkXZJmYOg2cI8BSHkV82ET4XTJCNPdveumaCn1UYnaNzsXD13kw5z+zmy8CufhFEzdXTrv/yt7KQ==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/animations": "^14.0.0 || ^15.0.0", + "@angular/cdk": "14.2.7", + "@angular/common": "^14.0.0 || ^15.0.0", + "@angular/core": "^14.0.0 || ^15.0.0", + "@angular/forms": "^14.0.0 || ^15.0.0", + "@angular/platform-browser": "^14.0.0 || ^15.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, "node_modules/@angular/platform-browser": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-13.2.6.tgz", - "integrity": "sha512-Gc/1TqysW+P+K3NeQihmHWs4KF1mjJT20s06r+YcETnPP11uPk+UxQl7gJNsDV587DYO/wT3oISXVpRw4UJhdQ==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-15.2.10.tgz", + "integrity": "sha512-9tbgVGSJqwfrOzT8aA/kWBLNhJSQ9gUg0CJxwFBSJm8VkBUJrszoBlDsnSvlxx8/W2ejNULKHFTXeUzq0O/+RQ==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^12.20.0 || ^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" }, "peerDependencies": { - "@angular/animations": "13.2.6", - "@angular/common": "13.2.6", - "@angular/core": "13.2.6" + "@angular/animations": "15.2.10", + "@angular/common": "15.2.10", + "@angular/core": "15.2.10" }, "peerDependenciesMeta": { "@angular/animations": { @@ -253,36 +365,36 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-13.2.6.tgz", - "integrity": "sha512-m77+pzwZw+4kiRhxzrj1kE3N1K82I8Xt+vEBKSL2Xv42hCX0T37erC6KlztFEDj4A68s5+/0C5vfwhEiDcr/Cw==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-15.2.10.tgz", + "integrity": "sha512-JHP6W+FX715Qv7DhqvfZLuBZXSDJrboiQsR06gUAgDSjAUyhbqmpVg/2YOtgeWpPkzNDtXdPU2PhcRdIv5J3Yg==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^12.20.0 || ^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" }, "peerDependencies": { - "@angular/common": "13.2.6", - "@angular/compiler": "13.2.6", - "@angular/core": "13.2.6", - "@angular/platform-browser": "13.2.6" + "@angular/common": "15.2.10", + "@angular/compiler": "15.2.10", + "@angular/core": "15.2.10", + "@angular/platform-browser": "15.2.10" } }, "node_modules/@angular/router": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-13.2.6.tgz", - "integrity": "sha512-dA9vL4mPLp+iNegzuvm9FaEWirFI2ZK3WQgbdoxoIpneym+BxRTkNDzPcvEaqfUf7eDGRBqlWakFDrd+H2QEbg==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-15.2.10.tgz", + "integrity": "sha512-LmuqEg0iIXSw7bli6HKJ19cbxP91v37GtRwbGKswyLihqzTgvjBYpvcfMnB5FRQ5LWkTwq5JclkX03dZw290Yg==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^12.20.0 || ^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" }, "peerDependencies": { - "@angular/common": "13.2.6", - "@angular/core": "13.2.6", - "@angular/platform-browser": "13.2.6", + "@angular/common": "15.2.10", + "@angular/core": "15.2.10", + "@angular/platform-browser": "15.2.10", "rxjs": "^6.5.3 || ^7.4.0" } }, @@ -353,6 +465,7 @@ "version": "7.23.2", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.22.13", @@ -381,12 +494,14 @@ "node_modules/@babel/core/node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "peer": true }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "peer": true, "bin": { "semver": "bin/semver.js" } @@ -741,19 +856,19 @@ "dev": true }, "node_modules/@ngtools/webpack": { - "version": "13.3.11", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-13.3.11.tgz", - "integrity": "sha512-gB33hTbc/RJmHyIgSUYj8ErPazhYYm7yfapOnvwHdYhCjrj1TKkR1ierOlhJtpfBYUQg6FChdl2YpyIQNPjWMA==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-15.2.10.tgz", + "integrity": "sha512-ZExB4rKh/Saad31O/Ofd2XvRuILuCNTYs0+qJL697Be2pzeewvzBhE4Xe1Mm7Jg13aWSPeuIdzSGOqCdwxxxFQ==", "dev": true, "engines": { - "node": "^12.20.0 || ^14.15.0 || >=16.10.0", + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" }, "peerDependencies": { - "@angular/compiler-cli": "^13.0.0", - "typescript": ">=4.4.3 <4.7", - "webpack": "^5.30.0" + "@angular/compiler-cli": "^15.0.0", + "typescript": ">=4.8.2 <5.0", + "webpack": "^5.54.0" } }, "node_modules/@nodelib/fs.scandir": { @@ -902,30 +1017,11 @@ "@types/node": "*" } }, - "node_modules/@types/jquery": { - "version": "3.5.14", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz", - "integrity": "sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg==", - "dev": true, - "dependencies": { - "@types/sizzle": "*" - } - }, "node_modules/@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" }, - "node_modules/@types/materialize-css": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/@types/materialize-css/-/materialize-css-1.0.14.tgz", - "integrity": "sha512-Jt8ReN/R7zrz1TBby0KvyJzAIB9353c1jaFjZt8fIaY/xsalED/8OsFuog1PJ79OuXleRWyJ+MZ8dmjbArXepg==", - "dev": true, - "dependencies": { - "@types/jquery": "*", - "cash-dom": "*" - } - }, "node_modules/@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", @@ -933,9 +1029,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", - "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", + "version": "20.11.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.0.tgz", + "integrity": "sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==", "dependencies": { "undici-types": "~5.26.4" } @@ -977,12 +1073,6 @@ "@types/node": "*" } }, - "node_modules/@types/sizzle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", - "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", - "dev": true - }, "node_modules/@types/sockjs": { "version": "0.3.33", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", @@ -1279,26 +1369,6 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, - "node_modules/angular2-materialize": { - "version": "15.1.10", - "resolved": "https://registry.npmjs.org/angular2-materialize/-/angular2-materialize-15.1.10.tgz", - "integrity": "sha1-d17LSgs5tXieOkAOYMZ7xIyFNN8=", - "peerDependencies": { - "@angular/common": "^4.0.0", - "materialize-css": "^0.100.1" - } - }, - "node_modules/angular2-moment": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/angular2-moment/-/angular2-moment-1.9.0.tgz", - "integrity": "sha512-ybPjYizpKVWAI2Z4AqxAS6s3FMkF3+zRpfvxX1wIdSJUFjl83XxQ5f2yn7retX68NSYZZ/JTK9KGnvOzZfrIZw==", - "dependencies": { - "moment": "^2.19.3" - }, - "peerDependencies": { - "@angular/core": ">=2.0.0 <6.0.0" - } - }, "node_modules/ansi-html-community": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", @@ -1468,6 +1538,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1571,12 +1642,6 @@ } ] }, - "node_modules/cash-dom": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/cash-dom/-/cash-dom-8.1.1.tgz", - "integrity": "sha512-aMESow+8m7EuifAeNhpnRHQHN8O24gGeiR53lebD5ShBCisBCoB4y5BBe9pGXtTPP6b1qCp90W9HaaUARyc16Q==", - "dev": true - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1776,7 +1841,8 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "node_modules/connect-history-api-fallback": { "version": "2.0.0", @@ -2754,6 +2820,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3007,6 +3074,18 @@ "node": "^14.13.1 || >=16.0.0" } }, + "node_modules/html-loader/node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -3643,11 +3722,11 @@ } }, "node_modules/magic-string": { - "version": "0.26.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz", - "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", + "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", "dependencies": { - "sourcemap-codec": "^1.4.8" + "@jridgewell/sourcemap-codec": "^1.4.13" }, "engines": { "node": ">=12" @@ -3658,11 +3737,6 @@ "resolved": "https://registry.npmjs.org/material-design-icons/-/material-design-icons-3.0.1.tgz", "integrity": "sha1-mnHEh0chjrylHlGmbaaCA4zct78=" }, - "node_modules/materialize-css": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/materialize-css/-/materialize-css-1.0.0.tgz", - "integrity": "sha512-4/oecXl8y/1i8RDZvyvwAICyqwNoKU4or5uf8uoAd74k76KzZ0Llym4zhJ5lLNUskcqjO0AuMcvNyDkpz8Z6zw==" - }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -3795,6 +3869,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3808,14 +3883,6 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, - "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", - "engines": { - "node": "*" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4124,28 +4191,11 @@ } }, "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "optional": true, + "peer": true }, "node_modules/parseurl": { "version": "1.3.3", @@ -4179,6 +4229,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -4243,9 +4294,9 @@ } }, "node_modules/postcss": { - "version": "8.4.33", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", - "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", + "version": "8.4.34", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.34.tgz", + "integrity": "sha512-4eLTO36woPSocqZ1zIrFD2K1v6wH7pY1uBh0JIM2KKfrVtGvPFiAku6aNOP0W1Wr9qwnaCsF0Z+CrVnryB2A8Q==", "dev": true, "funding": [ { @@ -5078,11 +5129,6 @@ "source-map": "^0.6.0" } }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" - }, "node_modules/spdy": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", @@ -5375,9 +5421,9 @@ } }, "node_modules/typescript": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", - "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", + "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -5875,9 +5921,9 @@ } }, "node_modules/zone.js": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.11.8.tgz", - "integrity": "sha512-82bctBg2hKcEJ21humWIkXRlLBBmrc3nN7DFh5LGGhcyycO2S7FN8NmdvlcKaGFDNVL4/9kFLmwmInTavdJERA==", + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.13.3.tgz", + "integrity": "sha512-MKPbmZie6fASC/ps4dkmIhaT5eonHkEt6eAy80K42tAm0G2W+AahLJjbfi6X9NPdciOE9GRFTTM8u2IiF6O3ww==", "dependencies": { "tslib": "^2.3.0" } @@ -5894,96 +5940,164 @@ } }, "@angular/animations": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-13.2.6.tgz", - "integrity": "sha512-DrjpKo68uR3lSLQQXosoTCbjKQS6IKRCpR14E2t8fo0AX8i2hkB8je4SrhdCyB7FgFN7l2kgUYo4Qa8+BOB+aA==", - "optional": true, + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-15.2.10.tgz", + "integrity": "sha512-yxfN8qQpMaukRU5LjFkJBmy85rqrOp86tYVCsf+hmPEFRiXBMUj6xYLeCMcpk3Mt1JtnWGBR34ivGx+7bNeAow==", "peer": true, "requires": { "tslib": "^2.3.0" } }, + "@angular/cdk": { + "version": "14.2.7", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-14.2.7.tgz", + "integrity": "sha512-/tEsYaUbDSnfEmKVvAMramIptmhI67O+9STjOV0i+74XR2NospeK0fkbywIANu1n3w6AHGMotvRWJrjmbCElFg==", + "peer": true, + "requires": { + "parse5": "^5.0.0", + "tslib": "^2.3.0" + } + }, "@angular/common": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-13.2.6.tgz", - "integrity": "sha512-t4XRb9db4UeRcPs5aHNtGuXRKSvGBlTEr0zzSeoKzHD9TCaO4dSDISh9obS9hThaPuBmPKRUHN5KE1HFmqnSHg==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-15.2.10.tgz", + "integrity": "sha512-jdBn3fctkqoNrJn9VLsUHpcCEhCxWSczdsR+BBbD6T0oLl6vMrAVNjPwfBejnlgfWN1KoRU9kgOYsMxa5apIWQ==", "requires": { "tslib": "^2.3.0" } }, "@angular/compiler": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-13.2.6.tgz", - "integrity": "sha512-LHU29J2/c/03WHkwtzUSElTBsXbzkKdYARodnNfsFdLPsWhyvzO3cqlcZYteFJxEy3dVH+ZrYDjqQ9Sp17aIgA==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-15.2.10.tgz", + "integrity": "sha512-M0XkeU0O73UlJZwDvOyp8/apetz9UKj78eTFDseMYJDLcxe6MpkbkxqpsGZnKYDj7LIep8PmCAKEkhtenE82zw==", "requires": { "tslib": "^2.3.0" } }, "@angular/compiler-cli": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-13.2.6.tgz", - "integrity": "sha512-QtlLKj3m6a2nkewFxhg+a3tQ2gEIBzMfI2c1laWUfAfJJ56phj79k8Z/kf2HQxypphWixyTK+ugpTlMdvvOquA==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-15.2.10.tgz", + "integrity": "sha512-mCFIxrs60XicKfA2o42hA7LrQvhybi9BQveWuZn/2iIEOXx7R62Iemz8E21pLWftAZHGxEW3NECfBrY1d3gVmA==", "requires": { - "@babel/core": "^7.17.2", + "@babel/core": "7.19.3", + "@jridgewell/sourcemap-codec": "^1.4.14", "chokidar": "^3.0.0", "convert-source-map": "^1.5.1", "dependency-graph": "^0.11.0", - "magic-string": "^0.26.0", + "magic-string": "^0.27.0", "reflect-metadata": "^0.1.2", "semver": "^7.0.0", - "sourcemap-codec": "^1.4.8", "tslib": "^2.3.0", "yargs": "^17.2.1" + }, + "dependencies": { + "@babel/core": { + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", + "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.3", + "@babel/helper-compilation-targets": "^7.19.3", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.3", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.3", + "@babel/types": "^7.19.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + } } }, "@angular/core": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-13.2.6.tgz", - "integrity": "sha512-ctWsxuaSO3d3afLW+wkJSyiEIA2uhaTKNps9x5wz/oZJDaUDYVa4PM4x7/UHn2bXzBjXjN9LSW8h9F31iwmcTg==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-15.2.10.tgz", + "integrity": "sha512-meGGidnitQJGDxYd9/LrqYiVlId+vGaLoiLgJdKBz+o2ZO6OmXQGuNw2VBqf17/Cc0/UjzrOY7+kILNFKkk/WQ==", "requires": { "tslib": "^2.3.0" } }, "@angular/forms": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-13.2.6.tgz", - "integrity": "sha512-3IikvNtO0RBiGb2AWl8aYcE3ivXHPIJz+JOn9Wz9XXSkYx75D3GjuJlz+fVIgz+7Q7tJuS6Q2E5qat/ldeDmoA==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-15.2.10.tgz", + "integrity": "sha512-NIntGsNcN6o8L1txsbWXOf6f3K/CUBizdKsxsYVYGJIXEW5qU6UnWmfAZffNNXsT/XvbgUCjgDwT0cAwcqZPuQ==", "requires": { "tslib": "^2.3.0" } }, "@angular/localize": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-13.2.6.tgz", - "integrity": "sha512-QyjOa8ptzLEFTGYTV5aFaEZ5I3fAZUU34P2+Xr9xYNn6Mv8JSoUPVZgaj3SDXxpW75Z6Xgzt841/qDe5/FYm6w==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-15.2.10.tgz", + "integrity": "sha512-RHN+mUR4H34c/LLnNPAyQbfuZME4i9JgodK5YRRX8cSAFPafYLT0SspSuLsKtcCCEDadAZNDHzb8qv5MBtzJtg==", "requires": { - "@babel/core": "7.17.2", - "glob": "7.2.0", + "@babel/core": "7.19.3", + "glob": "8.1.0", "yargs": "^17.2.1" }, "dependencies": { "@babel/core": { - "version": "7.17.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.2.tgz", - "integrity": "sha512-R3VH5G42VSDolRHyUO4V2cfag8WHcZyxdq5Z/m8Xyb92lW/Erm/6kM+XtRFGf3Mulre3mveni2NHfEUws8wSvw==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", + "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", "requires": { - "@ampproject/remapping": "^2.0.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.0", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helpers": "^7.17.2", - "@babel/parser": "^7.17.0", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.0", - "@babel/types": "^7.17.0", + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.3", + "@babel/helper-compilation-targets": "^7.19.3", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.3", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.3", + "@babel/types": "^7.19.3", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", + "json5": "^2.2.1", "semver": "^6.3.0" } }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -5991,26 +6105,34 @@ } } }, + "@angular/material": { + "version": "14.2.7", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-14.2.7.tgz", + "integrity": "sha512-WXHh8pEStpgkXZJmYOg2cI8BSHkV82ET4XTJCNPdveumaCn1UYnaNzsXD13kw5z+zmy8CufhFEzdXTrv/yt7KQ==", + "requires": { + "tslib": "^2.3.0" + } + }, "@angular/platform-browser": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-13.2.6.tgz", - "integrity": "sha512-Gc/1TqysW+P+K3NeQihmHWs4KF1mjJT20s06r+YcETnPP11uPk+UxQl7gJNsDV587DYO/wT3oISXVpRw4UJhdQ==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-15.2.10.tgz", + "integrity": "sha512-9tbgVGSJqwfrOzT8aA/kWBLNhJSQ9gUg0CJxwFBSJm8VkBUJrszoBlDsnSvlxx8/W2ejNULKHFTXeUzq0O/+RQ==", "requires": { "tslib": "^2.3.0" } }, "@angular/platform-browser-dynamic": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-13.2.6.tgz", - "integrity": "sha512-m77+pzwZw+4kiRhxzrj1kE3N1K82I8Xt+vEBKSL2Xv42hCX0T37erC6KlztFEDj4A68s5+/0C5vfwhEiDcr/Cw==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-15.2.10.tgz", + "integrity": "sha512-JHP6W+FX715Qv7DhqvfZLuBZXSDJrboiQsR06gUAgDSjAUyhbqmpVg/2YOtgeWpPkzNDtXdPU2PhcRdIv5J3Yg==", "requires": { "tslib": "^2.3.0" } }, "@angular/router": { - "version": "13.2.6", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-13.2.6.tgz", - "integrity": "sha512-dA9vL4mPLp+iNegzuvm9FaEWirFI2ZK3WQgbdoxoIpneym+BxRTkNDzPcvEaqfUf7eDGRBqlWakFDrd+H2QEbg==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-15.2.10.tgz", + "integrity": "sha512-LmuqEg0iIXSw7bli6HKJ19cbxP91v37GtRwbGKswyLihqzTgvjBYpvcfMnB5FRQ5LWkTwq5JclkX03dZw290Yg==", "requires": { "tslib": "^2.3.0" } @@ -6066,6 +6188,7 @@ "version": "7.23.2", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "peer": true, "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.22.13", @@ -6087,12 +6210,14 @@ "convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "peer": true }, "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "peer": true } } }, @@ -6363,9 +6488,9 @@ "dev": true }, "@ngtools/webpack": { - "version": "13.3.11", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-13.3.11.tgz", - "integrity": "sha512-gB33hTbc/RJmHyIgSUYj8ErPazhYYm7yfapOnvwHdYhCjrj1TKkR1ierOlhJtpfBYUQg6FChdl2YpyIQNPjWMA==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-15.2.10.tgz", + "integrity": "sha512-ZExB4rKh/Saad31O/Ofd2XvRuILuCNTYs0+qJL697Be2pzeewvzBhE4Xe1Mm7Jg13aWSPeuIdzSGOqCdwxxxFQ==", "dev": true, "requires": {} }, @@ -6500,30 +6625,11 @@ "@types/node": "*" } }, - "@types/jquery": { - "version": "3.5.14", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz", - "integrity": "sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg==", - "dev": true, - "requires": { - "@types/sizzle": "*" - } - }, "@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" }, - "@types/materialize-css": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/@types/materialize-css/-/materialize-css-1.0.14.tgz", - "integrity": "sha512-Jt8ReN/R7zrz1TBby0KvyJzAIB9353c1jaFjZt8fIaY/xsalED/8OsFuog1PJ79OuXleRWyJ+MZ8dmjbArXepg==", - "dev": true, - "requires": { - "@types/jquery": "*", - "cash-dom": "*" - } - }, "@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", @@ -6531,9 +6637,9 @@ "dev": true }, "@types/node": { - "version": "20.11.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", - "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", + "version": "20.11.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.0.tgz", + "integrity": "sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==", "requires": { "undici-types": "~5.26.4" } @@ -6575,12 +6681,6 @@ "@types/node": "*" } }, - "@types/sizzle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", - "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", - "dev": true - }, "@types/sockjs": { "version": "0.3.33", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", @@ -6829,20 +6929,6 @@ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "requires": {} }, - "angular2-materialize": { - "version": "15.1.10", - "resolved": "https://registry.npmjs.org/angular2-materialize/-/angular2-materialize-15.1.10.tgz", - "integrity": "sha1-d17LSgs5tXieOkAOYMZ7xIyFNN8=", - "requires": {} - }, - "angular2-moment": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/angular2-moment/-/angular2-moment-1.9.0.tgz", - "integrity": "sha512-ybPjYizpKVWAI2Z4AqxAS6s3FMkF3+zRpfvxX1wIdSJUFjl83XxQ5f2yn7retX68NSYZZ/JTK9KGnvOzZfrIZw==", - "requires": { - "moment": "^2.19.3" - } - }, "ansi-html-community": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", @@ -6978,6 +7064,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7038,12 +7125,6 @@ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001579.tgz", "integrity": "sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==" }, - "cash-dom": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/cash-dom/-/cash-dom-8.1.1.tgz", - "integrity": "sha512-aMESow+8m7EuifAeNhpnRHQHN8O24gGeiR53lebD5ShBCisBCoB4y5BBe9pGXtTPP6b1qCp90W9HaaUARyc16Q==", - "dev": true - }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -7207,7 +7288,8 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "connect-history-api-fallback": { "version": "2.0.0", @@ -7928,6 +8010,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -8111,6 +8194,15 @@ "relateurl": "^0.2.7", "terser": "^5.15.1" } + }, + "parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "requires": { + "entities": "^4.4.0" + } } } }, @@ -8554,11 +8646,11 @@ } }, "magic-string": { - "version": "0.26.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz", - "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", + "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", "requires": { - "sourcemap-codec": "^1.4.8" + "@jridgewell/sourcemap-codec": "^1.4.13" } }, "material-design-icons": { @@ -8566,11 +8658,6 @@ "resolved": "https://registry.npmjs.org/material-design-icons/-/material-design-icons-3.0.1.tgz", "integrity": "sha1-mnHEh0chjrylHlGmbaaCA4zct78=" }, - "materialize-css": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/materialize-css/-/materialize-css-1.0.0.tgz", - "integrity": "sha512-4/oecXl8y/1i8RDZvyvwAICyqwNoKU4or5uf8uoAd74k76KzZ0Llym4zhJ5lLNUskcqjO0AuMcvNyDkpz8Z6zw==" - }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -8663,6 +8750,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -8673,11 +8761,6 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, - "moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" - }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -8904,21 +8987,11 @@ "dev": true }, "parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "requires": { - "entities": "^4.4.0" - }, - "dependencies": { - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true - } - } + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "optional": true, + "peer": true }, "parseurl": { "version": "1.3.3", @@ -8945,7 +9018,8 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-key": { "version": "3.1.1", @@ -8992,9 +9066,9 @@ } }, "postcss": { - "version": "8.4.33", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", - "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", + "version": "8.4.34", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.34.tgz", + "integrity": "sha512-4eLTO36woPSocqZ1zIrFD2K1v6wH7pY1uBh0JIM2KKfrVtGvPFiAku6aNOP0W1Wr9qwnaCsF0Z+CrVnryB2A8Q==", "dev": true, "requires": { "nanoid": "^3.3.7", @@ -9602,11 +9676,6 @@ "source-map": "^0.6.0" } }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" - }, "spdy": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", @@ -9810,9 +9879,9 @@ } }, "typescript": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", - "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==" + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", + "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==" }, "undici-types": { "version": "5.26.5", @@ -10130,9 +10199,9 @@ "dev": true }, "zone.js": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.11.8.tgz", - "integrity": "sha512-82bctBg2hKcEJ21humWIkXRlLBBmrc3nN7DFh5LGGhcyycO2S7FN8NmdvlcKaGFDNVL4/9kFLmwmInTavdJERA==", + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.13.3.tgz", + "integrity": "sha512-MKPbmZie6fASC/ps4dkmIhaT5eonHkEt6eAy80K42tAm0G2W+AahLJjbfi6X9NPdciOE9GRFTTM8u2IiF6O3ww==", "requires": { "tslib": "^2.3.0" } diff --git a/package.json b/package.json index b387dbf7..619a1978 100644 --- a/package.json +++ b/package.json @@ -7,16 +7,15 @@ "i18n": "ng-xi18n -p tsconfig.json" }, "dependencies": { - "@angular/common": "13.2.6", - "@angular/compiler": "13.2.6", - "@angular/core": "13.2.6", - "@angular/forms": "13.2.6", - "@angular/localize": "13.2.6", - "@angular/platform-browser": "13.2.6", - "@angular/platform-browser-dynamic": "13.2.6", - "@angular/router": "13.2.6", - "angular2-materialize": "15.1.10", - "angular2-moment": "1.9.0", + "@angular/common": "15.2.10", + "@angular/compiler": "15.2.10", + "@angular/core": "^15.2.10", + "@angular/forms": "15.2.10", + "@angular/localize": "15.2.10", + "@angular/material": "14.2.7", + "@angular/platform-browser": "15.2.10", + "@angular/platform-browser-dynamic": "15.2.10", + "@angular/router": "15.2.10", "chart.js": "^3.9.1", "chartjs-plugin-annotation": "2.2.1", "core-js": "^3.35.1", @@ -24,18 +23,16 @@ "hammerjs": "^2.0.8", "jquery": "^3.7.1", "material-design-icons": "3.0.1", - "materialize-css": "1.0.0", "ng2-charts": "^3.1.2", "rxjs": "7.8.1", "ts-loader": "^9.5.1", "webpack-node-externals": "^3.0.0", - "zone.js": "~0.11.8" + "zone.js": "~0.13.0" }, "devDependencies": { - "@angular/compiler-cli": "13.2.6", - "@ngtools/webpack": "13.3.11", - "@types/materialize-css": "1.0.14", - "@types/node": "20.11.16", + "@angular/compiler-cli": "15.2.10", + "@ngtools/webpack": "15.2.10", + "@types/node": "20.11.0", "babel-loader": "^9.1.3", "copy-webpack-plugin": "12.0.2", "css-loader": "6.10.0", @@ -47,15 +44,15 @@ "raw-loader": "^4.0.0", "style-loader": "3.3.4", "to-string-loader": "1.2.0", - "typescript": "4.5.5", + "typescript": "4.8.2", "webpack": "^5.90.1", "webpack-cli": "^5.1.4", "webpack-dev-server": "^4.15.1", "webpack-merge": "5.10.0" }, "engines": { - "node": ">= 16.10.0", - "npm": ">= 7.10.0" + "node": ">= 18.19.0", + "npm": ">= 10.2.3" }, "type": "module" } diff --git a/src/angular/app/app.component.html b/src/angular/app/app.component.html index 14b251ef..b441255b 100644 --- a/src/angular/app/app.component.html +++ b/src/angular/app/app.component.html @@ -1,73 +1,43 @@ - - -
-
- -
-
- - +
+ +
+ + diff --git a/src/angular/app/app.component.ts b/src/angular/app/app.component.ts index 9afde86f..bf73e93c 100644 --- a/src/angular/app/app.component.ts +++ b/src/angular/app/app.component.ts @@ -1,4 +1,4 @@ -import {Component, OnInit} from '@angular/core'; +import {Component, OnInit, ViewChild} from '@angular/core'; import {Location} from '@angular/common'; import {AuthService} from './services/auth.service'; import {GraphQLService} from './services/graphql.service'; @@ -8,6 +8,7 @@ import {PageTitleService} from './services/page-title.service'; import {UserProfileService} from './services/user-profile.service'; import {Player} from '../graphql/schemas/Player'; import { filter } from 'rxjs'; +import { MatSidenav } from '@angular/material/sidenav'; @Component({ selector: 'office-league', @@ -15,8 +16,11 @@ import { filter } from 'rxjs'; styleUrls: ['app.component.less'] }) export class AppComponent implements OnInit { + @ViewChild('sidenav') sidenav: MatSidenav; + private static DEFAULT_TITLE = 'Office League'; + sidenavOpened: boolean = false; logoUrl: string; isPlayingGame: boolean; playerImage: string; @@ -55,21 +59,9 @@ export class AppComponent implements OnInit { }); } - ngAfterViewInit(): void { - this.initSidenav(); - this.initUserDropdown(); - } - - initSidenav(): void { - const elems = document.querySelectorAll('.sidenav'); - M.Sidenav.init(elems, { - edge: 'right' - }); - } - - initUserDropdown(): void { - const elems = document.querySelectorAll('.dropdown-trigger'); - M.Dropdown.init(elems); + toggleSidenav(): void { + this.sidenav.toggle(); + this.sidenavOpened = !this.sidenavOpened; } ngOnInit(): void { @@ -102,8 +94,7 @@ export class AppComponent implements OnInit { this.playerName = player.name; this.isNewUser = false; this.isAuthenticated = true; - this.displayMenu = false; - setTimeout(() => this.displayMenu = true, 100); // hack to force refresh materialize SideNav menu + this.displayMenu = true; } else { this.playerImage = ImageService.playerDefault(); this.playerName = ''; diff --git a/src/angular/app/app.module.ts b/src/angular/app/app.module.ts index 608cc19b..50700a9d 100644 --- a/src/angular/app/app.module.ts +++ b/src/angular/app/app.module.ts @@ -24,7 +24,12 @@ import {UserProfileService} from './services/user-profile.service'; import {WindowRefService} from './services/window-ref.service'; import {AudioService} from './services/audio.service'; import {PushNotificationService} from './services/push-notification.sevice'; -import { MaterializeModule } from 'angular2-materialize'; +import { MatSidenavModule } from '@angular/material/sidenav'; +import { MatToolbarModule } from '@angular/material/toolbar'; +import { MatListModule } from '@angular/material/list'; +import { MatIconModule } from '@angular/material/icon'; +import { MatButtonModule } from '@angular/material/button'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; const appRoutes: Routes = [ {path: '**', redirectTo: '', pathMatch: 'full'} @@ -35,8 +40,8 @@ const appRoutes: Routes = [ AppComponent ], imports: [ + BrowserAnimationsModule, CommonModule, - MaterializeModule, RouterModule.forRoot(appRoutes), FormsModule, HttpClientModule, @@ -44,7 +49,12 @@ const appRoutes: Routes = [ GamesModule, TeamsModule, LeaguesModule, - InfoPageModule + InfoPageModule, + MatSidenavModule, + MatToolbarModule, + MatListModule, + MatIconModule, + MatButtonModule, ], providers: [GraphQLService, AuthService, CryptoService, PageTitleService, AuthenticatedRouteGuard, PlayerRouteGuard, EditRouteGuard, OfflinePersistenceService, OnlineStatusService, RankingService, UserProfileService, WindowRefService, AudioService, @@ -57,4 +67,4 @@ const appRoutes: Routes = [ bootstrap: [AppComponent] }) export class AppModule { -} \ No newline at end of file +} diff --git a/src/angular/app/common/chips/chips.component.html b/src/angular/app/common/chips/chips.component.html index 94a8c543..8b1dea76 100644 --- a/src/angular/app/common/chips/chips.component.html +++ b/src/angular/app/common/chips/chips.component.html @@ -1 +1,11 @@ -
+ + + {{tag}} + cancel + + + diff --git a/src/angular/app/common/chips/chips.component.ts b/src/angular/app/common/chips/chips.component.ts index 0b07bdbd..f20147db 100644 --- a/src/angular/app/common/chips/chips.component.ts +++ b/src/angular/app/common/chips/chips.component.ts @@ -1,74 +1,46 @@ -import {Component, Input, Output, OnChanges, AfterViewInit, SimpleChanges, SimpleChange, EventEmitter, ElementRef, ViewChild} from '@angular/core'; -import {Router, ActivatedRoute} from '@angular/router'; -import {BaseComponent} from '../base.component'; -declare var $: any; +import { Component, Input, Output, EventEmitter, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; +import { MatChipInputEvent } from '@angular/material/chips'; +import { COMMA, ENTER } from '@angular/cdk/keycodes'; @Component({ - selector: 'chips', + selector: 'app-chips', templateUrl: 'chips.component.html', styleUrls: ['chips.component.less'] }) -export class ChipsComponent extends BaseComponent implements AfterViewInit { - +export class ChipsComponent implements AfterViewInit { @Input() availableTags: string[]; @Input() excludedTags: string[] = []; @Input() selectedTags: string[] = []; @Input() placeholder: string; - @ViewChild ('div') div; - - constructor(route: ActivatedRoute) { - super(route); - } - - ngOnInit() : void { - super.ngOnInit(); - } + @ViewChild('chipList') chipList: ElementRef; - ngAfterViewInit(): void { - this.refreshChips(); - } + readonly separatorKeysCodes: number[] = [ENTER, COMMA]; - ngOnChanges(changes: SimpleChanges): void { - super.ngOnChanges(changes); - if (changes['availableTags'] || changes['selectedTags']) { - this.refreshChips(); - } - } + constructor() {} - focus() { - if (this.div) { - this.div.nativeElement.children[0].focus(); - } - } - - refreshChips(): void { - let autocompleteData = {}; - this.availableTags.filter((tag) => this.excludedTags.indexOf(tag) == -1 ). - forEach((tag) => autocompleteData[tag] = null); + ngAfterViewInit(): void {} - const chips = document.querySelectorAll('.chips'); - M.Chips.init(chips, { - autocompleteOptions: { - data: autocompleteData, - limit: Infinity, - minLength: 1 - }, - placeholder: this.placeholder, - secondaryPlaceholder: this.placeholder - }); - } + add(event: MatChipInputEvent): void { + const input = event.input; + const value = event.value; - add(chip) { - this.selectedTags.push(chip.tag); - } + // Add our tag + if ((value || '').trim()) { + if (this.availableTags.includes(value.trim()) && !this.excludedTags.includes(value.trim())) { + this.selectedTags.push(value.trim()); + } + } - delete(chip) { - let deleteIndex = this.selectedTags.indexOf(chip.tag); - if (deleteIndex > -1) { - this.selectedTags.splice(deleteIndex, 1); + // Reset the input value + if (input) { + input.value = ''; } } - select(chip) { + delete(tag: string): void { + const index = this.selectedTags.indexOf(tag); + if (index >= 0) { + this.selectedTags.splice(index, 1); + } } } diff --git a/src/angular/app/common/common.module.ts b/src/angular/app/common/common.module.ts index 923eb2d5..6d9fb1cb 100644 --- a/src/angular/app/common/common.module.ts +++ b/src/angular/app/common/common.module.ts @@ -15,8 +15,9 @@ import {PlayerSelectComponent} from './player-select/player-select.component'; import {ChipsComponent} from './chips/chips.component'; import {ReactiveFormsModule} from "@angular/forms"; import {ConnectionErrorComponent} from './connection-error/connection-error.component'; -import { MaterializeModule } from 'angular2-materialize'; - +import { MatSnackBarModule } from '@angular/material/snack-bar'; +import { MatChipsModule } from '@angular/material/chips'; +import { MatIconModule } from '@angular/material/icon'; @NgModule({ declarations: [ @@ -36,9 +37,12 @@ import { MaterializeModule } from 'angular2-materialize'; ], imports: [ BrowserModule, - MaterializeModule, + //MaterializeModule, + MatSnackBarModule, FormsModule, - ReactiveFormsModule + ReactiveFormsModule, + MatChipsModule, + MatIconModule ], exports: [ BrowserModule, @@ -55,7 +59,7 @@ import { MaterializeModule } from 'angular2-materialize'; LoadingComponent, ConnectionErrorComponent, PlayerSelectComponent, - ChipsComponent, + ChipsComponent ] }) export class CommonModule { diff --git a/src/angular/app/common/global.errorhandler.ts b/src/angular/app/common/global.errorhandler.ts index c4be04bc..c41f530b 100644 --- a/src/angular/app/common/global.errorhandler.ts +++ b/src/angular/app/common/global.errorhandler.ts @@ -1,15 +1,20 @@ -import {ErrorHandler, Injectable} from '@angular/core'; -import {toast} from 'angular2-materialize'; +import { ErrorHandler, Injectable } from '@angular/core'; +import { MatSnackBar } from '@angular/material/snack-bar'; @Injectable() export class GlobalErrorHandler implements ErrorHandler { + constructor(private snackBar: MatSnackBar) {} handleError(error) { console.error('Global error handler showing toast for: ' + error?.toString(), error); - toast(`error_outline

Oops! Something went wrong!

`, 3000, 'error'); + + // Using Angular Material SnackBar instead of Materialize toast + this.snackBar.open('Oops! Something went wrong!', 'Error', { + duration: 3000, + panelClass: ['mat-toolbar', 'mat-warn'] + }); // IMPORTANT: Rethrow the error otherwise it gets swallowed //throw error; } - } diff --git a/src/angular/app/common/player-select/player-select.component.ts b/src/angular/app/common/player-select/player-select.component.ts index 17fd1e1c..3f035202 100644 --- a/src/angular/app/common/player-select/player-select.component.ts +++ b/src/angular/app/common/player-select/player-select.component.ts @@ -16,7 +16,6 @@ import {GraphQLService} from '../../services/graphql.service'; export class PlayerSelectComponent extends List2Component { @Input() playerIds: string[]; @Input() excludedPlayerIds: string[] = []; - @Input() materializeActions: EventEmitter = new EventEmitter(); @Output() playerSelected: EventEmitter = new EventEmitter(); allPlayers: Player[] = []; players: Player[] = []; @@ -30,18 +29,9 @@ export class PlayerSelectComponent extends List2Component { ngOnInit(): void { super.ngOnInit(); this.searchValue = ''; - if (this.materializeActions) { - this.materializeActions.subscribe((materialAction: any) => { - if (materialAction.params && materialAction.params[0] === 'open') { - this.searchValue = ''; - this.onSearchFieldModified(); - } - }); - } this.observer = this; } - ngOnChanges(changes: SimpleChanges): void { let playerIdsChange = changes['playerIds']; let excludedPlayerIdsChange = changes['excludedPlayerIds']; @@ -113,10 +103,6 @@ export class PlayerSelectComponent extends List2Component { this.notifySelected(); } - private refresh(currentPage: number = 1, searchValue: string = '') { - this.filterPlayers(searchValue); - } - static readonly GetPlayersQuery = `query ($playerIds: [ID], $first:Int) { players(ids: $playerIds, first: $first) { id diff --git a/src/angular/app/games/game-comment-dialog/game-comment-dialog.component.html b/src/angular/app/games/game-comment-dialog/game-comment-dialog.component.html new file mode 100644 index 00000000..d83499af --- /dev/null +++ b/src/angular/app/games/game-comment-dialog/game-comment-dialog.component.html @@ -0,0 +1,11 @@ + +
Game comment
+ + + +
+ + + + + diff --git a/src/angular/app/games/game-comment-dialog/game-comment-dialog.component.ts b/src/angular/app/games/game-comment-dialog/game-comment-dialog.component.ts new file mode 100644 index 00000000..e6ddf3d5 --- /dev/null +++ b/src/angular/app/games/game-comment-dialog/game-comment-dialog.component.ts @@ -0,0 +1,15 @@ +import { Component, EventEmitter, Output } from '@angular/core'; + +@Component({ + selector: 'game-comment-dialog', + templateUrl: 'game-comment-dialog.component.html' +}) +export class GameCommentDialogComponent { + comment: string; + + @Output() commentSubmitted = new EventEmitter(); + + onCommentDoneClicked(): void { + this.commentSubmitted.emit(this.comment); + } +} diff --git a/src/angular/app/games/game-continue-dialog/game-continue-dialog.component.html b/src/angular/app/games/game-continue-dialog/game-continue-dialog.component.html new file mode 100644 index 00000000..a364f2db --- /dev/null +++ b/src/angular/app/games/game-continue-dialog/game-continue-dialog.component.html @@ -0,0 +1,8 @@ + +
Game in progress
+

This game is not finished. Would you like to continue playing?

+
+ + + + diff --git a/src/angular/app/games/game-continue-dialog/game-continue-dialog.component.ts b/src/angular/app/games/game-continue-dialog/game-continue-dialog.component.ts new file mode 100644 index 00000000..35b2fc51 --- /dev/null +++ b/src/angular/app/games/game-continue-dialog/game-continue-dialog.component.ts @@ -0,0 +1,15 @@ +import { Component, EventEmitter, Output } from '@angular/core'; + +@Component({ + selector: 'game-continue-dialog', + templateUrl: 'game-continue-dialog.component.html' +}) +export class GameContinueDialogComponent { + @Output() continueConfirmed = new EventEmitter(); + + constructor() {} + + onConfirmContinueClicked() { + this.continueConfirmed.emit(); + } +} diff --git a/src/angular/app/games/game-delete-dialog/game-delete-dialog.component.html b/src/angular/app/games/game-delete-dialog/game-delete-dialog.component.html new file mode 100644 index 00000000..620db508 --- /dev/null +++ b/src/angular/app/games/game-delete-dialog/game-delete-dialog.component.html @@ -0,0 +1,8 @@ + +
Delete game
+

You are about to permanently delete this game. This operation cannot be undone.

+
+ + + + diff --git a/src/angular/app/games/game-delete-dialog/game-delete-dialog.component.ts b/src/angular/app/games/game-delete-dialog/game-delete-dialog.component.ts new file mode 100644 index 00000000..9d5d06dd --- /dev/null +++ b/src/angular/app/games/game-delete-dialog/game-delete-dialog.component.ts @@ -0,0 +1,15 @@ +import { Component, EventEmitter, Output } from '@angular/core'; + +@Component({ + selector: 'game-delete-dialog', + templateUrl: 'game-delete-dialog.component.html' +}) +export class GameDeleteDialogComponent { + @Output() deleteConfirmed = new EventEmitter(); + + constructor() {} + + onConfirmDeleteClicked() { + this.deleteConfirmed.emit(); + } +} diff --git a/src/angular/app/games/game-profile/game-profile.component.html b/src/angular/app/games/game-profile/game-profile.component.html index 1bec3bd6..c01226d4 100644 --- a/src/angular/app/games/game-profile/game-profile.component.html +++ b/src/angular/app/games/game-profile/game-profile.component.html @@ -8,16 +8,16 @@
- {{game.time | amCalendar:{lastDay: '[Yesterday at] HH:mm', sameDay: '[Today at] HH:mm', nextDay : '[Tomorrow at] HH:mm', lastWeek : '[last] dddd [at] HH:mm', nextWeek : 'dddd [at] HH:mm', sameElse : 'll HH:mm'} }} + {{ formattedDate }}
+ -
@@ -34,39 +34,18 @@
- - + + + - + + + - \ No newline at end of file + + + + diff --git a/src/angular/app/games/game-profile/game-profile.component.less b/src/angular/app/games/game-profile/game-profile.component.less index 4a2cbce9..2c5a0a44 100644 --- a/src/angular/app/games/game-profile/game-profile.component.less +++ b/src/angular/app/games/game-profile/game-profile.component.less @@ -11,21 +11,8 @@ padding: 0 0 20px; } -textarea.materialize-textarea:focus:not([readonly]) { - border-left: 0; -} - -textarea.materialize-textarea:focus { - border-bottom: 1px solid #0091ea; - box-shadow: 0 1px 0 0 #0091ea; -} - -textarea.materialize-textarea:focus + label { - color: #0091ea; -} - .fixed-action-btn { ul.game-profile__btn-menu { bottom: 40px; } -} \ No newline at end of file +} diff --git a/src/angular/app/games/game-profile/game-profile.component.ts b/src/angular/app/games/game-profile/game-profile.component.ts index 34732930..c8f61167 100644 --- a/src/angular/app/games/game-profile/game-profile.component.ts +++ b/src/angular/app/games/game-profile/game-profile.component.ts @@ -1,4 +1,8 @@ -import {Component, EventEmitter, OnDestroy, ViewChild} from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { GameCommentDialogComponent } from '../game-comment-dialog/game-comment-dialog.component'; // adjust the path as necessary +import { GameDeleteDialogComponent } from '../game-delete-dialog/game-delete-dialog.component'; // adjust the path as necessary +import { GameContinueDialogComponent } from '../game-continue-dialog/game-continue-dialog.component'; // adjust the path as necessary +import {Component, OnDestroy, ViewChild} from '@angular/core'; import {GraphQLService} from '../../services/graphql.service'; import {ActivatedRoute, Router} from '@angular/router'; import {GameComponent} from '../game/game.component'; @@ -11,34 +15,42 @@ import {OnlineStatusService} from '../../services/online-status.service'; import {EventType, RemoteEvent} from '../../../graphql/schemas/RemoteEvent'; import {WebSocketManager} from '../../services/websocket.manager'; import { Config } from '../../app.config'; +import { DatePipe } from '@angular/common'; declare var XPCONFIG: Config; @Component({ selector: 'game-profile', templateUrl: 'game-profile.component.html', - styleUrls: ['game-profile.component.less'] + styleUrls: ['game-profile.component.less'], + providers: [DatePipe] }) export class GameProfileComponent extends GameComponent implements OnDestroy { - materializeActions = new EventEmitter(); - materializeActionsDelete = new EventEmitter(); - materializeActionsContinue = new EventEmitter(); @ViewChild('commenttextarea') commentsTextAreaElementRef; comment: string; playerId: string; deletable: boolean; connectionError: boolean; - private online: boolean; + formattedDate: string; + online: boolean; private onlineStateCallback = () => this.online = navigator.onLine; private gameId: string; private wsMan: WebSocketManager; - constructor(protected graphQLService: GraphQLService, protected route: ActivatedRoute, protected router: Router, - private authService: AuthService, private pageTitleService: PageTitleService, - protected offlineService: OfflinePersistenceService, private onlineStatusService: OnlineStatusService) { + constructor( + protected graphQLService: GraphQLService, + protected route: ActivatedRoute, + protected router: Router, + private authService: AuthService, + private pageTitleService: PageTitleService, + protected offlineService: OfflinePersistenceService, + private onlineStatusService: OnlineStatusService, + private dialog: MatDialog, // Inject MatDialog + private datePipe: DatePipe + ) { super(graphQLService, route, router, offlineService); } @@ -55,15 +67,25 @@ export class GameProfileComponent this.wsMan = new WebSocketManager(this.getWsUrl(this.gameId)); this.wsMan.onMessage(this.onWsMessage.bind(this)); + this.formatGameTime(); } - ngAfterViewInit(): void { - setTimeout(() => this.initFloatingButtons(), 500); - } + formatGameTime() { + const now = new Date(); + const gameDate = new Date(this.game.time); // assuming this.game.time is a date compatible string or a timestamp + + const diffInDays = (now.getTime() - gameDate.getTime()) / (1000 * 3600 * 24); - initFloatingButtons(): void { - const buttons = document.querySelectorAll('.fixed-action-btn'); - M.FloatingActionButton.init(buttons); + if (diffInDays < 1 && now.getDate() === gameDate.getDate()) { + this.formattedDate = `Today at ${this.datePipe.transform(gameDate, 'HH:mm')}`; + } else if (diffInDays < 2 && now.getDate() - gameDate.getDate() === 1) { + this.formattedDate = `Yesterday at ${this.datePipe.transform(gameDate, 'HH:mm')}`; + } else if (diffInDays > -1 && now.getDate() - gameDate.getDate() === -1) { + this.formattedDate = `Tomorrow at ${this.datePipe.transform(gameDate, 'HH:mm')}`; + } else { + this.formattedDate = this.datePipe.transform(gameDate, 'EEEE [at] HH:mm'); // EEEE will give you the full name of the day + } + // Add more conditions for lastWeek, nextWeek, sameElse as per your requirement } ngOnDestroy(): void { @@ -98,7 +120,7 @@ export class GameProfileComponent const userInGame = (game.gamePlayers || []).find((gp) => gp.player.id === this.playerId); if (userInGame && !game.finished) { - this.showModalContinuePlaying(); + this.onConfirmContinueClicked(); } } @@ -114,30 +136,17 @@ export class GameProfileComponent this.connectionError = true; } - onCommentClicked() { - this.comment = ''; - this.showModalMessage(); - // TODO: fix this. - // setTimeout(_ => - // this._renderer.invokeElementMethod( - // this.commentsTextAreaElementRef.nativeElement, 'focus', []), 0); - } - - onCommentDoneClicked() { - this.comment = this.comment.trim(); + onCommentDoneClicked(comment: string) { + this.comment = comment.trim(); this.comment = this.comment.replace(/^\s+|\s+$/g, '');// trim line breaks if (this.comment) { this.createComment(this.comment).then((comment) => { - this.hideModalMessage(); + // TODO: Hide Comment Modal Component super.loadGame(this.gameId); }); } } - onDeleteClicked() { - this.showModalDelete(); - } - onConfirmDeleteClicked() { this.deleteGame().then((deleted) => { if (deleted) { @@ -149,32 +158,45 @@ export class GameProfileComponent } }); } - onConfirmContinueClicked() { - this.router.navigate(['games', this.game.league.id, 'game-play'], {replaceUrl: true, queryParams: {gameId: this.gameId}}); - } - public showModalMessage(): void { - this.materializeActions.emit({action: "modal", params: ['open']}); - } + onCommentClicked() { + this.comment = ''; + const dialogRef = this.dialog.open(GameCommentDialogComponent, { + width: '250px', + data: { comment: this.comment } + }); - public hideModalMessage(): void { - this.materializeActions.emit({action: "modal", params: ['close']}); + dialogRef.afterClosed().subscribe(result => { + console.log('The comment dialog was closed'); + this.comment = result; + this.onCommentDoneClicked(this.comment); + }); } - public showModalDelete(): void { - this.materializeActionsDelete.emit({action: "modal", params: ['open']}); - } + onDeleteClicked() { + const dialogRef = this.dialog.open(GameDeleteDialogComponent, { + width: '250px' + }); - public hideModalDelete(): void { - this.materializeActionsDelete.emit({action: "modal", params: ['close']}); + dialogRef.afterClosed().subscribe(result => { + console.log('The delete dialog was closed'); + if (result === true) { + this.onConfirmDeleteClicked(); + } + }); } - public showModalContinuePlaying(): void { - this.materializeActionsContinue.emit({action: "modal", params: ['open']}); - } + onConfirmContinueClicked() { + const dialogRef = this.dialog.open(GameContinueDialogComponent, { + width: '250px' + }); - public hideModalContinuePlaying(): void { - this.materializeActionsContinue.emit({action: "modal", params: ['close']}); + dialogRef.afterClosed().subscribe(result => { + console.log('The continue dialog was closed'); + if (result === true) { + this.router.navigate(['games', this.game.league.id, 'game-play'], {replaceUrl: true, queryParams: {gameId: this.gameId}}); + } + }); } onWsMessage(event: RemoteEvent) { diff --git a/src/angular/app/games/games.module.ts b/src/angular/app/games/games.module.ts index 4ef3d275..16b7d800 100644 --- a/src/angular/app/games/games.module.ts +++ b/src/angular/app/games/games.module.ts @@ -15,8 +15,15 @@ import {NgChartsModule} from 'ng2-charts'; import {GameFlowComponent} from './game-flow/game-flow.component'; import {GameSelection} from './GameSelection'; import {RatingPointsComponent} from './rating-points/rating-points.component'; -import {MomentModule} from 'angular2-moment' -import { MaterializeModule } from 'angular2-materialize'; +import { MatDialogModule } from '@angular/material/dialog'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatButtonModule } from '@angular/material/button'; +import { MatInputModule } from "@angular/material/input"; +import {PlayerSelectDialogComponent} from './player-select-dialog/player-select-dialog.component'; +import {NgOptimizedImage} from '@angular/common'; +import {GameCommentDialogComponent} from './game-comment-dialog/game-comment-dialog.component'; +import {GameDeleteDialogComponent} from './game-delete-dialog/game-delete-dialog.component'; +import {GameContinueDialogComponent} from './game-continue-dialog/game-continue-dialog.component'; const gameRoutes: Routes = [ {path: 'games', component: GameListPageComponent, canActivate: [PlayerRouteGuard]}, @@ -39,15 +46,23 @@ const gameRoutes: Routes = [ GamePlayComponent, GamePointsComponent, GameFlowComponent, - RatingPointsComponent + RatingPointsComponent, + PlayerSelectDialogComponent, + GameCommentDialogComponent, + GameDeleteDialogComponent, + GameContinueDialogComponent ], imports: [ CommonModule, - MaterializeModule, RouterModule.forChild(gameRoutes), FormsModule, NgChartsModule, - MomentModule + //MomentModule + MatDialogModule, + MatFormFieldModule, + MatButtonModule, + MatInputModule, + NgOptimizedImage ], exports: [GameListComponent], providers: [GameSelection], diff --git a/src/angular/app/games/new-game-player/new-game-player.component.html b/src/angular/app/games/new-game-player/new-game-player.component.html index 095f551e..765855db 100644 --- a/src/angular/app/games/new-game-player/new-game-player.component.html +++ b/src/angular/app/games/new-game-player/new-game-player.component.html @@ -1,22 +1,15 @@
-
+
Select a player Select a player
-
+
{{player.name}} {{player.name}}
- -
\ No newline at end of file +
diff --git a/src/angular/app/games/new-game-player/new-game-player.component.less b/src/angular/app/games/new-game-player/new-game-player.component.less index 33e51c00..a803287f 100644 --- a/src/angular/app/games/new-game-player/new-game-player.component.less +++ b/src/angular/app/games/new-game-player/new-game-player.component.less @@ -40,7 +40,7 @@ text-overflow: ellipsis; } - .modal.player-select-modal.open { + .modal.player-select-dialog.open { max-height: 80%; width: 90%; } @@ -63,7 +63,7 @@ } -.player-select-modal { +.player-select-dialog { //TODO Why the overflow hidden? overflow-y: hidden; }*/ diff --git a/src/angular/app/games/new-game-player/new-game-player.component.ts b/src/angular/app/games/new-game-player/new-game-player.component.ts index b4d5a6f8..3719ce53 100644 --- a/src/angular/app/games/new-game-player/new-game-player.component.ts +++ b/src/angular/app/games/new-game-player/new-game-player.component.ts @@ -1,7 +1,8 @@ import {Component, Input, Output, EventEmitter, ElementRef} from '@angular/core'; import {Player} from '../../../graphql/schemas/Player'; import { Config } from '../../app.config'; -import {MaterializeAction} from 'angular2-materialize'; +import { MatDialog } from '@angular/material/dialog'; +import {PlayerSelectDialogComponent} from '../player-select-dialog/player-select-dialog.component'; declare var XPCONFIG: Config; @@ -11,8 +12,6 @@ declare var XPCONFIG: Config; styleUrls: ['new-game-player.component.less'] }) export class NewGamePlayerComponent { - materializeActions = new EventEmitter(); - @Input() player: Player; @Input() leaguePlayerIds: string[]; @Input() selectedPlayerIds: string[]; @@ -20,35 +19,28 @@ export class NewGamePlayerComponent { @Output() playerSelected: EventEmitter = new EventEmitter(); playerSelectEnabled: boolean; - public modalTitle: string = 'Select a player'; - constructor(private el: ElementRef) { - } + constructor(private dialog: MatDialog) {} - public setPlayer(player: Player) { - this.player = player; - this.playerSelected.emit(player); - } - - onClicked() { + onNewPlayerClicked() { this.showModal(); } - onSelected(p: Player) { - if (p) { - this.hideModal(); - this.playerSelected.emit(p); - } - } - public showModal(): void { - this.materializeActions.emit({action: "modal", params: ['open']}); - this.playerSelectEnabled = true; - } + const dialogRef = this.dialog.open(PlayerSelectDialogComponent, { + width: '250px', + data: { + leaguePlayerIds: this.leaguePlayerIds, + selectedPlayerIds: this.selectedPlayerIds + } + }); + + dialogRef.afterClosed().subscribe(player => { + this.playerSelectEnabled = false; + this.playerSelected.emit(player); + }); - public hideModal(): void { - this.playerSelectEnabled = false; - this.materializeActions.emit({action: "modal", params: ['close']}); + this.playerSelectEnabled = true; } questionMarkImg(): string { diff --git a/src/angular/app/games/player-select-dialog/player-select-dialog.component.html b/src/angular/app/games/player-select-dialog/player-select-dialog.component.html new file mode 100644 index 00000000..1a251a82 --- /dev/null +++ b/src/angular/app/games/player-select-dialog/player-select-dialog.component.html @@ -0,0 +1,5 @@ + diff --git a/src/angular/app/games/player-select-dialog/player-select-dialog.component.ts b/src/angular/app/games/player-select-dialog/player-select-dialog.component.ts new file mode 100644 index 00000000..8b305421 --- /dev/null +++ b/src/angular/app/games/player-select-dialog/player-select-dialog.component.ts @@ -0,0 +1,18 @@ +import { Component, Inject } from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {Player} from '../../../graphql/schemas/Player'; + +@Component({ + selector: 'app-player-select-dialog', + templateUrl: 'player-select-dialog.component.html', +}) +export class PlayerSelectDialogComponent { + constructor( + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any + ) {} + + onPlayerSelected(player: any) { + this.dialogRef.close(player); + } +} diff --git a/src/angular/app/info-page/info-page.module.ts b/src/angular/app/info-page/info-page.module.ts index 15cb18c8..6ac5f7b4 100644 --- a/src/angular/app/info-page/info-page.module.ts +++ b/src/angular/app/info-page/info-page.module.ts @@ -4,7 +4,6 @@ import {CommonModule} from '../common/common.module'; import {InfoPageComponent} from './info-page.component'; import {FormsModule} from '@angular/forms'; import {PlayerRouteGuard, } from '../guards/player.route.guard'; -import { MaterializeModule } from 'angular2-materialize'; const pageInfoRoutes: Routes = [ {path: ':info-page', component: InfoPageComponent, canActivate: [PlayerRouteGuard,]} @@ -16,7 +15,6 @@ const pageInfoRoutes: Routes = [ ], imports: [ CommonModule, - MaterializeModule, RouterModule.forChild(pageInfoRoutes), FormsModule ], diff --git a/src/angular/app/leagues/add-players-dialog/add-players-dialog.component.html b/src/angular/app/leagues/add-players-dialog/add-players-dialog.component.html new file mode 100644 index 00000000..bae9a52e --- /dev/null +++ b/src/angular/app/leagues/add-players-dialog/add-players-dialog.component.html @@ -0,0 +1,7 @@ + +
Add players to league
+ +
+ + + diff --git a/src/angular/app/leagues/add-players-dialog/add-players-dialog.component.ts b/src/angular/app/leagues/add-players-dialog/add-players-dialog.component.ts new file mode 100644 index 00000000..6ceb2ece --- /dev/null +++ b/src/angular/app/leagues/add-players-dialog/add-players-dialog.component.ts @@ -0,0 +1,24 @@ +import {Component, Inject, ViewChild} from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +export interface AddPlayersDialogData { + playerNamesToAdd: string[]; + nonMembersPlayerNames: string[]; +} + +@Component({ + templateUrl: './add-players-dialog.component.html', +}) + +export class AddPlayersDialogComponent { + @ViewChild('addPlayerChips') addPlayerChipsViewChild: any; + + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: AddPlayersDialogData + ) {} + + onPlayersAdded(): void { + this.dialogRef.close(this.data.playerNamesToAdd); + } +} diff --git a/src/angular/app/leagues/admin-select-dialog/admin-select-dialog.component.html b/src/angular/app/leagues/admin-select-dialog/admin-select-dialog.component.html new file mode 100644 index 00000000..b8db071a --- /dev/null +++ b/src/angular/app/leagues/admin-select-dialog/admin-select-dialog.component.html @@ -0,0 +1,5 @@ + diff --git a/src/angular/app/leagues/admin-select-dialog/admin-select-dialog.component.ts b/src/angular/app/leagues/admin-select-dialog/admin-select-dialog.component.ts new file mode 100644 index 00000000..2cc1c4ba --- /dev/null +++ b/src/angular/app/leagues/admin-select-dialog/admin-select-dialog.component.ts @@ -0,0 +1,19 @@ +import { Component, Inject } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { Player } from '../../../graphql/schemas/Player'; // Adjust the path as needed + +@Component({ + selector: 'app-admin-select-dialog', + templateUrl: './admin-select-dialog.component.html', +}) +export class AdminSelectDialogComponent { + constructor( + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any + ) {} + + onAdminSelected(player: Player) { + // Close the dialog and return the selected player + this.dialogRef.close(player); + } +} diff --git a/src/angular/app/leagues/join-league-request-dialog/join-league-request-dialog.component.html b/src/angular/app/leagues/join-league-request-dialog/join-league-request-dialog.component.html new file mode 100644 index 00000000..69ef67c6 --- /dev/null +++ b/src/angular/app/leagues/join-league-request-dialog/join-league-request-dialog.component.html @@ -0,0 +1,9 @@ +

Join League Request

+ +

Player '{{data.playerName}}' has requested to join this league ({{data.leagueName}}).

+
+ + + + + diff --git a/src/angular/app/leagues/join-league-request-dialog/join-league-request-dialog.component.ts b/src/angular/app/leagues/join-league-request-dialog/join-league-request-dialog.component.ts new file mode 100644 index 00000000..ef402832 --- /dev/null +++ b/src/angular/app/leagues/join-league-request-dialog/join-league-request-dialog.component.ts @@ -0,0 +1,21 @@ +import { Component, Inject } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +export interface JoinLeagueRequestDialogData { + playerName: string; + leagueName: string; +} + +@Component({ + templateUrl: './join-league-request-dialog.component.html' +}) +export class JoinLeagueRequestDialogComponent { + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: JoinLeagueRequestDialogData + ) {} + + onConfirmJoin(allow: boolean): void { + this.dialogRef.close(allow); + } +} diff --git a/src/angular/app/leagues/league-browser/league-browser.component.html b/src/angular/app/leagues/league-browser/league-browser.component.html index 3e036c57..d07e8689 100644 --- a/src/angular/app/leagues/league-browser/league-browser.component.html +++ b/src/angular/app/leagues/league-browser/league-browser.component.html @@ -1,16 +1,15 @@
- - - + + + + + + + +
- add +
diff --git a/src/angular/app/leagues/league-browser/league-browser.component.ts b/src/angular/app/leagues/league-browser/league-browser.component.ts index 62185055..0b6ee159 100644 --- a/src/angular/app/leagues/league-browser/league-browser.component.ts +++ b/src/angular/app/leagues/league-browser/league-browser.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, ElementRef, AfterViewInit} from '@angular/core'; +import {Component, Input, OnDestroy, ViewChild} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import {ConfigUser} from '../../app.config'; import {GraphQLService} from '../../services/graphql.service'; @@ -7,44 +7,25 @@ import {OnlineStatusService} from '../../services/online-status.service'; import {League} from '../../../graphql/schemas/League'; import {BaseComponent} from '../../common/base.component'; import {PageTitleService} from '../../services/page-title.service'; +import {MatTabGroup} from '@angular/material/tabs'; @Component({ selector: 'league-browser', templateUrl: 'league-browser.component.html', styleUrls: ['league-browser.component.less'] }) -export class LeagueBrowserComponent extends BaseComponent implements AfterViewInit { - - private static readonly getLeaguesQuery: string = `query($playerId: ID, $leagueCount: Int) { - myLeagues : leagues(playerId:$playerId, first: $leagueCount){ - id - name - imageUrl - description - } - - allLeagues: leagues(first: $leagueCount){ - id - name - imageUrl - description - games(first:1 , finished:true) { - id - time - } - } - }`; +export class LeagueBrowserComponent extends BaseComponent implements OnDestroy { + @ViewChild(MatTabGroup) tabGroup: MatTabGroup; @Input() myLeagues: League[] = []; @Input() discoverLeagues: League[]; @Input() playerId: string; @Input() teamId: string; - private online: boolean; + online: boolean; private onlineStateCallback = () => this.online = navigator.onLine; constructor(route: ActivatedRoute, private graphQLService: GraphQLService, private pageTitleService: PageTitleService, - public authService: AuthService, private onlineStatusService: OnlineStatusService, - private elementRef: ElementRef) { + public authService: AuthService, private onlineStatusService: OnlineStatusService) { super(route); } @@ -74,9 +55,8 @@ export class LeagueBrowserComponent extends BaseComponent implements AfterViewIn private handleLeaguesQueryResponse(data) { this.myLeagues = data.myLeagues.map(league => League.fromJson(league)); if (this.myLeagues.length == 0) { - const tabs = document.querySelectorAll('ul.tabs').item(0); - const tabInstance = M.Tabs.getInstance(tabs); - tabInstance.select('discoverLeagues'); + // Switch to the 'Discover' tab programmatically if 'My Leagues' is empty + setTimeout(() => this.tabGroup.selectedIndex = 1, 0); // using setTimeout to avoid ExpressionChangedAfterItHasBeenCheckedError } let myLeagueIds = data.myLeagues.map(league => league.id); @@ -89,15 +69,6 @@ export class LeagueBrowserComponent extends BaseComponent implements AfterViewIn this.discoverLeagues = leagues; } - ngAfterViewInit(): void { - this.initTabs(); - } - - initTabs(): void { - const tabs = document.querySelectorAll('.tabs'); - M.Tabs.init(tabs); - } - private static compareLeagueByLastGameTime(l1: League, l2: League) { if (l1.games.length === 0 && l2.games.length === 0) { return 0; @@ -108,4 +79,24 @@ export class LeagueBrowserComponent extends BaseComponent implements AfterViewIn } return l2.games[0].time.getTime() - l1.games[0].time.getTime(); } + + private static readonly getLeaguesQuery: string = `query($playerId: ID, $leagueCount: Int) { + myLeagues : leagues(playerId:$playerId, first: $leagueCount){ + id + name + imageUrl + description + } + + allLeagues: leagues(first: $leagueCount){ + id + name + imageUrl + description + games(first:1 , finished:true) { + id + time + } + } + }`; } diff --git a/src/angular/app/leagues/league-delete-dialog/league-delete-dialog.component.html b/src/angular/app/leagues/league-delete-dialog/league-delete-dialog.component.html new file mode 100644 index 00000000..2f9bd5ef --- /dev/null +++ b/src/angular/app/leagues/league-delete-dialog/league-delete-dialog.component.html @@ -0,0 +1,9 @@ +

Delete League

+ +

You are about to delete this league ({{data.leagueName}}). This operation cannot be undone.

+
+ + + + + diff --git a/src/angular/app/leagues/league-delete-dialog/league-delete-dialog.component.ts b/src/angular/app/leagues/league-delete-dialog/league-delete-dialog.component.ts new file mode 100644 index 00000000..ac0f4e83 --- /dev/null +++ b/src/angular/app/leagues/league-delete-dialog/league-delete-dialog.component.ts @@ -0,0 +1,20 @@ +import { Component, Inject } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +@Component({ + templateUrl: './league-delete-dialog.component.html' +}) +export class LeagueDeleteDialogComponent { + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: { leagueName: string } + ) {} + + onConfirmDelete(): void { + this.dialogRef.close(true); // Close the dialog and indicate deletion + } + + onCancelDelete(): void { + this.dialogRef.close(false); // Close the dialog without deletion + } +} diff --git a/src/angular/app/leagues/league-edit-create/league-edit-create.component.html b/src/angular/app/leagues/league-edit-create/league-edit-create.component.html index 7c500220..282a3ee1 100644 --- a/src/angular/app/leagues/league-edit-create/league-edit-create.component.html +++ b/src/angular/app/leagues/league-edit-create/league-edit-create.component.html @@ -4,12 +4,7 @@
- - Edit league - - - Create league - + {{ editMode ? 'Edit league' : 'Create league' }}
@@ -37,29 +32,25 @@
+ +
-
- -
+
+ +
-
- -
+
@@ -97,43 +88,15 @@
+
- - Cancel - Create - - - Cancel - Save - - + +
- - - - - - - \ No newline at end of file + diff --git a/src/angular/app/leagues/league-edit-create/league-edit-create.component.less b/src/angular/app/leagues/league-edit-create/league-edit-create.component.less index 0d36c715..44ba88c2 100644 --- a/src/angular/app/leagues/league-edit-create/league-edit-create.component.less +++ b/src/angular/app/leagues/league-edit-create/league-edit-create.component.less @@ -34,7 +34,7 @@ } } - .modal.player-select-modal.open { + .modal.player-select-dialog.open { max-height: 80%; width: 90%; } diff --git a/src/angular/app/leagues/league-edit-create/league-edit-create.component.ts b/src/angular/app/leagues/league-edit-create/league-edit-create.component.ts index d5ccf497..5da484b3 100644 --- a/src/angular/app/leagues/league-edit-create/league-edit-create.component.ts +++ b/src/angular/app/leagues/league-edit-create/league-edit-create.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, ElementRef, EventEmitter, ViewChild} from '@angular/core'; +import {AfterViewInit, Component, ElementRef, ViewChild} from '@angular/core'; import {GraphQLService} from '../../services/graphql.service'; import {ActivatedRoute, Router} from '@angular/router'; import {Location} from '@angular/common'; @@ -17,7 +17,9 @@ import {Player} from '../../../graphql/schemas/Player'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { catchError, lastValueFrom, map } from 'rxjs'; import { Config } from '../../app.config'; -import { MaterializeAction } from 'angular2-materialize'; +import { MatDialog } from '@angular/material/dialog'; +import { AdminSelectDialogComponent } from '../admin-select-dialog/admin-select-dialog.component'; +import { PlayerSelectDialogComponent } from '../player-select-dialog/player-select-dialog.component'; declare var XPCONFIG: Config; @@ -34,7 +36,6 @@ export class LeagueEditCreateComponent private static readonly DEFAULT_MIN_DIFFERENCE: number = 2; @ViewChild('fileInput') inputEl: ElementRef; - @ViewChild('addPlayerChips') addPlayerChipsViewChild; name: string; leagueId: string; description: string; @@ -48,7 +49,6 @@ export class LeagueEditCreateComponent adminPlayerNames: string[] = []; onlyPlayers: Player[] = []; onlyPlayerNames: string[] = []; - onlyPlayerNamesToAdd: string[] = []; playerNames: string[] = []; allPlayerIds: string[] = []; allPlayerNames: string[] = []; @@ -61,12 +61,10 @@ export class LeagueEditCreateComponent 'pointsToWin': '', 'minimumDifference': '' }; - materializeActionsAdmin = new EventEmitter(); - materializeActionsPlayer = new EventEmitter(); - private online: boolean; + public online: boolean; private onlineStateCallback = () => this.online = navigator.onLine; - constructor(private http: HttpClient, private authService: AuthService, private graphQLService: GraphQLService, + constructor(private dialog: MatDialog, private http: HttpClient, private authService: AuthService, private graphQLService: GraphQLService, private pageTitleService: PageTitleService, private onlineStatusService: OnlineStatusService, route: ActivatedRoute, private location: Location, private router: Router, private fb: FormBuilder, private sanitizer: DomSanitizer) { @@ -307,30 +305,53 @@ export class LeagueEditCreateComponent } onAddAdminClicked() { - this.showSelectAdminModal(); + const dialogRef = this.dialog.open(AdminSelectDialogComponent, { + width: '250px', + data: { + allPlayerIds: this.allPlayerIds, + adminPlayerIds: this.adminPlayerIds, + } + }); + + dialogRef.afterClosed().subscribe(selectedAdmin => { + if (selectedAdmin) { + this.onAdminSelected(selectedAdmin); + } + }); } onAddPlayerClicked() { - this.showSelectPlayerModal(); + const dialogRef = this.dialog.open(PlayerSelectDialogComponent, { + width: '250px', + data: { + allPlayerNames: this.allPlayerNames, + playerNames: this.playerNames, + } + }); + + dialogRef.afterClosed().subscribe(selectedPlayers => { + if (selectedPlayers && selectedPlayers.length > 0) { + this.onPlayersSelected(selectedPlayers); + } + }); } - onAdminSelected(newAdmin: Player) { - if (!newAdmin) { + onAdminSelected(selectedAdmin: Player) { + if (!selectedAdmin) { return; } - let existing = this.admins.find((player) => player.id === newAdmin.id); + let existing = this.admins.find((player) => player.id === selectedAdmin.id); if (!existing) { - this.admins.push(newAdmin); - this.adminPlayerIds.push(newAdmin.id); - this.adminPlayerNames.push(newAdmin.name); - this.onRemovePlayerClicked(newAdmin); - this.playerNames.push(newAdmin.name); + this.admins.push(selectedAdmin); + this.adminPlayerIds.push(selectedAdmin.id); + this.adminPlayerNames.push(selectedAdmin.name); + this.onRemovePlayerClicked(selectedAdmin); + this.playerNames.push(selectedAdmin.name); } - this.hideSelectAdminModal(); } - onPlayersSelected() { - this.onlyPlayerNamesToAdd.forEach((playerName) => { + onPlayersSelected(selectedPlayerNames: string[]): void { + selectedPlayerNames.forEach(playerName => { if ((this.allPlayerMap[playerName] || playerName.indexOf('@') !== -1) && this.playerNames.indexOf(playerName) === -1) { let player = this.allPlayerMap[playerName] || new Player(undefined, playerName); this.onlyPlayers.push(player); @@ -338,25 +359,6 @@ export class LeagueEditCreateComponent this.playerNames.push(playerName); } }); - this.hideSelectPlayerModal(); - } - - showSelectAdminModal(): void { - this.materializeActionsAdmin.emit({action: "modal", params: ['open']}); - } - - showSelectPlayerModal(): void { - this.onlyPlayerNamesToAdd = []; - this.materializeActionsPlayer.emit({action: "modal", params: ['open']}); - setTimeout(() => this.addPlayerChipsViewChild.focus(), 300); //No possibility to set a callback on display - } - - hideSelectAdminModal(): void { - this.materializeActionsAdmin.emit({action: "modal", params: ['close']}); - } - - hideSelectPlayerModal(): void { - this.materializeActionsPlayer.emit({action: "modal", params: ['close']}); } private static readonly createLeagueMutation = `mutation ($name: String!, $description: String!, $sport: Sport!, $adminPlayerIds: [ID], $playerNames: [String], $pointsToWin: Int, $minimumDifference: Int, $halfTimeSwitch: Boolean) { diff --git a/src/angular/app/leagues/league-leave-dialog/league-leave-dialog.component.html b/src/angular/app/leagues/league-leave-dialog/league-leave-dialog.component.html new file mode 100644 index 00000000..1d4252a3 --- /dev/null +++ b/src/angular/app/leagues/league-leave-dialog/league-leave-dialog.component.html @@ -0,0 +1,10 @@ +

Leave League

+ +

You are about to leave this league ({{data.leagueName}}).

+
+ + + + + + diff --git a/src/angular/app/leagues/league-leave-dialog/league-leave-dialog.component.ts b/src/angular/app/leagues/league-leave-dialog/league-leave-dialog.component.ts new file mode 100644 index 00000000..a2311814 --- /dev/null +++ b/src/angular/app/leagues/league-leave-dialog/league-leave-dialog.component.ts @@ -0,0 +1,20 @@ +import { Component, Inject } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +@Component({ + templateUrl: './league-leave-dialog.component.html' +}) +export class LeagueLeaveDialogComponent { + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: { leagueName: string } + ) {} + + onConfirmLeave(): void { + this.dialogRef.close(true); + } + + onCancelLeave(): void { + this.dialogRef.close(false); + } +} diff --git a/src/angular/app/leagues/league-profile-players/league-profile-players.component.html b/src/angular/app/leagues/league-profile-players/league-profile-players.component.html index 67f0f24a..30e3ead7 100644 --- a/src/angular/app/leagues/league-profile-players/league-profile-players.component.html +++ b/src/angular/app/leagues/league-profile-players/league-profile-players.component.html @@ -11,8 +11,8 @@
  • + (removePlayer)="openRemovePlayerDialog($event)" + (approvePlayer)="openApproveOrRejectPlayerDialog($event)">
  • @@ -22,28 +22,4 @@ - - - diff --git a/src/angular/app/leagues/league-profile-players/league-profile-players.component.ts b/src/angular/app/leagues/league-profile-players/league-profile-players.component.ts index 53da5502..34f10673 100644 --- a/src/angular/app/leagues/league-profile-players/league-profile-players.component.ts +++ b/src/angular/app/leagues/league-profile-players/league-profile-players.component.ts @@ -1,4 +1,4 @@ -import {Component, EventEmitter, Input, SimpleChanges} from '@angular/core'; +import {Component, Input} from '@angular/core'; import {GraphQLService} from '../../services/graphql.service'; import {AuthService} from '../../services/auth.service'; import {ActivatedRoute, Router} from '@angular/router'; @@ -7,6 +7,9 @@ import {LeaguePlayer} from '../../../graphql/schemas/LeaguePlayer'; import {BaseComponent} from '../../common/base.component'; import {PageTitleService} from '../../services/page-title.service'; import {Player} from '../../../graphql/schemas/Player'; +import {JoinLeagueRequestDialogComponent} from '../join-league-request-dialog/join-league-request-dialog.component'; +import {MatDialog} from '@angular/material/dialog'; +import {RemovePlayerDialogComponent} from '../remove-player-dialog/remove-player-dialog.component'; @Component({ selector: 'league-profile-players', @@ -22,14 +25,10 @@ export class LeagueProfilePlayersComponent private leagueName: string; private pageCount: number = 1; adminInLeague: boolean; - materializeActionsRemove = new EventEmitter(); - materializeActionsApprove = new EventEmitter(); - removePlayer: Player; - approvePlayer: Player; connectionError: boolean; constructor(route: ActivatedRoute, private graphQLService: GraphQLService, private authService: AuthService, private router: Router, - private pageTitleService: PageTitleService) { + private pageTitleService: PageTitleService, private dialog: MatDialog) { super(route); } @@ -81,57 +80,50 @@ export class LeagueProfilePlayersComponent this.connectionError = true; } - onRemovePlayer(player: Player) { - this.removePlayer = player; - this.showModalRemove(); - } - - onApprovePlayer(player: Player) { - this.approvePlayer = player; - this.showModalApprove(); - } - - onConfirmRemoveClicked() { - this.graphQLService.post(LeagueProfilePlayersComponent.leavePlayerLeagueQuery, - {playerId: this.removePlayer.id, leagueId: this.league.id}).then( - data => { - this.hideModalRemove(); - this.refresh(); - }); + removePlayer(player: Player) { + this.graphQLService.post( + LeagueProfilePlayersComponent.leavePlayerLeagueQuery, + { playerId: player.id, leagueId: this.league.id } + ).then(() => this.refresh()); } - onConfirmPlayerJoin(allow: boolean) { - if (allow) { - this.graphQLService.post(LeagueProfilePlayersComponent.joinPlayerLeagueQuery, - {playerId: this.approvePlayer.id, leagueId: this.league.id}).then( - data => { - this.hideModalApprove(); - this.refresh(); - }); - } else { - this.graphQLService.post(LeagueProfilePlayersComponent.denyJoinLeagueRequestQuery, - {playerId: this.approvePlayer.id, leagueId: this.league.id}).then( - data => { - this.hideModalApprove(); - this.refresh(); - }); - } - } + openRemovePlayerDialog(player: Player): void { + const dialogRef = this.dialog.open(RemovePlayerDialogComponent, { + width: '250px', + data: { + playerName: player.name, + leagueName: this.league.name + } // pass data as needed + }); - public showModalRemove(): void { - this.materializeActionsRemove.emit({action: "modal", params: ['open']}); + dialogRef.afterClosed().subscribe(result => { + if (result === true) { + this.removePlayer(player); + } + }); } - public hideModalRemove(): void { - this.materializeActionsRemove.emit({action: "modal", params: ['close']}); - } + public openApproveOrRejectPlayerDialog(player: Player): void { + const dialogRef = this.dialog.open(JoinLeagueRequestDialogComponent, { + width: '250px', + data: { + playerName: player.name, + leagueName: this.league.name + } + }); - public showModalApprove(): void { - this.materializeActionsApprove.emit({action: "modal", params: ['open']}); + dialogRef.afterClosed().subscribe(result => { + if (result) { + this.approveOrRejectPlayer(player, result); + } + }); } - public hideModalApprove(): void { - this.materializeActionsApprove.emit({action: "modal", params: ['close']}); + approveOrRejectPlayer(player: Player, allow: boolean) { + this.graphQLService.post( + allow ? LeagueProfilePlayersComponent.joinPlayerLeagueQuery : LeagueProfilePlayersComponent.denyJoinLeagueRequestQuery, + { playerId: player.id, leagueId: this.league.id } + ).then(() => this.refresh()); } private static readonly getLeagueQuery = `query ($name: String, $after:String, $first:Int, $sort: String, $playerId: ID!, $gamesSince: String) { diff --git a/src/angular/app/leagues/league-profile/league-profile.component.html b/src/angular/app/leagues/league-profile/league-profile.component.html index fb80872e..1e799f57 100644 --- a/src/angular/app/leagues/league-profile/league-profile.component.html +++ b/src/angular/app/leagues/league-profile/league-profile.component.html @@ -31,7 +31,7 @@ starsJoin this league @@ -40,15 +40,15 @@ more_vert
    @@ -67,8 +67,8 @@ [leaguePlayers]="league.leaguePlayers" [detailsPath]="['leagues', league.name.toLowerCase(), 'players']" [seeMoreText]="'See full player ranking'" - [allowRemove]="adminInLeague && online" (removePlayer)="onRemovePlayer($event)" - (approvePlayer)="onApprovePlayerJoin($event)"> + [allowRemove]="adminInLeague && online" (removePlayer)="openRemovePlayerDialog($event)" + (approvePlayer)="openApproveOrRejectPlayerDialog($event)">
    @@ -83,84 +83,5 @@ [detailsPath]="['leagues', league.name.toLowerCase(), 'games']">
    - - - - - - - - - - diff --git a/src/angular/app/leagues/league-profile/league-profile.component.ts b/src/angular/app/leagues/league-profile/league-profile.component.ts index 26675c42..89abdd2c 100644 --- a/src/angular/app/leagues/league-profile/league-profile.component.ts +++ b/src/angular/app/leagues/league-profile/league-profile.component.ts @@ -11,6 +11,14 @@ import {Player} from '../../../graphql/schemas/Player'; import {WebSocketManager} from '../../services/websocket.manager'; import {EventType, RemoteEvent} from '../../../graphql/schemas/RemoteEvent'; import { Config } from '../../app.config'; +import { AddPlayersDialogComponent } from '../add-players-dialog/add-players-dialog.component'; +import { RemovePlayerDialogComponent } from '../remove-player-dialog/remove-player-dialog.component'; +import { MatDialog } from '@angular/material/dialog'; +import {JoinLeagueRequestDialogComponent} from '../join-league-request-dialog/join-league-request-dialog.component'; +import {PendingRequestDialogComponent} from '../pending-request-dialog/pending-request-dialog.component'; +import {LeagueDeleteDialogComponent} from '../league-delete-dialog/league-delete-dialog.component'; +import {LeagueLeaveDialogComponent} from '../league-leave-dialog/league-leave-dialog.component'; +import {RegenerateRankingDialogComponent} from '../regenerate-ranking-dialog/regenerate-ranking-dialog.component'; declare var XPCONFIG: Config; @@ -24,7 +32,6 @@ export class LeagueProfileComponent implements OnChanges, OnDestroy { @Input() league: League; - @ViewChild('addPlayerChips') addPlayerChipsViewChild; connectionError: boolean; playerInLeague: boolean; userAuthenticated: boolean; @@ -34,22 +41,20 @@ export class LeagueProfileComponent activeGames: Game[] = []; nonMembersPlayerNames: string[] = []; playerNamesToAdd: string[] = []; - removePlayer: Player; - approvePlayer: Player; approvePollingTimerId: any; - materializeActions = new EventEmitter(); - materializeActionsRemove = new EventEmitter(); - materializeActionsApprove = new EventEmitter(); - materializeActionsPending = new EventEmitter(); - materializeActionsDelete = new EventEmitter(); - materializeActionsLeave = new EventEmitter(); - materializeActionsRegenerateRanking = new EventEmitter(); online: boolean; onlineStateCallback = () => this.online = navigator.onLine; private wsMan: WebSocketManager; - constructor(route: ActivatedRoute, private authService: AuthService, private graphQLService: GraphQLService, - private pageTitleService: PageTitleService, private onlineStatusService: OnlineStatusService, private router: Router) { + constructor( + route: ActivatedRoute, + private authService: AuthService, + private graphQLService: GraphQLService, + private pageTitleService: PageTitleService, + private onlineStatusService: OnlineStatusService, + private router: Router, + private dialog: MatDialog + ) { super(route); } @@ -76,21 +81,6 @@ export class LeagueProfileComponent this.online = navigator.onLine; } - ngAfterViewInit(): void { - // Poll until loaded - const buttonPollId = setInterval(() => { - if (this.league) { - this.initFloatingButtons(); - clearInterval(buttonPollId); - } - }, 500); - } - - initFloatingButtons(): void { - const buttons = document.querySelectorAll('.fixed-action-btn'); - M.FloatingActionButton.init(buttons); - } - ngOnDestroy() { clearTimeout(this.approvePollingTimerId); this.approvePollingTimerId = undefined; @@ -195,165 +185,172 @@ export class LeagueProfileComponent this.router.navigate(['leagues', this.league.name.toLowerCase(), 'edit']); } - onAddPlayerClicked() { - this.showModal(); - } - - onDeleteClicked() { - this.showModalDelete(); - } - - onLeaveClicked() { - this.showModalLeave(); - } - onJoinClicked() { if (this.authService.isAuthenticated() && !this.playerInLeague) { let playerId = this.authService.getUser().playerId; - this.graphQLService.post(LeagueProfileComponent.requestJoinLeagueQuery, {leagueId: this.league.id}).then( - data => { - this.refreshData(this.league.name); - }); + this.graphQLService.post( + LeagueProfileComponent.requestJoinLeagueQuery, + { leagueId: this.league.id } + ).then(() => this.refreshData(this.league.name)); } } - onPlayersAdded() { - this.graphQLService.post(LeagueProfileComponent.addPlayersLeagueQuery, - {leagueId: this.league.id, playerNames: this.playerNamesToAdd}).then( - data => { - this.refreshData(this.league.name); - }); - this.hideModal(); + addPlayers(playerNamesToAdd: string[]) { + this.graphQLService.post(LeagueProfileComponent.addPlayersLeagueQuery, { + leagueId: this.league.id, + playerNames: playerNamesToAdd + }) + .then(() => this.refreshData(this.league.name)) + .catch(error => { + // Handle error + console.error("Error adding players: ", error); + }); } - onRemovePlayer(player: Player) { - this.removePlayer = player; - this.showModalRemove(); - } + openRemovePlayerDialog(player: Player): void { + //this.removePlayer = player; + const dialogRef = this.dialog.open(RemovePlayerDialogComponent, { + width: '250px', + data: { + playerName: player.name, + leagueName: this.league.name + } // pass data as needed + }); - onApprovePlayerJoin(player: Player) { - this.approvePlayer = player; - this.showModalApprove(); + dialogRef.afterClosed().subscribe(result => { + if (result === true) { + this.removePlayer(player); + // Handle the removal confirmation + } + }); } - onConfirmRemoveClicked() { + removePlayer(player: Player) { this.graphQLService.post(LeagueProfileComponent.leavePlayerLeagueQuery, - {playerId: this.removePlayer.id, leagueId: this.league.id}).then( + {playerId: player.id, leagueId: this.league.id}).then( data => { - this.hideModalRemove(); this.refreshData(this.league.name); }); } - onConfirmPlayerJoin(allow: boolean) { - if (allow) { - this.graphQLService.post(LeagueProfileComponent.joinPlayerLeagueQuery, - {playerId: this.approvePlayer.id, leagueId: this.league.id}).then( - data => { - this.hideModalApprove(); - this.refreshData(this.league.name); - }); - } else { - this.graphQLService.post(LeagueProfileComponent.denyJoinLeagueRequestQuery, - {playerId: this.approvePlayer.id, leagueId: this.league.id}).then( - data => { - this.hideModalApprove(); - this.refreshData(this.league.name); - }); - } - } - - onConfirmDeleteClicked() { - this.graphQLService.post(LeagueProfileComponent.deleteLeagueQuery, - {name: this.league.name}).then( - data => { - this.hideModalDelete(); - this.router.navigate(['leagues']); - }); - } - - onConfirmLeaveClicked() { - this.graphQLService.post(LeagueProfileComponent.leavePlayerLeagueQuery, - {playerId: this.authService.getUser().playerId, leagueId: this.league.id}).then( - data => { - this.hideModalLeave(); + approveOrRejectPlayer(player: Player, allow: boolean) { + this.graphQLService.post( + allow ? LeagueProfileComponent.joinPlayerLeagueQuery : LeagueProfileComponent.denyJoinLeagueRequestQuery, + { playerId: player.id, leagueId: this.league.id } + ).then(() => { + //this.hideModalApprove(); this.refreshData(this.league.name); }); } - onRankingRefreshClicked() { - this.showModalRanking(); - } - - onConfirmRegenerateClicked() { - this.graphQLService.post(LeagueProfileComponent.regenerateLeagueRanking, - {leagueId: this.league.id}).then( - data => { - this.hideModalRanking(); - }); + deleteLeague() { + this.graphQLService.post( + LeagueProfileComponent.deleteLeagueQuery, + {name: this.league.name} + ).then( () => this.router.navigate(['leagues'])); } - showModal(): void { - this.playerNamesToAdd = []; - this.materializeActions.emit({action: "modal", params: ['open']}); - setTimeout(() => this.addPlayerChipsViewChild.focus(), 300); //No possibility to set a callback on display + leaveLeague() { + this.graphQLService.post( + LeagueProfileComponent.leavePlayerLeagueQuery, + { playerId: this.authService.getUser().playerId, leagueId: this.league.id } + ).then(() => this.refreshData(this.league.name) ); } - hideModal(): void { - this.materializeActions.emit({action: "modal", params: ['close']}); + regenerateRanking() { + this.graphQLService.post(LeagueProfileComponent.regenerateLeagueRanking, {leagueId: this.league.id}); } - public showModalRemove(): void { - this.materializeActionsRemove.emit({action: "modal", params: ['open']}); - } + openAddPlayerDialog(): void { + const dialogRef = this.dialog.open(AddPlayersDialogComponent, { + width: '250px', + data: { + nonMembersPlayerNames: this.nonMembersPlayerNames, + playerNamesToAdd: this.playerNamesToAdd + } + }); - public hideModalRemove(): void { - this.materializeActionsRemove.emit({action: "modal", params: ['close']}); + dialogRef.afterClosed().subscribe(result => { + if (result) { + this.addPlayers(result); + } + }); } - public showModalApprove(): void { - this.materializeActionsApprove.emit({action: "modal", params: ['open']}); - } + public openApproveOrRejectPlayerDialog(player: Player): void { + const dialogRef = this.dialog.open(JoinLeagueRequestDialogComponent, { + width: '250px', + data: { + playerName: player.name, + leagueName: this.league.name + } + }); - public hideModalApprove(): void { - this.materializeActionsApprove.emit({action: "modal", params: ['close']}); + dialogRef.afterClosed().subscribe(result => { + if (result) { + this.approveOrRejectPlayer(player, result); + } + }); } - public showModalPending(): void { + public checkPendingRequest(): void { // check if pending, show info modal if still pending this.refreshData(this.league.name).then(() => { if (!this.playerInLeague && this.joinLeagueRequested) { - this.materializeActionsPending.emit({action: "modal", params: ['open']}); + this.openPendingRequestDialog(); } }); } - public hideModalPending(): void { - this.materializeActionsPending.emit({action: "modal", params: ['close']}); + public openPendingRequestDialog(): void { + this.dialog.open(PendingRequestDialogComponent, { + width: '250px' + }); } - public showModalDelete(): void { - this.materializeActionsDelete.emit({action: "modal", params: ['open']}); - } + public openLeagueDeleteDialog(): void { + const dialogRef = this.dialog.open(LeagueDeleteDialogComponent, { + width: '250px', + data: { + leagueName: this.league.name + } // pass data as needed + }); - public hideModalDelete(): void { - this.materializeActionsDelete.emit({action: "modal", params: ['close']}); + dialogRef.afterClosed().subscribe(result => { + if (result === true) { + this.deleteLeague(); + } + }); } - public showModalLeave(): void { - this.materializeActionsLeave.emit({action: "modal", params: ['open']}); - } + public openLeagueLeaveDialog(): void { + const dialogRef = this.dialog.open(LeagueLeaveDialogComponent, { + width: '250px', + data: { + leagueName: this.league.name + } // pass data as needed + }); - public hideModalLeave(): void { - this.materializeActionsLeave.emit({action: "modal", params: ['close']}); + dialogRef.afterClosed().subscribe(result => { + if (result === true) { + this.leaveLeague(); + } + }); } - public showModalRanking(): void { - this.materializeActionsRegenerateRanking.emit({action: "modal", params: ['open']}); - } + public openRegenerateRankingDialog(): void { + const dialogRef = this.dialog.open(RegenerateRankingDialogComponent, { + width: '250px', + data: { + leagueName: this.league.name + } // pass data as needed + }); - public hideModalRanking(): void { - this.materializeActionsRegenerateRanking.emit({action: "modal", params: ['close']}); + dialogRef.afterClosed().subscribe(result => { + if (result === true) { + this.regenerateRanking(); + } + }); } onWsMessage(event: RemoteEvent) { diff --git a/src/angular/app/leagues/league.module.ts b/src/angular/app/leagues/league.module.ts index cacde1d4..e031940a 100644 --- a/src/angular/app/leagues/league.module.ts +++ b/src/angular/app/leagues/league.module.ts @@ -17,7 +17,20 @@ import {PlayerRouteGuard} from '../guards/player.route.guard'; import {AdminListComponent} from './admin-list/admin-list.component'; import {AdminSummaryComponent} from './admin-summary/admin-summary.component'; import {LeaguePlayerGraphComponent} from './league-player-graph/league-player-graph.component'; -import { MaterializeModule } from 'angular2-materialize'; +import {AdminSelectDialogComponent} from './admin-select-dialog/admin-select-dialog.component'; +import {PlayerSelectDialogComponent} from './player-select-dialog/player-select-dialog.component'; +import { MatButtonModule } from '@angular/material/button'; +import { MatTabsModule } from '@angular/material/tabs'; +import { MatIconModule } from '@angular/material/icon'; +import { MatDialogModule } from '@angular/material/dialog'; +import { AddPlayersDialogComponent } from './add-players-dialog/add-players-dialog.component'; +import { RemovePlayerDialogComponent } from './remove-player-dialog/remove-player-dialog.component'; +import { ChipsComponent } from '../common/chips/chips.component'; +import { JoinLeagueRequestDialogComponent } from './join-league-request-dialog/join-league-request-dialog.component'; +import { PendingRequestDialogComponent } from './pending-request-dialog/pending-request-dialog.component'; +import { LeagueDeleteDialogComponent } from './league-delete-dialog/league-delete-dialog.component'; +import {LeagueLeaveDialogComponent} from './league-leave-dialog/league-leave-dialog.component'; +import {RegenerateRankingDialogComponent} from './regenerate-ranking-dialog/regenerate-ranking-dialog.component'; const leagueRoutes: Routes = [ {path: 'leagues', component: LeagueBrowserComponent, canActivate: [PlayerRouteGuard,]}, @@ -41,17 +54,35 @@ const leagueRoutes: Routes = [ LeagueEditCreateComponent, LeaguePlayerGraphComponent, AdminListComponent, - AdminSummaryComponent + AdminSummaryComponent, + AdminSelectDialogComponent, + PlayerSelectDialogComponent, + AddPlayersDialogComponent, + RemovePlayerDialogComponent, + JoinLeagueRequestDialogComponent, + PendingRequestDialogComponent, + LeagueDeleteDialogComponent, + LeagueLeaveDialogComponent, + RegenerateRankingDialogComponent ], imports: [ - MaterializeModule, + //MaterializeModule, FormsModule, CommonModule, GamesModule, NgChartsModule, - RouterModule.forChild(leagueRoutes) + RouterModule.forChild(leagueRoutes), + MatButtonModule, + MatTabsModule, + MatIconModule, + MatDialogModule + ], + exports: [ + LeagueListComponent, + LeaguePlayerListComponent, + LeagueTeamListComponent, + ChipsComponent ], - exports: [LeagueListComponent, LeaguePlayerListComponent, LeagueTeamListComponent], providers: [], bootstrap: [] }) diff --git a/src/angular/app/leagues/pending-request-dialog/pending-request-dialog.component.html b/src/angular/app/leagues/pending-request-dialog/pending-request-dialog.component.html new file mode 100644 index 00000000..d646f6c4 --- /dev/null +++ b/src/angular/app/leagues/pending-request-dialog/pending-request-dialog.component.html @@ -0,0 +1,9 @@ +

    Join League Requested

    + +

    A request for joining this league has been sent to the league administrators. You will be notified by email as soon as the petition is resolved.

    +
    + + + + + diff --git a/src/angular/app/leagues/pending-request-dialog/pending-request-dialog.component.ts b/src/angular/app/leagues/pending-request-dialog/pending-request-dialog.component.ts new file mode 100644 index 00000000..949f0d1f --- /dev/null +++ b/src/angular/app/leagues/pending-request-dialog/pending-request-dialog.component.ts @@ -0,0 +1,13 @@ +import { Component } from '@angular/core'; +import { MatDialogRef } from '@angular/material/dialog'; + +@Component({ + templateUrl: './pending-request-dialog.component.html' +}) +export class PendingRequestDialogComponent { + constructor(public dialogRef: MatDialogRef) {} + + closeDialog(): void { + this.dialogRef.close(); + } +} diff --git a/src/angular/app/leagues/player-select-dialog/player-select-dialog.component.html b/src/angular/app/leagues/player-select-dialog/player-select-dialog.component.html new file mode 100644 index 00000000..d2d0d685 --- /dev/null +++ b/src/angular/app/leagues/player-select-dialog/player-select-dialog.component.html @@ -0,0 +1,7 @@ +

    Select a player to add

    + + + + + + diff --git a/src/angular/app/leagues/player-select-dialog/player-select-dialog.component.ts b/src/angular/app/leagues/player-select-dialog/player-select-dialog.component.ts new file mode 100644 index 00000000..f8acab09 --- /dev/null +++ b/src/angular/app/leagues/player-select-dialog/player-select-dialog.component.ts @@ -0,0 +1,24 @@ +import {Component, Inject, ViewChild} from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; + +@Component({ + selector: 'app-player-select-dialog', + templateUrl: './player-select-dialog.component.html', +}) +export class PlayerSelectDialogComponent { + @ViewChild('addPlayerChips') addPlayerChipsViewChild: any; + onlyPlayerNamesToAdd: string[] = []; + + constructor( + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: { + allPlayerNames: string[]; + playerNames: string[]; + } + ) {} + + onPlayersSelected() { + // Close the dialog and return the selected players + this.dialogRef.close(this.onlyPlayerNamesToAdd); + } +} diff --git a/src/angular/app/leagues/regenerate-ranking-dialog/regenerate-ranking-dialog.component.html b/src/angular/app/leagues/regenerate-ranking-dialog/regenerate-ranking-dialog.component.html new file mode 100644 index 00000000..9cc7f1d6 --- /dev/null +++ b/src/angular/app/leagues/regenerate-ranking-dialog/regenerate-ranking-dialog.component.html @@ -0,0 +1,11 @@ +

    Regenerate League Ranking

    + +

    Are you sure you want to regenerate '{{data.leagueName}}' league's ranking?

    +
    + + + + + + + diff --git a/src/angular/app/leagues/regenerate-ranking-dialog/regenerate-ranking-dialog.component.ts b/src/angular/app/leagues/regenerate-ranking-dialog/regenerate-ranking-dialog.component.ts new file mode 100644 index 00000000..34c465bb --- /dev/null +++ b/src/angular/app/leagues/regenerate-ranking-dialog/regenerate-ranking-dialog.component.ts @@ -0,0 +1,20 @@ +import { Component, Inject } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +@Component({ + templateUrl: './regenerate-ranking-dialog.component.html' +}) +export class RegenerateRankingDialogComponent { + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: { leagueName: string } + ) {} + + onConfirmRegenerate(): void { + this.dialogRef.close(true); + } + + onCancelRegenerate(): void { + this.dialogRef.close(false); + } +} diff --git a/src/angular/app/leagues/remove-player-dialog/remove-player-dialog.component.html b/src/angular/app/leagues/remove-player-dialog/remove-player-dialog.component.html new file mode 100644 index 00000000..ca9a2f7c --- /dev/null +++ b/src/angular/app/leagues/remove-player-dialog/remove-player-dialog.component.html @@ -0,0 +1,9 @@ +

    Remove player

    + +

    You are about to remove player '{{data.playerName}}' from this league ({{data.leagueName}}).

    +
    + + + + + diff --git a/src/angular/app/leagues/remove-player-dialog/remove-player-dialog.component.ts b/src/angular/app/leagues/remove-player-dialog/remove-player-dialog.component.ts new file mode 100644 index 00000000..3a752171 --- /dev/null +++ b/src/angular/app/leagues/remove-player-dialog/remove-player-dialog.component.ts @@ -0,0 +1,20 @@ +import { Component, Inject } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +@Component({ + templateUrl: './remove-player-dialog.component.html' +}) +export class RemovePlayerDialogComponent { + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: { + playerName: string, + leagueName: string + } // Add types as appropriate + ) {} + + onConfirmRemoveClicked(): void { + // Implement your removal logic here + this.dialogRef.close(true); // Close the dialog and optionally return data + } +} diff --git a/src/angular/app/players/players.module.ts b/src/angular/app/players/players.module.ts index 4fa7aebc..243fe77a 100644 --- a/src/angular/app/players/players.module.ts +++ b/src/angular/app/players/players.module.ts @@ -14,6 +14,7 @@ import {FormsModule} from '@angular/forms'; import {AuthenticatedRouteGuard, } from '../guards/authenticated.route.guard'; import {EditRouteGuard, } from '../guards/edit.route.guard'; import {PlayerRouteGuard, } from '../guards/player.route.guard'; +import {MatDialogModule} from '@angular/material/dialog'; const playersRoutes: Routes = [ {path: '', component: PlayerProfileComponent, canActivate: [EditRouteGuard, AuthenticatedRouteGuard, PlayerRouteGuard,]}, @@ -39,7 +40,8 @@ const playersRoutes: Routes = [ LeaguesModule, TeamsModule, RouterModule.forChild(playersRoutes), - FormsModule + FormsModule, + MatDialogModule ], exports: [], providers: [], diff --git a/src/angular/app/teams/player-select-dialog/player-select-dialog.component.html b/src/angular/app/teams/player-select-dialog/player-select-dialog.component.html new file mode 100644 index 00000000..2917e6b1 --- /dev/null +++ b/src/angular/app/teams/player-select-dialog/player-select-dialog.component.html @@ -0,0 +1,4 @@ + +

    Select a player

    + +
    diff --git a/src/angular/app/teams/player-select-dialog/player-select-dialog.component.ts b/src/angular/app/teams/player-select-dialog/player-select-dialog.component.ts new file mode 100644 index 00000000..af924973 --- /dev/null +++ b/src/angular/app/teams/player-select-dialog/player-select-dialog.component.ts @@ -0,0 +1,21 @@ +import { Component, Inject } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import {Player} from '../../../graphql/schemas/Player'; + +@Component({ + templateUrl: './player-select-dialog.component.html', +}) +export class PlayerSelectDialogComponent { + + constructor( + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: { + possibleTeamMateIds: string[]; + } + ) {} + + onPlayerSelected(player: Player) { + // Close the dialog and return the selected players + this.dialogRef.close(player); + } +} diff --git a/src/angular/app/teams/team-edit-create/team-edit-create.component.html b/src/angular/app/teams/team-edit-create/team-edit-create.component.html index 35575c1b..491085db 100644 --- a/src/angular/app/teams/team-edit-create/team-edit-create.component.html +++ b/src/angular/app/teams/team-edit-create/team-edit-create.component.html @@ -19,7 +19,7 @@
    info_outline -
    @@ -36,7 +36,7 @@
    Team Players
    @@ -64,10 +64,3 @@
    Team Logo
    - - \ No newline at end of file diff --git a/src/angular/app/teams/team-edit-create/team-edit-create.component.ts b/src/angular/app/teams/team-edit-create/team-edit-create.component.ts index 8f576ed0..ad663d75 100644 --- a/src/angular/app/teams/team-edit-create/team-edit-create.component.ts +++ b/src/angular/app/teams/team-edit-create/team-edit-create.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, ElementRef, EventEmitter, ViewChild} from '@angular/core'; +import {AfterViewInit, Component, ElementRef, ViewChild} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {Location} from '@angular/common'; import {BaseComponent} from '../../common/base.component'; @@ -16,6 +16,8 @@ import {DomSanitizer, SafeUrl} from '@angular/platform-browser'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { catchError, lastValueFrom, map } from 'rxjs'; import { Config } from '../../app.config'; +import {MatDialog} from '@angular/material/dialog'; +import {PlayerSelectDialogComponent} from '../player-select-dialog/player-select-dialog.component'; declare var XPCONFIG: Config; @@ -27,7 +29,6 @@ declare var XPCONFIG: Config; export class TeamEditCreateComponent extends BaseComponent implements AfterViewInit { - materializeActions = new EventEmitter(); name: string; id: string; @@ -43,15 +44,16 @@ export class TeamEditCreateComponent 'name': '', 'description': '' }; + online: boolean; private currentPlayer: Player; - private online: boolean; private onlineStateCallback = () => this.online = navigator.onLine; @ViewChild('fileInput') inputEl: ElementRef; constructor(private http: HttpClient, route: ActivatedRoute, private graphQLService: GraphQLService, private pageTitleService: PageTitleService, private router: Router, private location: Location, - private authService: AuthService, private onlineStatusService: OnlineStatusService, - private fb: FormBuilder, private sanitizer: DomSanitizer) { + private authService: AuthService, private onlineStatusService: OnlineStatusService, + private fb: FormBuilder, private sanitizer: DomSanitizer, + private dialog: MatDialog) { super(route); } @@ -92,7 +94,7 @@ export class TeamEditCreateComponent inputEl.addEventListener('change', () => this.onFileInputChange(inputEl)); } - private updatePageTitle(title: string) { + updatePageTitle(title: string) { this.pageTitleService.setTitle(title); } @@ -185,8 +187,19 @@ export class TeamEditCreateComponent this.location.back(); } - onSelectPlayerClicked() { - this.showModal(); + openPlayerSelectDialog(): void { + const dialogRef = this.dialog.open(PlayerSelectDialogComponent, { + width: '250px', + data: { + possibleTeamMateIds: this.possibleTeamMateIds + } // pass data as needed + }); + + dialogRef.afterClosed().subscribe((player: Player) => { + if (player) { + this.players = [this.currentPlayer, player]; + } + }); } private updateTeam() { @@ -227,21 +240,6 @@ export class TeamEditCreateComponent } } - onPlayerSelected(p: Player) { - if (p) { - this.hideModal(); - this.players = [this.currentPlayer, p]; - } - } - - public showModal(): void { - this.materializeActions.emit({action: "modal", params: ['open']}); - } - - public hideModal(): void { - this.materializeActions.emit({action: "modal", params: ['close']}); - } - private checkTeamNameInUse(name: string): Promise { return this.graphQLService.post(TeamEditCreateComponent.teamNameInUseQuery, {name: name}).then(data => { return data && data.team ? data.team.id !== this.id : false; diff --git a/src/angular/app/teams/team.module.ts b/src/angular/app/teams/team.module.ts index 3991547f..fdf119c6 100644 --- a/src/angular/app/teams/team.module.ts +++ b/src/angular/app/teams/team.module.ts @@ -8,7 +8,8 @@ import {TeamEditCreateComponent} from './team-edit-create/team-edit-create.compo import {TeamListPageComponent} from './team-list-page/team-list-page.component'; import {FormsModule} from '@angular/forms'; import {PlayerRouteGuard, } from '../guards/player.route.guard'; -import { MaterializeModule } from 'angular2-materialize'; +import {PlayerSelectDialogComponent} from './player-select-dialog/player-select-dialog.component'; +import {MatDialogModule} from '@angular/material/dialog'; const teamRoutes: Routes = [ {path: 'teams', component: TeamListPageComponent, canActivate: [PlayerRouteGuard,]}, @@ -21,15 +22,16 @@ const teamRoutes: Routes = [ declarations: [ TeamListPageComponent, TeamProfileComponent, - TeamEditCreateComponent + TeamEditCreateComponent, + PlayerSelectDialogComponent ], imports: [ - MaterializeModule, CommonModule, GamesModule, LeaguesModule, RouterModule.forChild(teamRoutes), - FormsModule + FormsModule, + MatDialogModule ], exports: [], providers: [], diff --git a/src/angular/global/form.less b/src/angular/global/form.less index 2897b9e5..d8c5b50c 100644 --- a/src/angular/global/form.less +++ b/src/angular/global/form.less @@ -2,7 +2,7 @@ .card.edit-form { background-color: #2A374E; - + /*select, .admin-summary { background-color: #1C2641; }*/ @@ -22,8 +22,7 @@ input[type=text], input[type=password], input[type=email], select, -textarea, -textarea.materialize-textarea{ +textarea { background-color: #475367; color: #fff; padding: 10px; @@ -65,4 +64,4 @@ textarea.materialize-textarea{ } -} \ No newline at end of file +} diff --git a/src/angular/global/search.less b/src/angular/global/search.less index bca79fb0..69ba4633 100644 --- a/src/angular/global/search.less +++ b/src/angular/global/search.less @@ -7,9 +7,8 @@ color: @main-theme-color; &-input { - border: none !important; - box-sizing: border-box !important; - // remove important when overriding materialize stuff is removed + border: none; + box-sizing: border-box; input& { font-size: 16px; @@ -23,4 +22,4 @@ top: 10px; right: 10px; } -} \ No newline at end of file +} diff --git a/src/angular/index.html b/src/angular/index.html index 9f5af125..462c65f7 100644 --- a/src/angular/index.html +++ b/src/angular/index.html @@ -6,7 +6,6 @@ - - \ No newline at end of file + diff --git a/src/angular/polyfills.ts b/src/angular/polyfills.ts index 54b08927..90883aa1 100644 --- a/src/angular/polyfills.ts +++ b/src/angular/polyfills.ts @@ -17,7 +17,7 @@ // import 'core-js/es7/reflect'; import '@angular/localize/init' -import 'core-js/es/reflect'; -import 'core-js/stable/reflect'; +import 'core-js/es/reflect'; +import 'core-js/stable/reflect'; import 'core-js/features/reflect'; import 'zone.js'; diff --git a/src/angular/styles.less b/src/angular/styles.less index 91efa92c..ad2a6da9 100644 --- a/src/angular/styles.less +++ b/src/angular/styles.less @@ -1,7 +1,7 @@ /* You can add global styles to this file, and also import other style files */ @import "flag-icon"; @import "material-design-icons/iconfont/material-icons.css"; -@import "materialize-css/dist/css/materialize.css"; +@import '~@angular/material/prebuilt-themes/indigo-pink.css'; * { box-sizing: border-box; @@ -167,4 +167,4 @@ h2 { @import "global/modal.less"; @import "global/search.less"; @import "global/toast.less"; -@import "global/chip.less"; \ No newline at end of file +@import "global/chip.less"; diff --git a/src/angular/vendor.aot.ts b/src/angular/vendor.aot.ts index 385b414a..81a0ce29 100644 --- a/src/angular/vendor.aot.ts +++ b/src/angular/vendor.aot.ts @@ -7,15 +7,9 @@ import '@angular/common/http'; import '@angular/router'; // RxJS import 'rxjs'; -import 'materialize-css'; import 'crypto-js'; import 'chart.js'; import 'chartjs-plugin-annotation'; // Other vendors for example jQuery, Lodash or Bootstrap // You can import js, ts, css, sass, ... - -// angular2-materialize is still on materialize-css v0.100.1 and requires global variable called 'Materialize' -// while this app is now on materialize-css v1.0.0 which renamed the variable from 'Materialize' to 'M'. -// The fix below makes angular2-materialize work with materialize-css v1.0.0 -window['Materialize'] = M; diff --git a/src/angular/vendor.ts b/src/angular/vendor.ts index 5694a26e..09c39319 100644 --- a/src/angular/vendor.ts +++ b/src/angular/vendor.ts @@ -1,5 +1,3 @@ -// import './polyfills.ts'; - // Angular import '@angular/platform-browser'; import '@angular/platform-browser-dynamic'; @@ -14,7 +12,6 @@ import 'rxjs'; // Other vendors for example jQuery, Lodash or Bootstrap // You can import js, ts, css, sass, ... -import 'materialize-css'; import 'crypto-js'; import 'chart.js'; -import 'chartjs-plugin-annotation'; \ No newline at end of file +import 'chartjs-plugin-annotation'; diff --git a/src/main/resources/webapp/webapp.ejs b/src/main/resources/webapp/webapp.ejs index 4b1544f5..16e7752c 100644 --- a/src/main/resources/webapp/webapp.ejs +++ b/src/main/resources/webapp/webapp.ejs @@ -55,7 +55,7 @@ var XPCONFIG = { locale: '{{{locale}}}', countryIsoCode: '{{{countryIsoCode}}}', - {{#user}}user: {{{.}}},{{/user}} + {{#user}}user: {{{.}}},{{/user}} {{#content}}content: { name: '{{_name}}', type: '{{type}}' @@ -78,7 +78,7 @@ .then(registerServiceWorker) .then(postAssets); } - + function registerServiceWorker(registration) { if (!!registration && registration.active) { console.log('Detected active Service Worker with scope ' + registration.scope); @@ -95,9 +95,9 @@ console.log('Service Worker registration failure.'); console.log(err); }); - } + } } - + function postAssets(registration) { let serviceWorker = registration.installing || registration.active; if (serviceWorker) { @@ -117,17 +117,12 @@ }); } } - return registration; + return registration; } - <% for (var chunk in htmlWebpackPlugin.files.js) { %> <% } %> - - \ No newline at end of file +