Bejelentkezés, termék model+bootstrap

This commit is contained in:
Norbi Peti 2023-05-06 22:26:00 +02:00
parent 12e9601109
commit e8ccd3fff8
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
21 changed files with 1343 additions and 87 deletions

View file

@ -25,6 +25,7 @@
"src/assets"
],
"styles": [
"@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.css"
],
"scripts": []
@ -87,6 +88,7 @@
"src/assets"
],
"styles": [
"@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.css"
],
"scripts": []

863
client/package-lock.json generated
View file

@ -9,10 +9,12 @@
"version": "0.0.0",
"dependencies": {
"@angular/animations": "^16.0.0",
"@angular/cdk": "^16.0.0",
"@angular/common": "^16.0.0",
"@angular/compiler": "^16.0.0",
"@angular/core": "^16.0.0",
"@angular/forms": "^16.0.0",
"@angular/material": "^16.0.0",
"@angular/platform-browser": "^16.0.0",
"@angular/platform-browser-dynamic": "^16.0.0",
"@angular/router": "^16.0.0",
@ -260,6 +262,46 @@
"@angular/core": "16.0.0"
}
},
"node_modules/@angular/cdk": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-16.0.0.tgz",
"integrity": "sha512-3hiNRB5kBOYv+MJRlpLX++KzY96mTivE7BXM/pNoR4Hiq7aBnoCtp0zbTc9J7gPn8POX6t/4WfAogslbkvQXSg==",
"dependencies": {
"tslib": "^2.3.0"
},
"optionalDependencies": {
"parse5": "^7.1.2"
},
"peerDependencies": {
"@angular/common": "^16.0.0 || ^17.0.0",
"@angular/core": "^16.0.0 || ^17.0.0",
"rxjs": "^6.5.3 || ^7.4.0"
}
},
"node_modules/@angular/cdk/node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"optional": true,
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/@angular/cdk/node_modules/parse5": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
"integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
"optional": true,
"dependencies": {
"entities": "^4.4.0"
},
"funding": {
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
"node_modules/@angular/cli": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.0.0.tgz",
@ -427,6 +469,70 @@
"rxjs": "^6.5.3 || ^7.4.0"
}
},
"node_modules/@angular/material": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/@angular/material/-/material-16.0.0.tgz",
"integrity": "sha512-FIkBjcygdgN0vDnO+e3dWrjw/+U805zGC9dh7lwSkpbgQp89ZYVk4Wygk5+I6oSKn1oR9GJpIe/j8+kP6CMA4w==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/auto-init": "15.0.0-canary.51f9c0c28.0",
"@material/banner": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/button": "15.0.0-canary.51f9c0c28.0",
"@material/card": "15.0.0-canary.51f9c0c28.0",
"@material/checkbox": "15.0.0-canary.51f9c0c28.0",
"@material/chips": "15.0.0-canary.51f9c0c28.0",
"@material/circular-progress": "15.0.0-canary.51f9c0c28.0",
"@material/data-table": "15.0.0-canary.51f9c0c28.0",
"@material/density": "15.0.0-canary.51f9c0c28.0",
"@material/dialog": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/drawer": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/fab": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/floating-label": "15.0.0-canary.51f9c0c28.0",
"@material/form-field": "15.0.0-canary.51f9c0c28.0",
"@material/icon-button": "15.0.0-canary.51f9c0c28.0",
"@material/image-list": "15.0.0-canary.51f9c0c28.0",
"@material/layout-grid": "15.0.0-canary.51f9c0c28.0",
"@material/line-ripple": "15.0.0-canary.51f9c0c28.0",
"@material/linear-progress": "15.0.0-canary.51f9c0c28.0",
"@material/list": "15.0.0-canary.51f9c0c28.0",
"@material/menu": "15.0.0-canary.51f9c0c28.0",
"@material/menu-surface": "15.0.0-canary.51f9c0c28.0",
"@material/notched-outline": "15.0.0-canary.51f9c0c28.0",
"@material/radio": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/segmented-button": "15.0.0-canary.51f9c0c28.0",
"@material/select": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/slider": "15.0.0-canary.51f9c0c28.0",
"@material/snackbar": "15.0.0-canary.51f9c0c28.0",
"@material/switch": "15.0.0-canary.51f9c0c28.0",
"@material/tab": "15.0.0-canary.51f9c0c28.0",
"@material/tab-bar": "15.0.0-canary.51f9c0c28.0",
"@material/tab-indicator": "15.0.0-canary.51f9c0c28.0",
"@material/tab-scroller": "15.0.0-canary.51f9c0c28.0",
"@material/textfield": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tooltip": "15.0.0-canary.51f9c0c28.0",
"@material/top-app-bar": "15.0.0-canary.51f9c0c28.0",
"@material/touch-target": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.3.0"
},
"peerDependencies": {
"@angular/animations": "^16.0.0 || ^17.0.0",
"@angular/cdk": "16.0.0",
"@angular/common": "^16.0.0 || ^17.0.0",
"@angular/core": "^16.0.0 || ^17.0.0",
"@angular/forms": "^16.0.0 || ^17.0.0",
"@angular/platform-browser": "^16.0.0 || ^17.0.0",
"rxjs": "^6.5.3 || ^7.4.0"
}
},
"node_modules/@angular/platform-browser": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-16.0.0.tgz",
@ -2746,6 +2852,758 @@
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
"dev": true
},
"node_modules/@material/animation": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/animation/-/animation-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-YNCPsf7yoRmduOd+7H+PlQNci7gdvjkae92XQTY8cnYFy9XTbgFCmwCbJQn5AgxHtVuMssKl2sroszgUmF9aoQ==",
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/@material/auto-init": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/auto-init/-/auto-init-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-U75Y3Pm0OfKi2b8UUsWn+X7s+LGutqisOtgFytPJ1Su4UcB8Mh3nr/4+MOdb3DT0Z1bNdq+43JhEjTi9oijibg==",
"dependencies": {
"@material/base": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/banner": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/banner/-/banner-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-y5Q0MpuiGpIIN9UldCEv2eliYq0pHLTHkqHnjAsImzHRT8vnCqIQeeROwOlrLwBl3u/kpeLhSZzJ1w9OPkZeRQ==",
"dependencies": {
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/button": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tokens": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/base": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/base/-/base-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-nqFSLpkBRlTNS0Z2ydJQtghRH8Hz3gUexQG/mP+pBv8afqOc0teHwug3M5btdteoXmCHiRpDkP/CHbbZclClHg==",
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/@material/button": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/button/-/button-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-eLiLRm8uKERgpnnoUKaG98O5Kh5lQljaAWz/RBiKiwia+przJSikMtsBrBMV8BrwKg5wOIFUrUsJOP0q2YcYyw==",
"dependencies": {
"@material/density": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/focus-ring": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tokens": "15.0.0-canary.51f9c0c28.0",
"@material/touch-target": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/card": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/card/-/card-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-scGd0XzNNarVk8S0InGbpX04ApYYoRND5udDx1vRtU2jzu97j39dd+cwusLWtrtR+FGrS7C4A7yA08NI9BoTEQ==",
"dependencies": {
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tokens": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/checkbox": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/checkbox/-/checkbox-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-GEqx+GQcgslxRLsLpbj/ddd4rSgCQxtikkvnKUBd8nw2bvNm/6HUXGl8IaTU2nj36SS5zNLdiDJLRI+k+G4C6g==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/density": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/focus-ring": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/touch-target": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/chips": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/chips/-/chips-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-a3lGEXw/Y1+KqMuvakzcb9rCis5R+eLQ7uHSrC0WjGgX1oU9gWpM0/p05/rTknHbIji5sOHr4SxC48cRCBCSSA==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/checkbox": "15.0.0-canary.51f9c0c28.0",
"@material/density": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/focus-ring": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tokens": "15.0.0-canary.51f9c0c28.0",
"@material/touch-target": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"safevalues": "^0.3.4",
"tslib": "^2.1.0"
}
},
"node_modules/@material/circular-progress": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/circular-progress/-/circular-progress-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-ApIq1SK5B0aYqsyKc7byzWVYg0zk9uFziryBOAKfyd96caG7BfzEfheOWK2PPEQGo9cA/m08ZZJzz6JDmJNMLA==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/progress-indicator": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/data-table": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/data-table/-/data-table-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-5TajNrJqVqr49PeyHSXf3YzPpAF2xPz4/r2TaPbLd/gvw9/z7dN7QiiQkSQ15oYzjueRwh+JHMwLfY5gakWC2Q==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/checkbox": "15.0.0-canary.51f9c0c28.0",
"@material/density": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/icon-button": "15.0.0-canary.51f9c0c28.0",
"@material/linear-progress": "15.0.0-canary.51f9c0c28.0",
"@material/list": "15.0.0-canary.51f9c0c28.0",
"@material/menu": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/select": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tokens": "15.0.0-canary.51f9c0c28.0",
"@material/touch-target": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/density": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/density/-/density-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-7hc7vuh4RajlgNTtHYWZzUeMC6A7w4ePJGavslqAawPb84bo0M/3Idm6OmoW1c6dyDcQo59KOiHMsmnlgDWdjg==",
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/@material/dialog": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/dialog/-/dialog-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-60o18+BmPLoGLLZeJVEwexYr89dsZGVCRC0N3zASQTNVz3XWtyjgeragAoly4NTUIICJ4PMRjMEH7YhJ/Qg/BA==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/button": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/icon-button": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tokens": "15.0.0-canary.51f9c0c28.0",
"@material/touch-target": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/dom": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/dom/-/dom-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-SiJRfAgfBBffWVuc5yvaYiRqjli7+4Mx2BYZ69AT8J5k6Uj0Lt8ppd3T3a0zhfF0EXwTlHdeunP+X0keQFcRdw==",
"dependencies": {
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/drawer": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/drawer/-/drawer-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-GXq6jHZHMX/6A0z1YEYkI9809sxC/r7g/uJxF3CWC9/8/d2TRYRATAccnllgsyK06XhrnFPf6DtXhyPr1icOzQ==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/list": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/elevation": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-bBsfYZBi/k380Cdxob+xnNhrmy6OZ/7k3q3xfT9gjWqE7TveAkOukLfMkRMyIltdl40jI7G9ewoW4oN8F0qOmg==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/fab": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/fab/-/fab-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-QRanDJSZDMxMXcIyXWfspSXb31iusve9fB6D4SgeJ1/bZsvy/I3t9wXyl06sJBYJhRzIXOiORyoVUjal/OPCpg==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/focus-ring": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tokens": "15.0.0-canary.51f9c0c28.0",
"@material/touch-target": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/feature-targeting": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/feature-targeting/-/feature-targeting-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-ebWpsBhpOU3uwu46OsT4Gv7OUjPP9eQV17b5Ze5y8yYn3FcdKyZI3nBQH7gjlOpH0xhz6DNq/Dx1z7DVL5/3NQ==",
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/@material/floating-label": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/floating-label/-/floating-label-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-4T1uKFXIUAg6lP2+kY6QcHdIl6exqsgDkOUlkPnAvXUZmGWnL9NlTSv3c6hdTcattM8XfcdPrjHozS1ltiIiFA==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/focus-ring": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/focus-ring/-/focus-ring-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-QGGMoJf38IHwHSWUxvcsiB3AOfZ7RtqF1NNwQOy7dTycXwzpf7gA+tYlbr4KFHg5rz0PBd6C7yAdPRK+RAO+Eg==",
"dependencies": {
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0"
}
},
"node_modules/@material/form-field": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/form-field/-/form-field-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-sHn97Z9f9YUioeGve/EANIAqddH4YslybHbFTMFx9AA4CyFITEXuNI7GC7J7BzkI10rcjmatWUGx0JRal1kVGw==",
"dependencies": {
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/icon-button": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/icon-button/-/icon-button-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-/qJscrbn45yZN+yno0NHBdHGttJ/0kgOIY34OIb9LeGDnVe+snsWrA8DkiaPeYJTLge+ACtgfDdk/iN+6vvckg==",
"dependencies": {
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/density": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/focus-ring": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/touch-target": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/image-list": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/image-list/-/image-list-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-4IhKYtrF7qA2e7qKt1B1XXg9mEJy7eyoWO0iQrqK8jtYyAaDMmsi24fAvlubczO+Qj02RFCqPCO2j23RCojYnA==",
"dependencies": {
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/layout-grid": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/layout-grid/-/layout-grid-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-ihb7N9hLB4CSbrGC2b70zaFMiJo8DJTZAy99AmAdtpo9CdGlkXDxlyEDYI+NkFHMeyoL85m9dEqGgLgiEGlO5Q==",
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/@material/line-ripple": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/line-ripple/-/line-ripple-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-4LNf92KjQ+RnPv3qb9R4gwO0zWMbMfCYnuvA7mXysRChL8f/3uuvTLySRuobMeE8HndErAMylHdWdtgTQ+6GSw==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/linear-progress": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/linear-progress/-/linear-progress-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-Aoi03JbUspj+08fLx2Y72jguD3uYkXHE9RNk9R2cqcjtahzGDdL7tDCZEqzmepSvdnDezHsWIBvkiLHuJP7WGA==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/progress-indicator": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/list": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/list/-/list-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-hMxDwAgs3NMi5z6XZvBjiopmdkApWZlKt1EOurPyuMDAKu/f0Dpu4lttNXmC1Qhg/Z82inMxUgYVWv4eMok4cQ==",
"dependencies": {
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/density": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tokens": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/menu": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/menu/-/menu-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-Ua2KDrT+VW6a270QNXqHwC/WU0oO88THXV8XV50kZtFHipe70ZB8sBcqKYM3zntbhI0q05Dl+R+z1icJhpw2hA==",
"dependencies": {
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/list": "15.0.0-canary.51f9c0c28.0",
"@material/menu-surface": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tokens": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/menu-surface": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/menu-surface/-/menu-surface-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-aDGmwcZ2nI5E+gJ7jn7QrihJ2p33nU5EuKs9cpBZSmYZKm1wcfFcb2CR07ui1WBT/zaZ9CNaXnIdcJsKY76mSg==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/notched-outline": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/notched-outline/-/notched-outline-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-5fXgCxrEjoV9WKN2+4ru1mA8OIbnrrK/Zq5RT6QJgAbW/YRyMjtMZKIIbGhlL62/q4pZQCbYZaMmDskTkhiylg==",
"dependencies": {
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/floating-label": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/progress-indicator": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/progress-indicator/-/progress-indicator-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-teQwuo+45CKDRT17Ly9DOYJBHfoIJhGYbRsTCjgm6yGfWER3htP77NseTD8w1iaVHM09D9hjhvji3BQGD5s6Pg==",
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/@material/radio": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/radio/-/radio-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-8zYl1iQz4E8l+iI9m2rnf1pO7wZJZdvXjxjk6Wx608Rac5ntPFn8ky8eBVRa3AnCLFJlLMPRfGPwCO8TJQutKg==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/density": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/focus-ring": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/touch-target": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/ripple": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-q5Qk3a5kxlC3zvVRfDfpJBXMjPReey/xCFgov9NskbYyAWvGDUkizHxQqdBpZtaczMgFLG4locaM7lHCD6sGgw==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/rtl": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-osFXl265Tg0tMiLts31UBeV+hRogXdDclsMRDrIsfs1faSXkBANFf8pPBk9Iyo70zx3X4fhFDY0PnsIkex3kug==",
"dependencies": {
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/segmented-button": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/segmented-button/-/segmented-button-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-rYIyfIzf/Ev2d1/4OwkmzGvZ/jlQZDwR6i1FJA7pYbpYyVAI+8CxBL0ea02iUZfvTG8KQcx0fBW5HOlYSHayYQ==",
"dependencies": {
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/touch-target": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/select": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/select/-/select-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-DpfJ3ZgMEGfgRLDniGmkNlG/Wwrmd6wYI1bQiq2GhlkA3vsDCuCa/EyNkCDTCqhPDUzvWVJOH3kqUm4piSyDrA==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/density": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/floating-label": "15.0.0-canary.51f9c0c28.0",
"@material/line-ripple": "15.0.0-canary.51f9c0c28.0",
"@material/list": "15.0.0-canary.51f9c0c28.0",
"@material/menu": "15.0.0-canary.51f9c0c28.0",
"@material/menu-surface": "15.0.0-canary.51f9c0c28.0",
"@material/notched-outline": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tokens": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/shape": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/shape/-/shape-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-SdJEmNYyhvlITE2sZJuX3yygl/3l6N1Md4mKT2tclkY/eYf+HnHZRJvUpE2KnWMnIAvVdAljhU+eYZfalAvH7A==",
"dependencies": {
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/slider": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/slider/-/slider-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-LxZRzXMRjc9mmMz3PYY6QOl85WHH9AoBox3+kNaB5J7Q9J/LaCRdqHHpOvh05n+MVZcecaV+UdADxQ8dJbR0Fg==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tokens": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/snackbar": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/snackbar/-/snackbar-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-51MLSplWiVjzVoEEkvRFEqFu/q4ra6ai03/rG/em9kmr8VI0hpvyxLEZ4yIRue+7SSjt5Bsou3hUdL0Q8Q20iw==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/button": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/icon-button": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tokens": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/switch": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/switch/-/switch-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-kRTmekNkKkiHgKuLb/GcnPvZ2WVvoS5U66NxGsRhs2ixKbWwa6qsBtXc5V7kNEsUDVgetUG5xDLye+ofQoyxEg==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/density": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/focus-ring": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tokens": "15.0.0-canary.51f9c0c28.0",
"safevalues": "^0.3.4",
"tslib": "^2.1.0"
}
},
"node_modules/@material/tab": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/tab/-/tab-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-Z8tepFaE46qTjKi+NLb/tY6EXxFNxhx3VS4vGbC/ZktuQpPJx3POU1HHs7pQzhRIh6fDTreWAoXZo5WTj8miZg==",
"dependencies": {
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/focus-ring": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/tab-indicator": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tokens": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/tab-bar": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/tab-bar/-/tab-bar-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-C0lE3ye6QycNNTbzhgCe5lUj01Z5tZpm/BF/aw2z9N49cXVB0Ka59cn4jktOs7wTzoW0OQOilhs72/xf0PR7Cw==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/density": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/tab": "15.0.0-canary.51f9c0c28.0",
"@material/tab-indicator": "15.0.0-canary.51f9c0c28.0",
"@material/tab-scroller": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tokens": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/tab-indicator": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/tab-indicator/-/tab-indicator-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-C5DBeiVgR75+Du4MdSdfPmBJ/AYhMyvM2nG+2PBqR5h1recM5+ocypeEtmZI9foJaPRHypc3fNTW/mdxV7c3dA==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/tab-scroller": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/tab-scroller/-/tab-scroller-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-00JZXIbnVvrRPoY6N4MNlS/L2sHZOCj8tzCLEszJZCg722onlN8YDyCh51t0mdcfzw5N1ULvGnsa5BpeWeW3vw==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/tab": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/textfield": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/textfield/-/textfield-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-e8HjmBiRFI7/4Sg6c8XsshYLZsLn7qwKrJZWR7gA9LcYCJZDN1zaOVC5/Cx6lwS+R/hShtJh85ob3HJhdKmKRw==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/density": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/floating-label": "15.0.0-canary.51f9c0c28.0",
"@material/line-ripple": "15.0.0-canary.51f9c0c28.0",
"@material/notched-outline": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tokens": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/theme": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/theme/-/theme-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-E9W/SM3YAsz4qfYuNZby9bq4TvrgPEjsDitj842FmlTmHXZIoQqizvnX6mtzGq+aPmlSF+nDG+uSJTg37kVQWA==",
"dependencies": {
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/tokens": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/tokens/-/tokens-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-rXjIFqfos9M60J9oYgbRA784I2JtTL7WvFHH6c4i3vIFnGwJiC57ovju5jF2OaAyrB5GuUNRVRaJw1CSn5bzvA==",
"dependencies": {
"@material/elevation": "15.0.0-canary.51f9c0c28.0"
}
},
"node_modules/@material/tooltip": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/tooltip/-/tooltip-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-Lvh/Yjmh2wLSFp6p/S6PWrbIQbWFNqAq9K7YAnjYaWLUfBznz/GmgJbWzIhwtTwLzA6eyCk84KY7Ldm4y6QXnA==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/button": "15.0.0-canary.51f9c0c28.0",
"@material/dom": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/tokens": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"safevalues": "^0.3.4",
"tslib": "^2.1.0"
}
},
"node_modules/@material/top-app-bar": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/top-app-bar/-/top-app-bar-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-ApTalnQcMMuoZ9r2wace2A3SUIfwOfHryFX/rzR00SG8VlXA+Hj4SFNeEQ7qQVPx0RL5supT3Ixz9MWaujdb3Q==",
"dependencies": {
"@material/animation": "15.0.0-canary.51f9c0c28.0",
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/elevation": "15.0.0-canary.51f9c0c28.0",
"@material/ripple": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/shape": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"@material/typography": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/touch-target": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/touch-target/-/touch-target-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-0O6TSukUJSscOQYlel1MTR63cEeX3XV6SQ/X1FIV+JkYxMof/stiIbWYF55FrWuiV8o4t0JCYHHwB7MPWvufVA==",
"dependencies": {
"@material/base": "15.0.0-canary.51f9c0c28.0",
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/rtl": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@material/typography": {
"version": "15.0.0-canary.51f9c0c28.0",
"resolved": "https://registry.npmjs.org/@material/typography/-/typography-15.0.0-canary.51f9c0c28.0.tgz",
"integrity": "sha512-54B9LQe1ueFwcjrh58C8FII/O9bflTWNMv3eZSaLwAFz4csNPXHkoLryFmMGbO99p04SsQ/xCjqLJedJCrpN3A==",
"dependencies": {
"@material/feature-targeting": "15.0.0-canary.51f9c0c28.0",
"@material/theme": "15.0.0-canary.51f9c0c28.0",
"tslib": "^2.1.0"
}
},
"node_modules/@ngtools/webpack": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.0.0.tgz",
@ -9895,6 +10753,11 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true
},
"node_modules/safevalues": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/safevalues/-/safevalues-0.3.4.tgz",
"integrity": "sha512-LRneZZRXNgjzwG4bDQdOTSbze3fHm1EAKN/8bePxnlEZiBmkYEDggaHbuvHI9/hoqHbGfsEA7tWS9GhYHZBBsw=="
},
"node_modules/sass": {
"version": "1.62.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.62.1.tgz",

View file

@ -11,10 +11,12 @@
"private": true,
"dependencies": {
"@angular/animations": "^16.0.0",
"@angular/cdk": "^16.0.0",
"@angular/common": "^16.0.0",
"@angular/compiler": "^16.0.0",
"@angular/core": "^16.0.0",
"@angular/forms": "^16.0.0",
"@angular/material": "^16.0.0",
"@angular/platform-browser": "^16.0.0",
"@angular/platform-browser-dynamic": "^16.0.0",
"@angular/router": "^16.0.0",
@ -35,4 +37,4 @@
"karma-jasmine-html-reporter": "~2.0.0",
"typescript": "~5.0.2"
}
}
}

View file

@ -0,0 +1,5 @@
.loginbox:host {
display: flex;
flex-direction: column;
align-items: flex-start;
}

View file

@ -1,21 +1,21 @@
<div *ngIf="userService.user">
<div *ngIf="userService.user; else login" class="loginbox" style="margin: 20px">
Üdv {{ userService.user.username }}
</div>
<ng-template #login>
<form>
<div>
Felhasználónév:
<input type="text" name="username">
</div>
<div>
Jelszó:
<input type="password" name="password">
</div>
<button>Bejelentkezés</button>
<div>
<button>Regisztráció</button>
</div>
</form>
<div class="loginbox">
<form [formGroup]="loginForm">
<mat-form-field appearance="fill">
<mat-label>Felhasználónév</mat-label>
<input matInput formControlName="username">
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Jelszó</mat-label>
<input matInput type="password" formControlName="password">
</mat-form-field>
<button mat-button class="mat-primary" (click)="doLogin()">Bejelentkezés</button>
<button mat-button>Regisztráció</button>
</form>
</div>
</ng-template>
<h1>Termékek</h1>

View file

@ -1,12 +1,34 @@
import { Component } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { UserService } from './services/user.service';
import { FormControl, FormGroup } from '@angular/forms';
import { Router } from '@angular/router';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(public userService: UserService) {
export class AppComponent implements OnInit {
loginForm = new FormGroup({
username: new FormControl(),
password: new FormControl()
});
constructor(public userService: UserService, private router: Router) {
}
ngOnInit() {
if (!this.userService.user) {
this.userService.getCurrentUser();
}
}
async doLogin() {
try {
await this.userService.login(this.loginForm.value.username, this.loginForm.value.password);
} catch (e: any) {
console.log("Hiba:", e);
alert("Hiba: " + (e?.error?.error ?? JSON.stringify(e)));
}
}
}

View file

@ -2,13 +2,33 @@ import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatButtonModule } from '@angular/material/button';
import { ReactiveFormsModule } from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ProductListComponent } from './product-list/product-list.component';
import { MatTableModule } from '@angular/material/table';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatSortModule } from '@angular/material/sort';
import { HttpClientModule } from '@angular/common/http';
@NgModule({
declarations: [
AppComponent
AppComponent,
ProductListComponent
],
imports: [
BrowserModule
BrowserModule,
MatFormFieldModule,
MatButtonModule,
ReactiveFormsModule,
MatInputModule,
BrowserAnimationsModule,
MatTableModule,
MatPaginatorModule,
MatSortModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]

View file

@ -0,0 +1,111 @@
import { DataSource } from '@angular/cdk/collections';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { map } from 'rxjs/operators';
import { Observable, of as observableOf, merge } from 'rxjs';
// TODO: Replace this with your own data model type
export interface ProductListItem {
name: string;
id: number;
}
// TODO: replace this with real data from your application
const EXAMPLE_DATA: ProductListItem[] = [
{id: 1, name: 'Hydrogen'},
{id: 2, name: 'Helium'},
{id: 3, name: 'Lithium'},
{id: 4, name: 'Beryllium'},
{id: 5, name: 'Boron'},
{id: 6, name: 'Carbon'},
{id: 7, name: 'Nitrogen'},
{id: 8, name: 'Oxygen'},
{id: 9, name: 'Fluorine'},
{id: 10, name: 'Neon'},
{id: 11, name: 'Sodium'},
{id: 12, name: 'Magnesium'},
{id: 13, name: 'Aluminum'},
{id: 14, name: 'Silicon'},
{id: 15, name: 'Phosphorus'},
{id: 16, name: 'Sulfur'},
{id: 17, name: 'Chlorine'},
{id: 18, name: 'Argon'},
{id: 19, name: 'Potassium'},
{id: 20, name: 'Calcium'},
];
/**
* Data source for the ProductList view. This class should
* encapsulate all logic for fetching and manipulating the displayed data
* (including sorting, pagination, and filtering).
*/
export class ProductListDataSource extends DataSource<ProductListItem> {
data: ProductListItem[] = EXAMPLE_DATA;
paginator: MatPaginator | undefined;
sort: MatSort | undefined;
constructor() {
super();
}
/**
* Connect this data source to the table. The table will only update when
* the returned stream emits new items.
* @returns A stream of the items to be rendered.
*/
connect(): Observable<ProductListItem[]> {
if (this.paginator && this.sort) {
// Combine everything that affects the rendered data into one update
// stream for the data-table to consume.
return merge(observableOf(this.data), this.paginator.page, this.sort.sortChange)
.pipe(map(() => {
return this.getPagedData(this.getSortedData([...this.data ]));
}));
} else {
throw Error('Please set the paginator and sort on the data source before connecting.');
}
}
/**
* Called when the table is being destroyed. Use this function, to clean up
* any open connections or free any held resources that were set up during connect.
*/
disconnect(): void {}
/**
* Paginate the data (client-side). If you're using server-side pagination,
* this would be replaced by requesting the appropriate data from the server.
*/
private getPagedData(data: ProductListItem[]): ProductListItem[] {
if (this.paginator) {
const startIndex = this.paginator.pageIndex * this.paginator.pageSize;
return data.splice(startIndex, this.paginator.pageSize);
} else {
return data;
}
}
/**
* Sort the data (client-side). If you're using server-side sorting,
* this would be replaced by requesting the appropriate data from the server.
*/
private getSortedData(data: ProductListItem[]): ProductListItem[] {
if (!this.sort || !this.sort.active || this.sort.direction === '') {
return data;
}
return data.sort((a, b) => {
const isAsc = this.sort?.direction === 'asc';
switch (this.sort?.active) {
case 'name': return compare(a.name, b.name, isAsc);
case 'id': return compare(+a.id, +b.id, isAsc);
default: return 0;
}
});
}
}
/** Simple sort comparator for example ID/Name columns (for client-side sorting). */
function compare(a: string | number, b: string | number, isAsc: boolean): number {
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}

View file

@ -0,0 +1,3 @@
.full-width-table {
width: 100%;
}

View file

@ -0,0 +1,26 @@
<div class="mat-elevation-z8">
<table mat-table class="full-width-table" matSort aria-label="Elements">
<!-- Id Column -->
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Id</th>
<td mat-cell *matCellDef="let row">{{row.id}}</td>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
<td mat-cell *matCellDef="let row">{{row.name}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator #paginator
[length]="dataSource?.data?.length"
[pageIndex]="0"
[pageSize]="10"
[pageSizeOptions]="[5, 10, 20]"
aria-label="Select page">
</mat-paginator>
</div>

View file

@ -0,0 +1,34 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { ProductListComponent } from './product-list.component';
describe('ProductListComponent', () => {
let component: ProductListComponent;
let fixture: ComponentFixture<ProductListComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ProductListComponent],
imports: [
NoopAnimationsModule,
MatPaginatorModule,
MatSortModule,
MatTableModule,
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ProductListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should compile', () => {
expect(component).toBeTruthy();
});
});

View file

@ -0,0 +1,30 @@
import { AfterViewInit, Component, ViewChild } from '@angular/core';
import { MatTable } from '@angular/material/table';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { ProductListDataSource, ProductListItem } from './product-list-datasource';
@Component({
selector: 'app-product-list',
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements AfterViewInit {
@ViewChild(MatPaginator) paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;
@ViewChild(MatTable) table!: MatTable<ProductListItem>;
dataSource: ProductListDataSource;
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['id', 'name'];
constructor() {
this.dataSource = new ProductListDataSource();
}
ngAfterViewInit(): void {
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
this.table.dataSource = this.dataSource;
}
}

View file

@ -1,5 +1,8 @@
import { Injectable } from '@angular/core';
import { User } from '../model/user.model';
import { FormControl, ɵFormGroupValue, ɵTypedOrUntyped } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { firstValueFrom } from 'rxjs';
@Injectable({
providedIn: 'root'
@ -7,13 +10,26 @@ import { User } from '../model/user.model';
export class UserService {
private _user: User | undefined;
get user() {
get user(): User | undefined {
return this._user;
}
constructor() { }
constructor(private http: HttpClient) { }
login() {
async login(username: string, password: string) {
const user = await firstValueFrom(this.http.post('/api/users/login', {username, password}));
this._user = user as User;
}
async getCurrentUser() {
try {
const user = await firstValueFrom(this.http.get('/api/users/status'));
this._user = user as User;
} catch (e: any) {
if (e?.error?.error?.status !== 'NOTOK') {
console.log("Failed to get user:", e);
}
this._user = undefined;
}
}
}

View file

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

View file

@ -1 +1,4 @@
/* You can add global styles to this file, and also import other style files */
html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }

View file

@ -1,5 +1,6 @@
const mongoose = require('mongoose');
const User = mongoose.model('user');
const Product = require('./productSchema')
async function ensureAdminExists() {
try {
@ -22,4 +23,21 @@ async function ensureAdminExists() {
}
}
module.exports = ensureAdminExists;
async function boot() {
await ensureAdminExists();
if (await Product.exists({})) {
console.log("A termékek már léteznek");
return;
}
for (let i = 0; i < 20; i++) {
const product = new Product({
name: `Teszt termék${i}`,
price: Math.floor(500+Math.random()*500),
description: `Teszt leirás${i}`
});
await product.save();
}
console.log("Termékek sikeresen létrehozva!");
}
module.exports = boot;

View file

@ -1,7 +1,7 @@
const mongoose = require('mongoose');
const productSchema = new mongoose.Schema({
username: {
name: {
type: String,
/* támogatott típusok: String, Number, Date, Buffer, Boolean, Mixed, ObjectId,
Array, Decimal128, Map, Schema - az utolsóval valósítható meg az egymásba ágyazás, tehát hogy az egyik dokumentum
@ -9,49 +9,28 @@ const productSchema = new mongoose.Schema({
required: true,
unique : true
},
password: {
price: {
type: Number,
required: true,
default: 1000,
},
description: {
type: String,
required: true,
},
accessLevel: {
type: Number,
required: true,
default: 1,
},
birthdate: {
type: Date,
required: true,
},
});
userSchema.pre('save', function(next) {
const user = this;
if(user.isModified('password')) {
bcrypt.genSalt(10, function(err, salt) {
if(err) {
console.log('hiba a salt generalasa soran');
return next(err);
}
bcrypt.hash(user.password, salt, function(error, hash) {
if(error) {
console.log('hiba a hasheles soran');
return next(error);
}
user.password = hash;
return next();
})
})
} else {
return next();
id: {
type: String,
}
});
userSchema.methods.comparePasswords = function(password, nx) {
bcrypt.compare(password, this.password, function(err, isMatch) {
nx(err, isMatch);
});
};
productSchema.pre('save', function(next) {
const product = this;
if(product.isModified('name')) {
product.name = product.name.replaceAll(/[ !?$.,-]/g, '');
}
return next();
});
const User = mongoose.model('user', userSchema);
const Product = mongoose.model('product', productSchema);
module.exports = User;
module.exports = Product;

View file

@ -30,39 +30,33 @@ app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
passport.use('local', new LocalStrategy({}, function (username, password, done) {
User.findOne({ username: username }, function (err, user) {
if (err) return done('Hiba lekeres soran', null);
if (!user) return done('Nincs ilyen felhasználónév', null);
user.comparePasswords(password, function (error, isMatch) {
if (error) return done(error, false);
if (!isMatch) return done('Hibas jelszo', false);
return done(null, user);
});
passport.use('local', new LocalStrategy({}, async function (username, password, done) {
const user = await User.findOne({ username: username }).catch(() => done('Hiba lekeres soran', null));
if (!user) return done('Nincs ilyen felhasználónév', null);
user.comparePasswords(password, function (error, isMatch) {
if (error) return done(error, false);
if (!isMatch) return done('Hibás jelszó', false);
return done(null, user);
});
}));
passport.serializeUser(function (user, done) {
if (!user) return done('nincs megadva beléptethető felhasználó', null);
if (!user) return done('nincs megadva szerializálható felhasználó', null);
return done(null, user);
});
passport.deserializeUser(function (user, done) {
if (!user) return done("nincs user akit kiléptethetnénk", null);
if (!user) return done("nincs megadva deszerializálható felhasználó", null);
return done(null, user);
});
app.use(expressSession({ secret: 'prf2021lassananodejsvegereerunk', resave: true, saveUninitialized: false }));
app.use(expressSession({ secret: 'prfcheesecrescentmc', resave: true, saveUninitialized: false }));
app.use(passport.initialize({}));
app.use(passport.session({}));
app.use((req, res, next) => {
console.log('A middleware futott!')
next()
});
app.use('/api/users', require('./usersRouter'))
app.use('/api/products', require('./productsRouter'))
app.use('', express.static('public'))

View file

@ -4,7 +4,7 @@
"description": "",
"main": "index.js",
"scripts": {
"start": "node .",
"start": "node --watch .",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],

105
server/productsRouter.js Normal file
View file

@ -0,0 +1,105 @@
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const Product = mongoose.model('product');
const passport = require('passport');
function getProductData(product) {
return {name: product.name, price: product.price, description: product.description, id: product.id};
}
async function getProduct(req, res, next) {
try {
const product = await Product.findById(req.params.id);
if (product == null) {
return res.status(404).json({ message: 'A termék nem található' });
}
res.product = product;
next();
} catch (error) {
return res.status(500).json({ message: error.message });
}
}
// GET /products - összes termék lekérdezése
router.get('/', async (req, res) => {
if (!req.isAuthenticated()) {
return res.status(403).json({ message: "Unauthenticated" });
}
try {
const products = await Product.find();
res.status(200).json(products);
} catch (error) {
res.status(500).json({ message: error.message });
}
});
// GET /products/:id - egy termék lekérdezése az id alapján
router.get('/:id', getProduct, (req, res) => {
if (!req.isAuthenticated()) {
return res.status(403).json({ message: "Unauthenticated" });
}
res.json(res.product);
});
// POST /products - új termék létrehozása
router.post('/', async (req, res) => {
if (!req.isAuthenticated()) {
return res.status(403).json({ message: "Unauthenticated" });
}
const product = new Product({
name: req.body.name,
price: req.body.price,
description: req.body.description,
id: req.body.id,
});
try {
const newProduct = await product.save();
res.status(201).json(newProduct);
} catch (error) {
res.status(400).json({ message: error.message });
}
});
// PATCH /products/:id - egy termék frissítése az id alapján
router.patch('/:id', getProduct, async (req, res) => {
if (!req.isAuthenticated()) {
return res.status(403).json({ message: "Unauthenticated" });
}
if (req.body.name != null) {
res.product.name = req.body.name;
}
if (req.body.price != null) {
res.product.price = req.body.price;
}
if (req.body.description != null) {
res.product.description = req.body.description;
}
if (req.body.id != null) {
res.product.id = req.body.id;
}
try {
const updatedProduct = await res.product.save();
res.json(updatedProduct);
} catch (error) {
res.status(400).json({ message: error.message });
}
});
// DELETE /products/:id - egy termék törlése az id alapján
router.delete('/:id', getProduct, async (req, res) => {
if (!req.isAuthenticated()) {
return res.status(403).json({ message: "Unauthenticated" });
}
try {
await res.product.remove();
res.json({ message: 'A termék sikeresen törölve!' });
} catch (error) {
res.status(500).json({ message: error.message });
}
});
module.exports = router

View file

@ -5,13 +5,18 @@ const User = mongoose.model('user');
const passport = require('passport');
function getUserData(user) {
return {username: user.username, accessLevel: user.accessLevel, birthdate: user.birthdate};
}
router.route('/login').post((req, res) => {
console.log("Req body:", req.body);
if (req.body.username && req.body.password) {
passport.authenticate('local', {}, function (error, user) {
if (error) return res.status(500).send(error);
if (error) return res.status(500).send({error: error});
req.login(user, function (error) {
if (error) return res.status(500).send(error);
return res.status(200).send('Bejelentkezes sikeres');
return res.status(200).send(getUserData(user));
})
})(req, res);
} else {
@ -36,9 +41,9 @@ router.route('/logout').post((req, res) => {
router.route('/status').get((req, res) => {
if (req.isAuthenticated()) {
console.log(req.user)
return res.status(200).send(req.user);
return res.status(200).send(getUserData(req.user));
} else {
return res.status(403).send('Nem is volt bejelentkezve');
return res.status(403).send({status: "NOTOK"});
}
})
@ -57,6 +62,9 @@ async function getUser(req, res, next) {
// GET /users - összes felhasználó lekérdezése
router.get('/', async (req, res) => {
if (!req.isAuthenticated()) {
return res.status(403).json({ message: "Unauthenticated" });
}
try {
const users = await User.find();
res.status(200).json(users);
@ -67,11 +75,17 @@ router.get('/', async (req, res) => {
// GET /users/:id - egy felhasználó lekérdezése az id alapján
router.get('/:id', getUser, (req, res) => {
if (!req.isAuthenticated()) {
return res.status(403).json({ message: "Unauthenticated" });
}
res.json(res.user);
});
// POST /users - új felhasználó létrehozása
router.post('/', async (req, res) => {
if (!req.isAuthenticated()) {
return res.status(403).json({ message: "Unauthenticated" });
}
const user = new User({
username: req.body.username,
password: req.body.password,
@ -89,6 +103,9 @@ router.post('/', async (req, res) => {
// PATCH /users/:id - egy felhasználó frissítése az id alapján
router.patch('/:id', getUser, async (req, res) => {
if (!req.isAuthenticated()) {
return res.status(403).json({ message: "Unauthenticated" });
}
if (req.body.username != null) {
res.user.username = req.body.username;
}
@ -112,6 +129,9 @@ router.patch('/:id', getUser, async (req, res) => {
// DELETE /users/:id - egy felhasználó törlése az id alapján
router.delete('/:id', getUser, async (req, res) => {
if (!req.isAuthenticated()) {
return res.status(403).json({ message: "Unauthenticated" });
}
try {
await res.user.remove();
res.json({ message: 'A felhasználó sikeresen törölve!' });