add changes diffing modal & silence some logs
This commit is contained in:
parent
148488e2c4
commit
da353cec84
22 changed files with 1770 additions and 120 deletions
853
client/package-lock.json
generated
853
client/package-lock.json
generated
|
|
@ -9,10 +9,12 @@
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "^16.2.0",
|
"@angular/animations": "^16.2.0",
|
||||||
|
"@angular/cdk": "^16.2.12",
|
||||||
"@angular/common": "^16.2.0",
|
"@angular/common": "^16.2.0",
|
||||||
"@angular/compiler": "^16.2.0",
|
"@angular/compiler": "^16.2.0",
|
||||||
"@angular/core": "^16.2.0",
|
"@angular/core": "^16.2.0",
|
||||||
"@angular/forms": "^16.2.0",
|
"@angular/forms": "^16.2.0",
|
||||||
|
"@angular/material": "^16.2.12",
|
||||||
"@angular/platform-browser": "^16.2.0",
|
"@angular/platform-browser": "^16.2.0",
|
||||||
"@angular/platform-browser-dynamic": "^16.2.0",
|
"@angular/platform-browser-dynamic": "^16.2.0",
|
||||||
"@angular/router": "^16.2.0",
|
"@angular/router": "^16.2.0",
|
||||||
|
|
@ -350,6 +352,34 @@
|
||||||
"@angular/core": "16.2.5"
|
"@angular/core": "16.2.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@angular/cdk": {
|
||||||
|
"version": "16.2.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-16.2.12.tgz",
|
||||||
|
"integrity": "sha512-wT8/265zm2WKY0BDaRoYbrAT4kadrmejTRLjuimQIEUKnw4vBsJMWCwQkpFo3s6zr6eznGqYVAFb8KKPVLKGBg==",
|
||||||
|
"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/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": {
|
"node_modules/@angular/cli": {
|
||||||
"version": "16.2.2",
|
"version": "16.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.2.tgz",
|
||||||
|
|
@ -517,6 +547,70 @@
|
||||||
"rxjs": "^6.5.3 || ^7.4.0"
|
"rxjs": "^6.5.3 || ^7.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@angular/material": {
|
||||||
|
"version": "16.2.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@angular/material/-/material-16.2.12.tgz",
|
||||||
|
"integrity": "sha512-k1DGRfP1mMmhg/nLJjZBOPzX3SyAjgbRBY2KauKOV8OFCXJGoMn/oLgMBh+qB1WugzIna/31dBV8ruHD3Uvp2w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/auto-init": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/banner": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/button": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/card": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/checkbox": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/chips": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/circular-progress": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/data-table": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/density": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dialog": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/drawer": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/fab": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/floating-label": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/form-field": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/icon-button": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/image-list": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/layout-grid": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/line-ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/linear-progress": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/list": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/menu": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/menu-surface": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/notched-outline": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/radio": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/segmented-button": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/select": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/slider": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/snackbar": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/switch": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tab": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tab-bar": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tab-indicator": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tab-scroller": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/textfield": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tooltip": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/top-app-bar": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/touch-target": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.3.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/animations": "^16.0.0 || ^17.0.0",
|
||||||
|
"@angular/cdk": "16.2.12",
|
||||||
|
"@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": {
|
"node_modules/@angular/platform-browser": {
|
||||||
"version": "16.2.5",
|
"version": "16.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-16.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-16.2.5.tgz",
|
||||||
|
|
@ -2940,6 +3034,758 @@
|
||||||
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
|
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@material/animation": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/animation/-/animation-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-leRf+BcZTfC/iSigLXnYgcHAGvFVQveoJT5+2PIRdyPI/bIG7hhciRgacHRsCKC0sGya81dDblLgdkjSUemYLw==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/auto-init": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/auto-init/-/auto-init-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-uxzDq7q3c0Bu1pAsMugc1Ik9ftQYQqZY+5e2ybNplT8gTImJhNt4M2mMiMHbMANk2l3UgICmUyRSomgPBWCPIA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/banner": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/banner/-/banner-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-SHeVoidCUFVhXANN6MNWxK9SZoTSgpIP8GZB7kAl52BywLxtV+FirTtLXkg/8RUkxZRyRWl7HvQ0ZFZa7QQAyA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/button": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tokens": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/base": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/base/-/base-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-Fc3vGuOf+duGo22HTRP6dHdc+MUe0VqQfWOuKrn/wXKD62m0QQR2TqJd3rRhCumH557T5QUyheW943M3E+IGfg==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/button": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/button/-/button-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-3AQgwrPZCTWHDJvwgKq7Cj+BurQ4wTjDdGL+FEnIGUAjJDskwi1yzx5tW2Wf/NxIi7IoPFyOY3UB41jwMiOrnw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/density": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/focus-ring": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tokens": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/touch-target": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/card": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/card/-/card-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-nPlhiWvbLmooTnBmV5gmzB0eLWSgLKsSRBYAbIBmO76Okgz1y+fQNLag+lpm/TDaHVsn5fmQJH8e0zIg0rYsQA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tokens": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/checkbox": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/checkbox/-/checkbox-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-4tpNnO1L0IppoMF3oeQn8F17t2n0WHB0D7mdJK9rhrujen/fLbekkIC82APB3fdGtLGg3qeNqDqPsJm1YnmrwA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/density": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/focus-ring": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/touch-target": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/chips": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/chips/-/chips-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-fqHKvE5bSWK0bXVkf57MWxZtytGqYBZvvHIOs4JI9HPHEhaJy4CpSw562BEtbm3yFxxALoQknvPW2KYzvADnmA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/checkbox": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/density": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/focus-ring": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tokens": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/touch-target": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"safevalues": "^0.3.4",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/circular-progress": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/circular-progress/-/circular-progress-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-Lxe8BGAxQwCQqrLhrYrIP0Uok10h7aYS3RBXP41ph+5GmwJd5zdyE2t93qm2dyThvU6qKuXw9726Dtq/N+wvZQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/progress-indicator": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/data-table": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/data-table/-/data-table-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-j/7qplT9+sUpfe4pyWhPbl01qJA+OoNAG3VMJruBBR461ZBKyTi7ssKH9yksFGZ8eCEPkOsk/+kDxsiZvRWkeQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/checkbox": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/density": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/icon-button": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/linear-progress": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/list": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/menu": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/select": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tokens": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/touch-target": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/density": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/density/-/density-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-Zt3u07fXrBWLW06Tl5fgvjicxNQMkFdawLyNTzZ5TvbXfVkErILLePwwGaw8LNcvzqJP6ABLA8jiR+sKNoJQCg==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/dialog": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/dialog/-/dialog-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-o+9a/fmwJ9+gY3Z/uhj/PMVJDq7it1NTWKJn2GwAKdB+fDkT4hb9qEdcxMPyvJJ5ups+XiKZo03+tZrD+38c1w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/button": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/icon-button": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tokens": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/touch-target": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/dom": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/dom/-/dom-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-ly78R7aoCJtundSUu0UROU+5pQD5Piae0Y1MkN6bs0724azeazX1KeXFeaf06JOXnlr5/41ol+fSUPowjoqnOg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/drawer": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/drawer/-/drawer-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-PFL4cEFnt7VTxDsuspFVNhsFDYyumjU0VWfj3PWB7XudsEfQ3lo85D3HCEtTTbRsCainGN8bgYNDNafLBqiigw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/list": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/elevation": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-Ro+Pk8jFuap+T0B0shA3xI1hs2b89dNQ2EIPCNjNMp87emHKAzJfhKb7EZGIwv3+gFLlVaLyIVkb94I89KLsyg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/fab": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/fab/-/fab-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-dvU0KWMRglwJEQwmQtFAmJcAjzg9VFF6Aqj78bJYu/DAIGFJ1VTTTSgoXM/XCm1YyQEZ7kZRvxBO37CH54rSDg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/focus-ring": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tokens": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/touch-target": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/feature-targeting": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/feature-targeting/-/feature-targeting-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-wkDjVcoVEYYaJvun28IXdln/foLgPD7n9ZC9TY76GErGCwTq+HWpU6wBAAk+ePmpRFDayw4vI4wBlaWGxLtysQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/floating-label": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/floating-label/-/floating-label-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-bUWPtXzZITOD/2mkvLkEPO1ngDWmb74y0Kgbz6llHLOQBtycyJIpuoQJ1q2Ez0NM/tFLwPphhAgRqmL3YQ/Kzw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/focus-ring": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/focus-ring/-/focus-ring-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-cZHThVose3GvAlJzpJoBI1iqL6d1/Jj9hXrR+r8Mwtb1hBIUEG3hxfsRd4vGREuzROPlf0OgNf/V+YHoSwgR5w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/form-field": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/form-field/-/form-field-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-+JFXy5X44Gue1CbZZAQ6YejnI203lebYwL0i6k0ylDpWHEOdD5xkF2PyHR28r9/65Ebcbwbff6q7kI1SGoT7MA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/icon-button": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/icon-button/-/icon-button-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-1a0MHgyIwOs4RzxrVljsqSizGYFlM1zY2AZaLDsgT4G3kzsplTx8HZQ022GpUCjAygW+WLvg4z1qAhQHvsbqlw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/density": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/focus-ring": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/touch-target": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/image-list": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/image-list/-/image-list-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-WKWmiYap2iu4QdqmeUSliLlN4O2Ueqa0OuVAYHn/TCzmQ2xmnhZ1pvDLbs6TplpOmlki7vFfe+aSt5SU9gwfOQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/layout-grid": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/layout-grid/-/layout-grid-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-5GqmT6oTZhUGWIb+CLD0ZNyDyTiJsr/rm9oRIi3+vCujACwxFkON9tzBlZohdtFS16nuzUusthN6Jt9UrJcN6Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/line-ripple": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/line-ripple/-/line-ripple-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-8S30WXEuUdgDdBulzUDlPXD6qMzwCX9SxYb5mGDYLwl199cpSGdXHtGgEcCjokvnpLhdZhcT1Dsxeo1g2Evh5Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/linear-progress": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/linear-progress/-/linear-progress-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-6EJpjrz6aoH2/gXLg9iMe0yF2C42hpQyZoHpmcgTLKeci85ktDvJIjwup8tnk8ULQyFiGiIrhXw2v2RSsiFjvQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/progress-indicator": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/list": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/list/-/list-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-TQ1ppqiCMQj/P7bGD4edbIIv4goczZUoiUAaPq/feb1dflvrFMzYqJ7tQRRCyBL8nRhJoI2x99tk8Q2RXvlGUQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/density": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tokens": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/menu": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/menu/-/menu-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-IlAh61xzrzxXs38QZlt74UYt8J431zGznSzDtB1Fqs6YFNd11QPKoiRXn1J2Qu/lUxbFV7i8NBKMCKtia0n6/Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/list": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/menu-surface": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tokens": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/menu-surface": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/menu-surface/-/menu-surface-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-dMtSPN+olTWE+08M5qe4ea1IZOhVryYqzK0Gyb2u1G75rSArUxCOB5rr6OC/ST3Mq3RS6zGuYo7srZt4534K9Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/notched-outline": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/notched-outline/-/notched-outline-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-WuurMg44xexkvLTBTnsO0A+qnzFjpcPdvgWBGstBepYozsvSF9zJGdb1x7Zv1MmqbpYh/Ohnuxtb/Y3jOh6irg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/floating-label": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/progress-indicator": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/progress-indicator/-/progress-indicator-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-uOnsvqw5F2fkeTnTl4MrYzjI7KCLmmLyZaM0cgLNuLsWVlddQE+SGMl28tENx7DUK3HebWq0FxCP8f25LuDD+w==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/radio": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/radio/-/radio-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-ehzOK+U1IxQN+OQjgD2lsnf1t7t7RAwQzeO6Czkiuid29ookYbQynWuLWk7NW8H8ohl7lnmfqTP1xSNkkL/F0g==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/density": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/focus-ring": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/touch-target": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/ripple": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-JfLW+g3GMVDv4cruQ19+HUxpKVdWCldFlIPw1UYezz2h3WTNDy05S3uP2zUdXzZ01C3dkBFviv4nqZ0GCT16MA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/rtl": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-SkKLNLFp5QtG7/JEFg9R92qq4MzTcZ5As6sWbH7rRg6ahTHoJEuqE+pOb9Vrtbj84k5gtX+vCYPvCILtSlr2uw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/segmented-button": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/segmented-button/-/segmented-button-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-YDwkCWP9l5mIZJ7pZJZ2hMDxfBlIGVJ+deNzr8O+Z7/xC5LGXbl4R5aPtUVHygvXAXxpf5096ZD+dSXzYzvWlw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/touch-target": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/select": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/select/-/select-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-unfOWVf7T0sixVG+3k3RTuATfzqvCF6QAzA6J9rlCh/Tq4HuIBNDdV4z19IVu4zwmgWYxY0iSvqWUvdJJYwakQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/density": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/floating-label": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/line-ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/list": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/menu": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/menu-surface": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/notched-outline": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tokens": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/shape": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/shape/-/shape-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-Dsvr771ZKC46ODzoixLdGwlLEQLfxfLrtnRojXABoZf5G3o9KtJU+J+5Ld5aa960OAsCzzANuaub4iR88b1guA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/slider": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/slider/-/slider-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-3AEu+7PwW4DSNLndue47dh2u7ga4hDJRYmuu7wnJCIWJBnLCkp6C92kNc4Rj5iQY2ftJio5aj1gqryluh5tlYg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tokens": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/snackbar": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/snackbar/-/snackbar-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-TwwQSYxfGK6mc03/rdDamycND6o+1p61WNd7ElZv1F1CLxB4ihRjbCoH7Qo+oVDaP8CTpjeclka+24RLhQq0mA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/button": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/icon-button": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tokens": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/switch": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/switch/-/switch-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-OjUjtT0kRz1ASAsOS+dNzwMwvsjmqy5edK57692qmrP6bL4GblFfBDoiNJ6t0AN4OaKcmL5Hy/xNrTdOZW7Qqw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/density": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/focus-ring": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tokens": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"safevalues": "^0.3.4",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/tab": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/tab/-/tab-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-s/L9otAwn/pZwVQZBRQJmPqYeNbjoEbzbjMpDQf/VBG/6dJ+aP03ilIBEkqo8NVnCoChqcdtVCoDNRtbU+yp6w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/focus-ring": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tab-indicator": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tokens": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/tab-bar": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/tab-bar/-/tab-bar-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-Xmtq0wJGfu5k+zQeFeNsr4bUKv7L+feCmUp/gsapJ655LQKMXOUQZtSv9ZqWOfrCMy55hoF1CzGFV+oN3tyWWQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/density": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tab": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tab-indicator": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tab-scroller": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tokens": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/tab-indicator": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/tab-indicator/-/tab-indicator-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-despCJYi1GrDDq7F2hvLQkObHnSLZPPDxnOzU16zJ6FNYvIdszgfzn2HgAZ6pl5hLOexQ8cla6cAqjTDuaJBhQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/tab-scroller": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/tab-scroller/-/tab-scroller-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-QWHG/EWxirj4V9u2IHz+OSY9XCWrnNrPnNgEufxAJVUKV/A8ma1DYeFSQqxhX709R8wKGdycJksg0Flkl7Gq7w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tab": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/textfield": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/textfield/-/textfield-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-R3qRex9kCaZIAK8DuxPnVC42R0OaW7AB7fsFknDKeTeVQvRcbnV8E+iWSdqTiGdsi6QQHifX8idUrXw+O45zPw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/density": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/floating-label": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/line-ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/notched-outline": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tokens": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/theme": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/theme/-/theme-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-CpUwXGE0dbhxQ45Hu9r9wbJtO/MAlv5ER4tBHA9tp/K+SU+lDgurBE2touFMg5INmdfVNtdumxb0nPPLaNQcUg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/tokens": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/tokens/-/tokens-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-nbEuGj05txWz6ZMUanpM47SaAD7soyjKILR+XwDell9Zg3bGhsnexCNXPEz2fD+YgomS+jM5XmIcaJJHg/H93Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/tooltip": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/tooltip/-/tooltip-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-UzuXp0b9NuWuYLYpPguxrjbJnCmT/Cco8CkjI/6JajxaeA3o2XEBbQfRMTq8PTafuBjCHTc0b0mQY7rtxUp1Gg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/button": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/dom": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/tokens": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"safevalues": "^0.3.4",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/top-app-bar": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/top-app-bar/-/top-app-bar-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-vJWjsvqtdSD5+yQ/9vgoBtBSCvPJ5uF/DVssv8Hdhgs1PYaAcODUi77kdi0+sy/TaWyOsTkQixqmwnFS16zesA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/animation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/elevation": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/ripple": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/shape": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/typography": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/touch-target": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/touch-target/-/touch-target-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-AqYh9fjt+tv4ZE0C6MeYHblS2H+XwLbDl2mtyrK0DOEnCVQk5/l5ImKDfhrUdFWHvS4a5nBM4AA+sa7KaroLoA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/base": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/rtl": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/typography": {
|
||||||
|
"version": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/typography/-/typography-15.0.0-canary.bc9ae6c9c.0.tgz",
|
||||||
|
"integrity": "sha512-CKsG1zyv34AKPNyZC8olER2OdPII64iR2SzQjpqh1UUvmIFiMPk23LvQ1OnC5aCB14pOXzmVgvJt31r9eNdZ6Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"@material/theme": "15.0.0-canary.bc9ae6c9c.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@ng-select/ng-select": {
|
"node_modules/@ng-select/ng-select": {
|
||||||
"version": "11.2.0",
|
"version": "11.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ng-select/ng-select/-/ng-select-11.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ng-select/ng-select/-/ng-select-11.2.0.tgz",
|
||||||
|
|
@ -5693,7 +6539,7 @@
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||||
"dev": true,
|
"devOptional": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.12"
|
"node": ">=0.12"
|
||||||
},
|
},
|
||||||
|
|
@ -10500,6 +11346,11 @@
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||||
"dev": true
|
"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": {
|
"node_modules/sass": {
|
||||||
"version": "1.64.1",
|
"version": "1.64.1",
|
||||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.64.1.tgz",
|
"resolved": "https://registry.npmjs.org/sass/-/sass-1.64.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,12 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "^16.2.0",
|
"@angular/animations": "^16.2.0",
|
||||||
|
"@angular/cdk": "^16.2.12",
|
||||||
"@angular/common": "^16.2.0",
|
"@angular/common": "^16.2.0",
|
||||||
"@angular/compiler": "^16.2.0",
|
"@angular/compiler": "^16.2.0",
|
||||||
"@angular/core": "^16.2.0",
|
"@angular/core": "^16.2.0",
|
||||||
"@angular/forms": "^16.2.0",
|
"@angular/forms": "^16.2.0",
|
||||||
|
"@angular/material": "^16.2.12",
|
||||||
"@angular/platform-browser": "^16.2.0",
|
"@angular/platform-browser": "^16.2.0",
|
||||||
"@angular/platform-browser-dynamic": "^16.2.0",
|
"@angular/platform-browser-dynamic": "^16.2.0",
|
||||||
"@angular/router": "^16.2.0",
|
"@angular/router": "^16.2.0",
|
||||||
|
|
|
||||||
|
|
@ -309,4 +309,19 @@ export class RecipeService {
|
||||||
{ withCredentials: true, responseType: 'json' }
|
{ withCredentials: true, responseType: 'json' }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async sortRecipe(
|
||||||
|
country: string,
|
||||||
|
filename: string,
|
||||||
|
sortKey: string,
|
||||||
|
): Promise<Observable<any>> {
|
||||||
|
return this._httpClient.post<any>(
|
||||||
|
environment.api + '/recipes/sort/' + country + '/' + filename ,
|
||||||
|
JSON.stringify({
|
||||||
|
"sortKey": sortKey
|
||||||
|
}),
|
||||||
|
{ withCredentials: true, responseType: 'json' }
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
116
client/src/app/features/merge/changes/changes.component.ts
Normal file
116
client/src/app/features/merge/changes/changes.component.ts
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { MatCardModule } from '@angular/material/card';
|
||||||
|
import { compare } from 'src/app/shared/helpers/compare';
|
||||||
|
import { RecipeListComponent } from '../../recipes/recipe-details/recipe-list/recipe-list.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-changes',
|
||||||
|
standalone: true,
|
||||||
|
templateUrl: './changes.component.html',
|
||||||
|
imports: [CommonModule, MatCardModule, RecipeListComponent],
|
||||||
|
})
|
||||||
|
export class ChangesComponent implements OnInit {
|
||||||
|
@Input() changePackage:
|
||||||
|
| {
|
||||||
|
// if is unchanged, do not show
|
||||||
|
minimizeUnchanged: boolean;
|
||||||
|
// do highlight when matched this data
|
||||||
|
highlightChangeWhenMatched: {};
|
||||||
|
// base product code
|
||||||
|
targetProductCode: string;
|
||||||
|
// full recipelist
|
||||||
|
targetRecipe: any;
|
||||||
|
// path
|
||||||
|
path: string;
|
||||||
|
// changes
|
||||||
|
changes: any;
|
||||||
|
}
|
||||||
|
| undefined = undefined;
|
||||||
|
|
||||||
|
diffList: any[] = [];
|
||||||
|
matchedIdx: number[] = [];
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
// this.createDiffList(this.changePackage?.targetRecipe, this.changePackage?.targetRecipe);
|
||||||
|
|
||||||
|
// iterate
|
||||||
|
this.traverseByPath(
|
||||||
|
this.changePackage?.path!,
|
||||||
|
this.changePackage?.targetRecipe
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
createDiffList = (base: any, change: any) => {
|
||||||
|
// console.log("base", base, "change", change);
|
||||||
|
let compRes = compare(base, change);
|
||||||
|
// if (!this.diffList.includes(compRes)) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for(let c of compRes){
|
||||||
|
// console.log("c", c, "diffList", this.diffList.indexOf(c));
|
||||||
|
// if(this.diffList.indexOf(c) == -1){
|
||||||
|
// this.diffList.push(c);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
if(this.diffList.length == 0){
|
||||||
|
this.diffList = compRes;
|
||||||
|
}
|
||||||
|
// else if(this.diffList.length > 0){
|
||||||
|
|
||||||
|
// let concatable = true;
|
||||||
|
// // check if exist
|
||||||
|
// for(let i = 0; i < this.diffList.length; i++){
|
||||||
|
// for(let j = 0; j < compRes.length; j++){
|
||||||
|
// if(this.diffList[i] == compRes[j]){
|
||||||
|
// concatable = false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if(concatable){
|
||||||
|
// this.diffList = this.diffList.concat(compRes);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
console.log("diff list", this.diffList);
|
||||||
|
};
|
||||||
|
|
||||||
|
traverseByPath = (path: string, obj: any) => {
|
||||||
|
let pathList = path.split('.');
|
||||||
|
let data = obj;
|
||||||
|
for (let pathKey of pathList) {
|
||||||
|
if (pathKey != '') {
|
||||||
|
if (!isNaN(parseInt(pathKey))) {
|
||||||
|
let asIntKey = parseInt(pathKey);
|
||||||
|
|
||||||
|
data = data[asIntKey];
|
||||||
|
if (!this.matchedIdx.includes(asIntKey)) {
|
||||||
|
this.matchedIdx.push(parseInt(pathKey));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data = data[pathKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
popLast = (keyString: string) => {
|
||||||
|
let keyList = keyString.split('.');
|
||||||
|
keyList.pop();
|
||||||
|
return keyList.join('.');
|
||||||
|
};
|
||||||
|
|
||||||
|
getChanges = () =>
|
||||||
|
this.traverseByPath(
|
||||||
|
this.popLast(this.changePackage!.path),
|
||||||
|
this.changePackage!.changes
|
||||||
|
);
|
||||||
|
|
||||||
|
removeDot = (s: string) => s.replace(".", "");
|
||||||
|
}
|
||||||
|
|
@ -1,40 +1,68 @@
|
||||||
<p>merge works!</p>
|
<div class="h-[80vh]">
|
||||||
<!-- 3 columns with master at center -->
|
<!-- select a commit -->
|
||||||
<div class="grid grid-cols-3">
|
<div *ngIf="isPatchMapKeysLoaded()">
|
||||||
<!-- from patch -->
|
<label for="patchKeys">Select a commit : </label>
|
||||||
<div>
|
<select
|
||||||
<div class="m-2" *ngFor="let patchKey of getPatchMapKeys()">
|
class="select select-sm select-primary"
|
||||||
|
name="patchKeys"
|
||||||
|
(change)="selectCommit($event)"
|
||||||
|
>
|
||||||
|
<option>---</option>
|
||||||
|
<option *ngFor="let commit of getPatchMapKeys()" [value]="commit" id="commit_{{commit}}">
|
||||||
|
[{{ getCommitAttr(commit, "Created_at") }}] [{{
|
||||||
|
getCommitAttr(commit, "Editor")
|
||||||
|
}}] | {{ getCommitAttr(commit, "Msg") }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- enable from console -->
|
||||||
|
<button class="hidden" (click)="testLoadCheck()">Test load</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 3 columns with master at center -->
|
||||||
|
<div class="flex flex-grow gap-4 p-4">
|
||||||
|
<!-- from patch -->
|
||||||
|
<div
|
||||||
|
class="w-100 overflow-x-visible overflow-y-visible"
|
||||||
|
*ngIf="hasProductCodeOfCommits() && selectedCommit != '' && selectedCommit != '---'"
|
||||||
|
>
|
||||||
|
<details class="collapse collapse-arrow">
|
||||||
|
<summary class="collapse-title">{{ selectedCommit }}</summary>
|
||||||
|
<div class="collapse-content">
|
||||||
|
<app-recipe-list
|
||||||
|
[productCode]="
|
||||||
|
getCommitAttr(selectedCommit, 'contents').productCode
|
||||||
|
"
|
||||||
|
[noFetch]="true"
|
||||||
|
[recipeList]="getCommitAttr(selectedCommit, 'contents').recipes"
|
||||||
|
[displayOnly]="true"
|
||||||
|
[diffChangeContext]="buildContext()"
|
||||||
|
(recipeListFormChange)="onRecipeListFormChange($event)"
|
||||||
|
></app-recipe-list>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
<!-- from master -->
|
||||||
|
<div *ngIf="hasProductCodeOfCommits()">
|
||||||
|
<!-- display zone -->
|
||||||
|
|
||||||
<mat-card class="!bg-amber-300 !rounded-xl p-2">
|
<div *ngFor="let pd of getProductCodesOfCommits()">
|
||||||
<mat-card-title>
|
<div class="container">
|
||||||
{{getCommitAttr(patchKey, 'Msg')}}
|
<details class="collapse collapse-arrow">
|
||||||
</mat-card-title>
|
<summary class="collapse-title">{{ pd }}</summary>
|
||||||
<mat-card-content>
|
<div>
|
||||||
<div>
|
<app-recipe-list
|
||||||
<p>date: {{getCommitAttr(patchKey, 'Created_at') }}</p>
|
[productCode]="pd!"
|
||||||
<p>editor: {{getCommitAttr(patchKey, 'Editor') }}</p>
|
[noFetch]="false"
|
||||||
<p>ref: {{patchKey}}</p>
|
[displayOnly]="true"
|
||||||
|
[diffChangeContext]="buildContext()"
|
||||||
<p class="hidden">full ref: {{getCommitAttr(patchKey, 'Change_file')}}</p>
|
(recipeListFormChange)="onRecipeListFormChange($event)"
|
||||||
|
></app-recipe-list>
|
||||||
<button mat-raised-button class="!bg-white" (click)="copyRef(getCommitAttr(patchKey, 'Change_file'))">Copy full ref</button>
|
</div>
|
||||||
</div>
|
<!-- collapse -->
|
||||||
</mat-card-content>
|
</details>
|
||||||
</mat-card>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- from master -->
|
|
||||||
<div>
|
|
||||||
<p>master</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- from machine -->
|
|
||||||
<div>
|
|
||||||
<p>machine</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,16 @@
|
||||||
import { Component, Input, OnInit } from '@angular/core';
|
import {
|
||||||
|
AfterViewInit,
|
||||||
|
ApplicationRef,
|
||||||
|
Component,
|
||||||
|
ComponentFactoryResolver,
|
||||||
|
Injector,
|
||||||
|
Input,
|
||||||
|
OnDestroy,
|
||||||
|
OnInit,
|
||||||
|
TemplateRef,
|
||||||
|
ViewChild,
|
||||||
|
ViewContainerRef,
|
||||||
|
} from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { RecipeService } from 'src/app/core/services/recipe.service';
|
import { RecipeService } from 'src/app/core/services/recipe.service';
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card';
|
||||||
|
|
@ -6,14 +18,38 @@ import { MatButtonModule } from '@angular/material/button';
|
||||||
import { copy } from 'src/app/shared/helpers/copy';
|
import { copy } from 'src/app/shared/helpers/copy';
|
||||||
import { compare } from 'src/app/shared/helpers/compare';
|
import { compare } from 'src/app/shared/helpers/compare';
|
||||||
import { AsyncStorage } from 'src/app/shared/helpers/asyncStorage';
|
import { AsyncStorage } from 'src/app/shared/helpers/asyncStorage';
|
||||||
|
import { ChangesComponent } from './changes/changes.component';
|
||||||
|
import {
|
||||||
|
CdkPortal,
|
||||||
|
DomPortalOutlet,
|
||||||
|
Portal,
|
||||||
|
PortalModule,
|
||||||
|
TemplatePortal,
|
||||||
|
} from '@angular/cdk/portal';
|
||||||
|
import { MatSelectModule } from '@angular/material/select';
|
||||||
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { RecipeListComponent } from '../recipes/recipe-details/recipe-list/recipe-list.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-merge',
|
selector: 'app-merge',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, MatCardModule, MatButtonModule],
|
|
||||||
templateUrl: './merge.component.html',
|
templateUrl: './merge.component.html',
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
MatCardModule,
|
||||||
|
MatButtonModule,
|
||||||
|
ChangesComponent,
|
||||||
|
RecipeListComponent,
|
||||||
|
PortalModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatSelectModule,
|
||||||
|
FormsModule
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class MergeComponent implements OnInit {
|
export class MergeComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||||
|
onRecipeListFormChange($event: any) {}
|
||||||
|
|
||||||
@Input() commit: Array<any> | undefined = undefined;
|
@Input() commit: Array<any> | undefined = undefined;
|
||||||
|
|
||||||
patchMap: any = {};
|
patchMap: any = {};
|
||||||
|
|
@ -23,11 +59,47 @@ export class MergeComponent implements OnInit {
|
||||||
//map productCode:commits
|
//map productCode:commits
|
||||||
mapProductCodeWithCommits: any = {};
|
mapProductCodeWithCommits: any = {};
|
||||||
// master recipes for product code given by commits
|
// master recipes for product code given by commits
|
||||||
targetRecipe: any = {}
|
targetRecipe: any = {};
|
||||||
// change map
|
// change map
|
||||||
changeMap: any = {};
|
changeMap: any = {};
|
||||||
|
|
||||||
constructor(private _recipeService: RecipeService) {}
|
// -------------------- current selection
|
||||||
|
|
||||||
|
currentTargetOfMaster: any = undefined;
|
||||||
|
highlightChanges: any = {};
|
||||||
|
selectedProductCode = '';
|
||||||
|
|
||||||
|
changePackage:
|
||||||
|
| {
|
||||||
|
minimizeUnchanged: boolean;
|
||||||
|
highlightChangeWhenMatched: {};
|
||||||
|
targetProductCode: string;
|
||||||
|
targetRecipe: any;
|
||||||
|
path: string;
|
||||||
|
changes: any;
|
||||||
|
}
|
||||||
|
| undefined = undefined;
|
||||||
|
|
||||||
|
selectedCommit: string = '';
|
||||||
|
|
||||||
|
// --------------------- Portal
|
||||||
|
// deprecated~!
|
||||||
|
// @ViewChild(CdkPortal)
|
||||||
|
// private portal: CdkPortal | undefined;
|
||||||
|
// private host: DomPortalOutlet | undefined;
|
||||||
|
|
||||||
|
selectedPortal!: Portal<any>;
|
||||||
|
templatePortal!: TemplatePortal<any>;
|
||||||
|
// template
|
||||||
|
@ViewChild('templateRecipeChangeContent')
|
||||||
|
templateRecipeChangeContent!: TemplateRef<any>;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private _recipeService: RecipeService,
|
||||||
|
private _containerRef: ViewContainerRef // private cfr: ComponentFactoryResolver,
|
||||||
|
) // private appRef: ApplicationRef,
|
||||||
|
// private injector: Injector
|
||||||
|
{}
|
||||||
|
|
||||||
async ngOnInit(): Promise<void> {
|
async ngOnInit(): Promise<void> {
|
||||||
(
|
(
|
||||||
|
|
@ -51,7 +123,7 @@ export class MergeComponent implements OnInit {
|
||||||
if (productCode) {
|
if (productCode) {
|
||||||
// check if exist in map
|
// check if exist in map
|
||||||
if (!this.mapProductCodeWithCommits[productCode]) {
|
if (!this.mapProductCodeWithCommits[productCode]) {
|
||||||
this.mapProductCodeWithCommits[productCode] = [ key ];
|
this.mapProductCodeWithCommits[productCode] = [key];
|
||||||
} else {
|
} else {
|
||||||
this.mapProductCodeWithCommits[productCode].push(key);
|
this.mapProductCodeWithCommits[productCode].push(key);
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +141,29 @@ export class MergeComponent implements OnInit {
|
||||||
});
|
});
|
||||||
|
|
||||||
// fetch related product codes
|
// fetch related product codes
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
//Called after ngAfterContentInit when the component's view has been initialized. Applies to components only.
|
||||||
|
//Add 'implements AfterViewInit' to the class.
|
||||||
|
// this.host = new DomPortalOutlet(
|
||||||
|
// document.querySelector('#view_change')!,
|
||||||
|
// this.cfr,
|
||||||
|
// this.appRef,
|
||||||
|
// this.injec2tor
|
||||||
|
// );
|
||||||
|
|
||||||
|
// this.host.attach(this.portal);
|
||||||
|
// console.log("Portal attached!");
|
||||||
|
|
||||||
|
this.templatePortal = new TemplatePortal(
|
||||||
|
this.templateRecipeChangeContent,
|
||||||
|
this._containerRef
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
// this.host?.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
// funcitons
|
// funcitons
|
||||||
|
|
@ -77,20 +171,73 @@ export class MergeComponent implements OnInit {
|
||||||
// get patch map keys
|
// get patch map keys
|
||||||
getPatchMapKeys = () => Object.keys(this.patchMap);
|
getPatchMapKeys = () => Object.keys(this.patchMap);
|
||||||
|
|
||||||
|
// check if load patch keys
|
||||||
|
isPatchMapKeysLoaded = () => this.getPatchMapKeys().length > 0;
|
||||||
|
testLoadCheck = () => console.log('test load check', this.isPatchMapKeysLoaded());
|
||||||
|
|
||||||
|
// get product code targets
|
||||||
|
getProductCodesOfCommits = () => Object.keys(this.mapProductCodeWithCommits);
|
||||||
|
|
||||||
|
// mapProductCodeWithCommits have data in it yet?
|
||||||
|
hasProductCodeOfCommits = () =>
|
||||||
|
Object.keys(this.mapProductCodeWithCommits).length > 0;
|
||||||
|
|
||||||
// get commit message by commit id
|
// get commit message by commit id
|
||||||
getCommitAttr = (id: string, attr: string) => this.fullPatches[id][attr];
|
getCommitAttr = (id: string, attr: string) => this.fullPatches[id][attr];
|
||||||
|
|
||||||
// copy to clipboard
|
// copy to clipboard
|
||||||
copyRef = async (ref: string) => await copy(ref);
|
copyRef = async (ref: string) => await copy(ref);
|
||||||
|
|
||||||
|
// do show warning conflict if contains same path key in change map
|
||||||
|
isThisCommitConflict = (patchId: string) => {
|
||||||
|
// loop key of change map
|
||||||
|
// find other patch if .changes array contains same path key
|
||||||
|
// if yes, return true
|
||||||
|
if (
|
||||||
|
this.changeMap[patchId] == undefined ||
|
||||||
|
this.changeMap[patchId] == null ||
|
||||||
|
!Object.keys(this.changeMap[patchId]).includes('changes')
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let commit = this.changeMap[patchId]['changes'] as Array<any>;
|
||||||
|
for (let key in this.changeMap) {
|
||||||
|
if (key !== patchId) {
|
||||||
|
let testCondition = this.changeMap[key].changes.some(
|
||||||
|
(change: any) =>
|
||||||
|
commit.find((commit: any) => commit.path === change.path) !=
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
return testCondition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
selectCommit = (commit: any) => {
|
||||||
|
console.log('select commit', commit.target.value);
|
||||||
|
this.selectedCommit = commit.target.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildContext = () => {
|
||||||
|
return {
|
||||||
|
changeContext: undefined,
|
||||||
|
skipZeroes: true,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// ----------------------------- Master Functions ---------------------------
|
// ----------------------------- Master Functions ---------------------------
|
||||||
|
|
||||||
getMasterRecipeOfProductCode = async (productCode: string) => {
|
getMasterRecipeOfProductCode = async (productCode: string) => {
|
||||||
(await this._recipeService.getRawRecipeOfProductCode(
|
(
|
||||||
await this._recipeService.getCurrentCountry(),
|
await this._recipeService.getRawRecipeOfProductCode(
|
||||||
this._recipeService.getCurrentFile(),
|
await this._recipeService.getCurrentCountry(),
|
||||||
productCode
|
this._recipeService.getCurrentFile(),
|
||||||
)).subscribe({
|
productCode
|
||||||
|
)
|
||||||
|
).subscribe({
|
||||||
next: (data: any) => {
|
next: (data: any) => {
|
||||||
this.targetRecipe[productCode] = data;
|
this.targetRecipe[productCode] = data;
|
||||||
// console.log("get master recipe", this.targetRecipe);
|
// console.log("get master recipe", this.targetRecipe);
|
||||||
|
|
@ -106,12 +253,88 @@ export class MergeComponent implements OnInit {
|
||||||
);
|
);
|
||||||
// save only what changes
|
// save only what changes
|
||||||
this.changeMap[patchId] = {
|
this.changeMap[patchId] = {
|
||||||
changes: cmp
|
changes: cmp,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("change map", this.changeMap);
|
console.log('change map', this.changeMap);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
generateMasterRecipeList(productCode: string): any {
|
||||||
|
// this do fetch recipelist
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.targetRecipe[productCode] != undefined ||
|
||||||
|
this.targetRecipe[productCode] != null
|
||||||
|
) {
|
||||||
|
this.getMasterRecipeOfProductCode(productCode);
|
||||||
|
}
|
||||||
|
return this.targetRecipe[productCode].recipes;
|
||||||
|
}
|
||||||
|
|
||||||
|
getRecipeFromSingleLayerPath = (
|
||||||
|
productCode: string,
|
||||||
|
path: string,
|
||||||
|
ref_id: string,
|
||||||
|
popLast?: boolean
|
||||||
|
) => {
|
||||||
|
console.log(
|
||||||
|
'mapProductCodeWithCommits map = ',
|
||||||
|
this.mapProductCodeWithCommits
|
||||||
|
);
|
||||||
|
// split path
|
||||||
|
let pathList = path.split('.');
|
||||||
|
|
||||||
|
if (popLast) {
|
||||||
|
// pop last pathlist
|
||||||
|
pathList.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// get product code data
|
||||||
|
let productCodeData = this.targetRecipe[productCode];
|
||||||
|
let data = undefined;
|
||||||
|
for (let pathKey of pathList) {
|
||||||
|
if (data == undefined) {
|
||||||
|
if (!isNaN(parseInt(pathKey))) {
|
||||||
|
data = productCodeData[parseInt(pathKey)];
|
||||||
|
} else {
|
||||||
|
data = productCodeData[pathKey];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!isNaN(parseInt(pathKey))) {
|
||||||
|
data = data[parseInt(pathKey)];
|
||||||
|
} else {
|
||||||
|
data = data[pathKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log('data from path', path,"=", data);
|
||||||
|
|
||||||
|
// setter
|
||||||
|
this.selectedProductCode = productCode;
|
||||||
|
this.currentTargetOfMaster = productCodeData.recipes;
|
||||||
|
// configure for changes display
|
||||||
|
// this.highlightChanges = data;
|
||||||
|
// this.minimizeUnchanged = true;
|
||||||
|
|
||||||
|
// packing into one map; do update if selected
|
||||||
|
let changeConfigure = {
|
||||||
|
minimizeUnchanged: true,
|
||||||
|
highlightChangeWhenMatched: data,
|
||||||
|
targetProductCode: productCode,
|
||||||
|
targetRecipe: productCodeData,
|
||||||
|
path: path,
|
||||||
|
changes: this.fullPatches[ref_id].contents,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.changePackage = changeConfigure;
|
||||||
|
};
|
||||||
|
|
||||||
|
// revert search by using commit ref id to find productCode
|
||||||
|
getProductCodeByCommitRef = (commitRef: string) => {
|
||||||
|
return this.patchMap[commitRef].productCode;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="justify-center w-full flex flex-row sticky top-0 z-10">
|
<div class="justify-center w-full flex flex-row sticky top-0 z-10" *ngIf="displayOnly == false">
|
||||||
<button class="btn w-1/2" (click)="addRow()">Add</button>
|
<button class="btn w-1/2" (click)="addRow()">Add</button>
|
||||||
<button class="btn w-1/2" (click)="removeRow()">Remove</button>
|
<button class="btn w-1/2" (click)="removeRow()">Remove</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
(click)="addToSelection(i)"
|
(click)="addToSelection(i)"
|
||||||
(mousedown)="initHoldEvent()"
|
(mousedown)="initHoldEvent()"
|
||||||
(mouseup)="openRecipeListEditor(i)"
|
(mouseup)="openRecipeListEditor(i)"
|
||||||
|
*ngIf="invokeZeroMaterialChecker(i)"
|
||||||
>
|
>
|
||||||
<td class="font-medium text-gray-900 whitespace-nowrap sticky left-0">
|
<td class="font-medium text-gray-900 whitespace-nowrap sticky left-0">
|
||||||
<input type="checkbox" class="toggle" formControlName="isUse" />
|
<input type="checkbox" class="toggle" formControlName="isUse" />
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { CommonModule, NgFor, NgIf } from '@angular/common';
|
import { CommonModule, NgFor, NgIf } from '@angular/common';
|
||||||
import { Component, EventEmitter, Input, OnInit, Output, ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR } from '@angular/core';
|
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR } from '@angular/core';
|
||||||
import {
|
import {
|
||||||
FormArray,
|
FormArray,
|
||||||
FormBuilder,
|
FormBuilder,
|
||||||
|
|
@ -42,10 +42,15 @@ import Lang from 'src/app/shared/helpers/lang';
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule,NgIf, NgFor, ReactiveFormsModule, FormsModule, RecipeToppingComponent]
|
imports: [CommonModule,NgIf, NgFor, ReactiveFormsModule, FormsModule, RecipeToppingComponent]
|
||||||
})
|
})
|
||||||
export class RecipeListComponent implements OnInit {
|
export class RecipeListComponent implements OnInit, OnChanges {
|
||||||
@Input({ required: true }) productCode!: string;
|
@Input({ required: true }) productCode!: string;
|
||||||
@Input() noFetch: boolean = false;
|
@Input() noFetch: boolean = false;
|
||||||
@Input() recipeList: any | undefined = undefined;
|
@Input() recipeList: any | undefined = undefined;
|
||||||
|
@Input() displayOnly: boolean = false;
|
||||||
|
@Input() diffChangeContext: {
|
||||||
|
changeContext: any;
|
||||||
|
skipZeroes: boolean;
|
||||||
|
} | undefined = undefined;
|
||||||
@Output() recipeListFormChange = new EventEmitter<unknown[]>();
|
@Output() recipeListFormChange = new EventEmitter<unknown[]>();
|
||||||
|
|
||||||
materialList: MaterialCode[] = [];
|
materialList: MaterialCode[] = [];
|
||||||
|
|
@ -267,6 +272,7 @@ export class RecipeListComponent implements OnInit {
|
||||||
this.isMatLoaded = true;
|
this.isMatLoaded = true;
|
||||||
});
|
});
|
||||||
} else if(this.recipeList != undefined){
|
} else if(this.recipeList != undefined){
|
||||||
|
console.log("test recipelist", this.recipeList);
|
||||||
this.recipeList.forEach( (recipeDetailMat: RecipeDetailMat, index: number) => {
|
this.recipeList.forEach( (recipeDetailMat: RecipeDetailMat, index: number) => {
|
||||||
|
|
||||||
// StringParam
|
// StringParam
|
||||||
|
|
@ -297,7 +303,7 @@ export class RecipeListComponent implements OnInit {
|
||||||
// --------------- mapping missing data ---------------
|
// --------------- mapping missing data ---------------
|
||||||
|
|
||||||
// map name
|
// map name
|
||||||
console.log("use recipeList input; ", recipeDetailMat);
|
// console.log("use recipeList input; ", recipeDetailMat);
|
||||||
|
|
||||||
this.recipeListData.push(
|
this.recipeListData.push(
|
||||||
this._formBuilder.group({
|
this._formBuilder.group({
|
||||||
|
|
@ -460,6 +466,216 @@ export class RecipeListComponent implements OnInit {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async ngOnChanges(changes: SimpleChanges): Promise<void> {
|
||||||
|
|
||||||
|
if(changes['recipeList']){
|
||||||
|
let previousRecipeList = changes['recipeList'].previousValue;
|
||||||
|
let newUpdatedRecipeList = changes['recipeList'].currentValue;
|
||||||
|
let firstTime = changes['recipeList'].isFirstChange();
|
||||||
|
|
||||||
|
console.log("test on changes", changes);
|
||||||
|
if(newUpdatedRecipeList != undefined && !firstTime){
|
||||||
|
console.log("test updated input recipelist", newUpdatedRecipeList);
|
||||||
|
|
||||||
|
// reset
|
||||||
|
this.stringParamData.clear();
|
||||||
|
this.recipeListData.clear();
|
||||||
|
|
||||||
|
newUpdatedRecipeList.forEach( (recipeDetailMat: RecipeDetailMat, index: number) => {
|
||||||
|
|
||||||
|
// StringParam
|
||||||
|
if (
|
||||||
|
recipeDetailMat.StringParam != '' ||
|
||||||
|
recipeDetailMat.StringParam != null
|
||||||
|
) {
|
||||||
|
let currStringParam = new StringParam(recipeDetailMat.StringParam);
|
||||||
|
let stringParamList = currStringParam.extract().as_list();
|
||||||
|
|
||||||
|
let stringParamListTransform: any[] = [];
|
||||||
|
for (let param of stringParamList) {
|
||||||
|
// boolean transform
|
||||||
|
if (param.pvalue == 'true') {
|
||||||
|
param.pvalue = true;
|
||||||
|
} else if (param.pvalue == 'false') {
|
||||||
|
param.pvalue = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.stringParamData.push(
|
||||||
|
this._formBuilder.array(stringParamListTransform)
|
||||||
|
)
|
||||||
|
|
||||||
|
this.stringParams[index] = stringParamList;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------- mapping missing data ---------------
|
||||||
|
|
||||||
|
// map name
|
||||||
|
// console.log("use recipeList input; ", recipeDetailMat);
|
||||||
|
|
||||||
|
this.recipeListData.push(
|
||||||
|
this._formBuilder.group({
|
||||||
|
StringParam: [
|
||||||
|
{
|
||||||
|
value: recipeDetailMat.StringParam,
|
||||||
|
disabled: !this.isEditable(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
isUse: [
|
||||||
|
{ value: recipeDetailMat.isUse, disabled: !this.isEditable() },
|
||||||
|
],
|
||||||
|
materialPathId: [
|
||||||
|
{
|
||||||
|
value: recipeDetailMat.materialPathId,
|
||||||
|
disabled: !this.isEditable(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: [{ value: recipeDetailMat.name, disabled: true }],
|
||||||
|
MixOrder: [
|
||||||
|
{
|
||||||
|
value: recipeDetailMat.MixOrder,
|
||||||
|
disabled: !this.isEditable(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
stirTime: [
|
||||||
|
{
|
||||||
|
value: recipeDetailMat.stirTime,
|
||||||
|
disabled: !this.isEditable(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
powderGram: [
|
||||||
|
{
|
||||||
|
value: recipeDetailMat.powderGram,
|
||||||
|
disabled: !this.isEditable(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
powderTime: [
|
||||||
|
{
|
||||||
|
value: recipeDetailMat.powderTime,
|
||||||
|
disabled: !this.isEditable(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
syrupGram: [
|
||||||
|
{
|
||||||
|
value: recipeDetailMat.syrupGram,
|
||||||
|
disabled: !this.isEditable(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
syrupTime: [
|
||||||
|
{
|
||||||
|
value: recipeDetailMat.syrupTime,
|
||||||
|
disabled: !this.isEditable(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
waterCold: [
|
||||||
|
{
|
||||||
|
value: recipeDetailMat.waterCold,
|
||||||
|
disabled: !this.isEditable(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
waterYield: [
|
||||||
|
{
|
||||||
|
value: recipeDetailMat.waterYield,
|
||||||
|
disabled: !this.isEditable(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
feedPattern: [
|
||||||
|
{
|
||||||
|
value: recipeDetailMat.feedPattern,
|
||||||
|
disabled: !this.isEditable(),
|
||||||
|
}
|
||||||
|
],
|
||||||
|
feedParameter: [
|
||||||
|
{
|
||||||
|
value: recipeDetailMat.feedParameter,
|
||||||
|
disabled: !this.isEditable(),
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// resub listener
|
||||||
|
|
||||||
|
this.recipeListForm.valueChanges.subscribe((value) => {
|
||||||
|
// console.log(value.recipeListData);
|
||||||
|
// console.log("original recipe detail",this._recipeListOriginalArray);
|
||||||
|
if (
|
||||||
|
!isEqual(
|
||||||
|
sortBy(value, 'materialID'),
|
||||||
|
sortBy(this._recipeListOriginalArray, 'materialID')
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
let emitted_res: any[] = [];
|
||||||
|
|
||||||
|
// force type change. temporary solution
|
||||||
|
forEach(value.recipeListData!, (recipeDetailMat: any) => {
|
||||||
|
recipeDetailMat.materialPathId = parseInt(
|
||||||
|
recipeDetailMat.materialPathId!
|
||||||
|
);
|
||||||
|
|
||||||
|
// revert stirTime
|
||||||
|
recipeDetailMat.stirTime = recipeDetailMat.stirTime!;
|
||||||
|
|
||||||
|
emitted_res.push(recipeDetailMat);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.recipeListFormChange.emit([this.toppingList, emitted_res] as unknown[]);
|
||||||
|
} else {
|
||||||
|
this.recipeListFormChange.emit([]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.stringParamForm.valueChanges.subscribe((value) => {
|
||||||
|
// value.stringParamData: Array
|
||||||
|
// where this.stringParams: {[key: number] : {pkey: string, pvalue: any}}
|
||||||
|
|
||||||
|
// transform value to map
|
||||||
|
let mapValue: { [key: number]: { pkey: string; pvalue: any }[] } = {};
|
||||||
|
forEach(value.stringParamData, (param: any, index: number) => {
|
||||||
|
mapValue[index] = param;
|
||||||
|
});
|
||||||
|
|
||||||
|
let checkLen =
|
||||||
|
Object.keys(mapValue).length ==
|
||||||
|
Object.keys(this.stringParams as any).length;
|
||||||
|
let baseLen =
|
||||||
|
Object.keys(this.stringParams as any).length >=
|
||||||
|
Object.keys(mapValue).length
|
||||||
|
? Object.keys(this.stringParams as any).length
|
||||||
|
: Object.keys(mapValue).length;
|
||||||
|
|
||||||
|
if (checkLen) {
|
||||||
|
for (let i = 0; i < baseLen; i++) {
|
||||||
|
if (!isEqual(this.stringParams[i], mapValue[i])) {
|
||||||
|
// console.log('check', (this.stringParams as any)[i], mapValue[i]);
|
||||||
|
|
||||||
|
// transform back to string
|
||||||
|
let initString = ',';
|
||||||
|
for (let key of Object.keys(mapValue[i])) {
|
||||||
|
initString += `${mapValue[i][parseInt(key)].pkey}=${
|
||||||
|
mapValue[i][parseInt(key)].pvalue
|
||||||
|
},`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initString.length > 1) {
|
||||||
|
(this.recipeListData.at(i) as any).controls.StringParam.setValue(
|
||||||
|
initString
|
||||||
|
);
|
||||||
|
// console.log('set', initString);
|
||||||
|
}
|
||||||
|
|
||||||
|
// do last
|
||||||
|
this.stringParams[i] = mapValue[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// add new row
|
// add new row
|
||||||
addRow() {
|
addRow() {
|
||||||
|
|
@ -521,6 +737,11 @@ export class RecipeListComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
isEditable() {
|
isEditable() {
|
||||||
|
|
||||||
|
if(this.displayOnly){
|
||||||
|
return !this.displayOnly;
|
||||||
|
}
|
||||||
|
|
||||||
return this._userService
|
return this._userService
|
||||||
.getCurrentUser()!
|
.getCurrentUser()!
|
||||||
.permissions.includes(UserPermissions.EDITOR);
|
.permissions.includes(UserPermissions.EDITOR);
|
||||||
|
|
@ -737,7 +958,7 @@ export class RecipeListComponent implements OnInit {
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
if (this.timeoutHandler) {
|
if (this.timeoutHandler) {
|
||||||
|
|
||||||
if (this.timeout >= 20) {
|
if (this.timeout >= 20 && !this.displayOnly) {
|
||||||
// alert("Opening Recipe List Editor in detail")
|
// alert("Opening Recipe List Editor in detail")
|
||||||
if (confirm("Are you sure you want to open Recipe List Editor in detail?")) {
|
if (confirm("Are you sure you want to open Recipe List Editor in detail?")) {
|
||||||
this.showDetailRecipeList = true;
|
this.showDetailRecipeList = true;
|
||||||
|
|
@ -810,4 +1031,17 @@ export class RecipeListComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------- Change/Diff -------------------------------
|
||||||
|
|
||||||
|
invokeZeroMaterialChecker = (index: number) => {
|
||||||
|
if(this.diffChangeContext?.skipZeroes == true){
|
||||||
|
// check if current index's material is 0
|
||||||
|
let isZeroMaterial = this.recipeListData.at(index).get('materialPathId')?.value == "0";
|
||||||
|
if(isZeroMaterial){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,21 +82,26 @@ export class RecipeToppingComponent implements OnInit {
|
||||||
this._toppingSetOriginalArray = data;
|
this._toppingSetOriginalArray = data;
|
||||||
console.log('ToppingSet', data, this.index, data.length >= this.index!, data[0]);
|
console.log('ToppingSet', data, this.index, data.length >= this.index!, data[0]);
|
||||||
|
|
||||||
this.listGroupId.push(data[this.index!].ListGroupID);
|
|
||||||
|
|
||||||
// check length of toppingList if in range with given index
|
if(data[this.index!] != undefined && data[this.index!] != null){
|
||||||
if (data.length >= this.index!) {
|
|
||||||
this.toppingList.push(
|
this.listGroupId.push(data[this.index!].ListGroupID);
|
||||||
this._formBuilder.group({
|
|
||||||
isUse: data[this.index!].isUse,
|
// check length of toppingList if in range with given index
|
||||||
groupID: data[this.index!].groupID,
|
if (data.length >= this.index!) {
|
||||||
defaultIDSelect: data[this.index!].defaultIDSelect,
|
this.toppingList.push(
|
||||||
ListGroupID: data[this.index!].ListGroupID,
|
this._formBuilder.group({
|
||||||
})
|
isUse: data[this.index!].isUse,
|
||||||
);
|
groupID: data[this.index!].groupID,
|
||||||
|
defaultIDSelect: data[this.index!].defaultIDSelect,
|
||||||
|
ListGroupID: data[this.index!].ListGroupID,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('SubscribeToppingSet', this.toppingList, "list group id=", this.listGroupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('SubscribeToppingSet', this.toppingList, "list group id=", this.listGroupId);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// get all topping
|
// get all topping
|
||||||
|
|
|
||||||
|
|
@ -305,7 +305,8 @@
|
||||||
<th scope="col" class="px-6 py-3" *ngFor="let header of tableHeads">
|
<th scope="col" class="px-6 py-3" *ngFor="let header of tableHeads">
|
||||||
<div class="flex items-center uppercase">
|
<div class="flex items-center uppercase">
|
||||||
{{ header }}
|
{{ header }}
|
||||||
<a href="#"
|
<!-- sorting -->
|
||||||
|
<button (click)="sortByHeader(header)"
|
||||||
><svg
|
><svg
|
||||||
class="w-3 h-3 ml-1.5"
|
class="w-3 h-3 ml-1.5"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
|
|
@ -317,7 +318,7 @@
|
||||||
d="M8.574 11.024h6.852a2.075 2.075 0 0 0 1.847-1.086 1.9 1.9 0 0 0-.11-1.986L13.736 2.9a2.122 2.122 0 0 0-3.472 0L6.837 7.952a1.9 1.9 0 0 0-.11 1.986 2.074 2.074 0 0 0 1.847 1.086Zm6.852 1.952H8.574a2.072 2.072 0 0 0-1.847 1.087 1.9 1.9 0 0 0 .11 1.985l3.426 5.05a2.123 2.123 0 0 0 3.472 0l3.427-5.05a1.9 1.9 0 0 0 .11-1.985 2.074 2.074 0 0 0-1.846-1.087Z"
|
d="M8.574 11.024h6.852a2.075 2.075 0 0 0 1.847-1.086 1.9 1.9 0 0 0-.11-1.986L13.736 2.9a2.122 2.122 0 0 0-3.472 0L6.837 7.952a1.9 1.9 0 0 0-.11 1.986 2.074 2.074 0 0 0 1.847 1.086Zm6.852 1.952H8.574a2.072 2.072 0 0 0-1.847 1.087 1.9 1.9 0 0 0 .11 1.985l3.426 5.05a2.123 2.123 0 0 0 3.472 0l3.427-5.05a1.9 1.9 0 0 0 .11-1.985 2.074 2.074 0 0 0-1.846-1.087Z"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th scope="col" class="px-6 py-3"></th>
|
<th scope="col" class="px-6 py-3"></th>
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,6 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
// );
|
// );
|
||||||
|
|
||||||
// // get default file that should be opened
|
// // get default file that should be opened
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -626,4 +625,35 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
console.log('copyToTsvErr', err);
|
console.log('copyToTsvErr', err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------ sorting ------------------------------------
|
||||||
|
|
||||||
|
async sortByHeader(header: string) {
|
||||||
|
// productCode
|
||||||
|
// name
|
||||||
|
// otherName
|
||||||
|
// description
|
||||||
|
// otherDescription
|
||||||
|
// LastUpdate
|
||||||
|
|
||||||
|
// activate sorting
|
||||||
|
console.log('sortByHeader', header);
|
||||||
|
//
|
||||||
|
|
||||||
|
// send to server [/recipe/sort]
|
||||||
|
(
|
||||||
|
await this._recipeService.sortRecipe(
|
||||||
|
await this._recipeService.getCurrentCountry(),
|
||||||
|
this._recipeService.getCurrentFile(),
|
||||||
|
header
|
||||||
|
)
|
||||||
|
).subscribe({
|
||||||
|
|
||||||
|
next: (data: any) => {
|
||||||
|
if(data.status == 'OK'){
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ func GetCommitLogOfFilename(countryId string, filename string) ([]CommitLog, err
|
||||||
}
|
}
|
||||||
|
|
||||||
commitDB, err := sqlx.Connect("sqlite3", "./data/database.db")
|
commitDB, err := sqlx.Connect("sqlite3", "./data/database.db")
|
||||||
// fmt.Println("GetCommitLogOfFilename", err)
|
// //fmt.Println("GetCommitLogOfFilename", err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -89,7 +89,7 @@ func GetCommitLogOfFilename(countryId string, filename string) ([]CommitLog, err
|
||||||
|
|
||||||
err = commitDB.Select(&commits, "SELECT * FROM commit_log WHERE change_file LIKE ?", "%"+filename+"%")
|
err = commitDB.Select(&commits, "SELECT * FROM commit_log WHERE change_file LIKE ?", "%"+filename+"%")
|
||||||
|
|
||||||
// fmt.Println("commits", err)
|
// //fmt.Println("commits", err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -112,7 +112,7 @@ func GetCommitLogOfFilename(countryId string, filename string) ([]CommitLog, err
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// fmt.Println("commitsByCountryID", len(commitsByCountryID) == 0)
|
// //fmt.Println("commitsByCountryID", len(commitsByCountryID) == 0)
|
||||||
if len(commitsByCountryID) == 0 {
|
if len(commitsByCountryID) == 0 {
|
||||||
|
|
||||||
return nil, fmt.Errorf("no commit found for %s", filename)
|
return nil, fmt.Errorf("no commit found for %s", filename)
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"recipe-manager/helpers"
|
"recipe-manager/helpers"
|
||||||
"recipe-manager/models"
|
"recipe-manager/models"
|
||||||
"recipe-manager/services/logger"
|
"recipe-manager/services/logger"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -358,22 +359,22 @@ func (d *Data) GetRecipe01ByProductCode(filename, countryID, productCode string)
|
||||||
// try convert
|
// try convert
|
||||||
if len(countryID) != 3 {
|
if len(countryID) != 3 {
|
||||||
for k, v := range d.CurrentCountryID {
|
for k, v := range d.CurrentCountryID {
|
||||||
fmt.Println("GetRecipe01ByProductCode.Iterate", k, v, v == countryID)
|
// //fmt.Println("GetRecipe01ByProductCode.Iterate", k, v, v == countryID)
|
||||||
if v == countryID {
|
if v == countryID {
|
||||||
countryID = k
|
countryID = k
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Println("GetRecipe01ByProductCode", filename, countryID, productCode)
|
// //fmt.Println("GetRecipe01ByProductCode", filename, countryID, productCode)
|
||||||
|
|
||||||
if !strings.Contains(filename, "tmp") {
|
if !strings.Contains(filename, "tmp") {
|
||||||
if filename == "" || filename == d.CurrentFile[countryID] {
|
if filename == "" || filename == d.CurrentFile[countryID] {
|
||||||
// , d.CurrentFile, countryID, "result by country id", len(d.currentRecipe[countryID].Recipe01)
|
// , d.CurrentFile, countryID, "result by country id", len(d.currentRecipe[countryID].Recipe01)
|
||||||
// fmt.Println("GetRecipe01ByProductCode.ReadCurrent::filename", filename)
|
// //fmt.Println("GetRecipe01ByProductCode.ReadCurrent::filename", filename)
|
||||||
// fmt.Println("GetRecipe01ByProductCode.ReadCurrent::countryID", countryID)
|
// //fmt.Println("GetRecipe01ByProductCode.ReadCurrent::countryID", countryID)
|
||||||
// fmt.Println("GetRecipe01ByProductCode.ReadCurrent::CurrentFile", d.CurrentFile)
|
// //fmt.Println("GetRecipe01ByProductCode.ReadCurrent::CurrentFile", d.CurrentFile)
|
||||||
// fmt.Println("GetRecipe01ByProductCode.ReadCurrent::CurrentCountryID", d.CurrentCountryID)
|
// //fmt.Println("GetRecipe01ByProductCode.ReadCurrent::CurrentCountryID", d.CurrentCountryID)
|
||||||
|
|
||||||
for _, v := range d.CurrentRecipe[countryID].Recipe01 {
|
for _, v := range d.CurrentRecipe[countryID].Recipe01 {
|
||||||
if v.ProductCode == productCode {
|
if v.ProductCode == productCode {
|
||||||
|
|
@ -386,17 +387,17 @@ func (d *Data) GetRecipe01ByProductCode(filename, countryID, productCode string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fmt.Println("No result in current recipe", countryID)
|
// //fmt.Println("No result in current recipe", countryID)
|
||||||
} else if recipe, ok := d.recipeMap[filename]; ok {
|
} else if recipe, ok := d.recipeMap[filename]; ok {
|
||||||
// fmt.Println("GetRecipe01ByProductCode.ReadMap", filename, d.CurrentFile, recipe.Recipe[countryID], "countryID=", countryID)
|
// //fmt.Println("GetRecipe01ByProductCode.ReadMap", filename, d.CurrentFile, recipe.Recipe[countryID], "countryID=", countryID)
|
||||||
for _, v := range recipe.Recipe[countryID].Recipe01 {
|
for _, v := range recipe.Recipe[countryID].Recipe01 {
|
||||||
if v.ProductCode == productCode {
|
if v.ProductCode == productCode {
|
||||||
d.taoLogger.Log.Debug("GetRecipe01ByProductCode.getSuccess", zap.Any("fromFile", filename), zap.Any("whereSource", d.recipeMap))
|
// d.taoLogger.Log.Debug("GetRecipe01ByProductCode.getSuccess", zap.Any("fromFile", filename), zap.Any("whereSource", d.recipeMap))
|
||||||
return v, nil
|
return v, nil
|
||||||
} else if len(v.SubMenu) > 0 {
|
} else if len(v.SubMenu) > 0 {
|
||||||
for _, subMenu := range v.SubMenu {
|
for _, subMenu := range v.SubMenu {
|
||||||
if subMenu.ProductCode == productCode {
|
if subMenu.ProductCode == productCode {
|
||||||
d.taoLogger.Log.Debug("GetRecipe01ByProductCode.getSuccess", zap.Any("fromFile", filename), zap.Any("whereSource", d.recipeMap))
|
// d.taoLogger.Log.Debug("GetRecipe01ByProductCode.getSuccess", zap.Any("fromFile", filename), zap.Any("whereSource", d.recipeMap))
|
||||||
return subMenu, nil
|
return subMenu, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -915,3 +916,114 @@ func (d *Data) GetCountryIDByName(countryName string) (string, error) {
|
||||||
}
|
}
|
||||||
return "", fmt.Errorf("country name: %s not found", countryName)
|
return "", fmt.Errorf("country name: %s not found", countryName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------ sorting ------
|
||||||
|
func (d *Data) SortRecipe(countryID, filename string, sort_by string) (error, []string) {
|
||||||
|
// Get recipe
|
||||||
|
recipe := d.GetRecipe(countryID, filename)
|
||||||
|
|
||||||
|
// error code
|
||||||
|
errorCode := 0
|
||||||
|
emptiedComparators := make([]string, 0)
|
||||||
|
|
||||||
|
// Sort
|
||||||
|
switch sort_by {
|
||||||
|
case "Product Code":
|
||||||
|
slices.SortFunc(recipe.Recipe01, func(a, b models.Recipe01) int {
|
||||||
|
|
||||||
|
if a.ProductCode == "" || b.ProductCode == "" {
|
||||||
|
errorCode = 1
|
||||||
|
emptiedComparators = append(emptiedComparators, a.ProductCode+" !compare! "+b.ProductCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Compare(a.ProductCode, b.ProductCode)
|
||||||
|
})
|
||||||
|
case "Name":
|
||||||
|
slices.SortFunc(recipe.Recipe01, func(a, b models.Recipe01) int {
|
||||||
|
|
||||||
|
if a.Name == "" || b.Name == "" {
|
||||||
|
errorCode = 2
|
||||||
|
emptiedComparators = append(emptiedComparators, a.Name+" !compare! "+b.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Compare(a.Name, b.Name)
|
||||||
|
})
|
||||||
|
case "Other Name":
|
||||||
|
slices.SortFunc(recipe.Recipe01, func(a, b models.Recipe01) int {
|
||||||
|
|
||||||
|
if a.OtherName == "" || b.OtherName == "" {
|
||||||
|
errorCode = 3
|
||||||
|
emptiedComparators = append(emptiedComparators, a.OtherName+" !compare! "+b.OtherName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Compare(a.OtherName, b.OtherName)
|
||||||
|
})
|
||||||
|
case "Description":
|
||||||
|
slices.SortFunc(recipe.Recipe01, func(a, b models.Recipe01) int {
|
||||||
|
|
||||||
|
if a.Description == "" || b.Description == "" {
|
||||||
|
errorCode = 4
|
||||||
|
emptiedComparators = append(emptiedComparators, a.Description+" !compare! "+b.Description)
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Compare(a.Description, b.Description)
|
||||||
|
})
|
||||||
|
case "Other Description":
|
||||||
|
slices.SortFunc(recipe.Recipe01, func(a, b models.Recipe01) int {
|
||||||
|
|
||||||
|
if a.OtherDescription == "" || b.OtherDescription == "" {
|
||||||
|
errorCode = 5
|
||||||
|
emptiedComparators = append(emptiedComparators, a.OtherDescription+" !compare! "+b.OtherDescription)
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Compare(a.OtherDescription, b.OtherDescription)
|
||||||
|
})
|
||||||
|
case "Last Updated":
|
||||||
|
slices.SortFunc(recipe.Recipe01, func(a, b models.Recipe01) int {
|
||||||
|
// parse date
|
||||||
|
layout := "02-Jan-2006 15:04:05"
|
||||||
|
|
||||||
|
if a.LastChange == "" || b.LastChange == "" {
|
||||||
|
errorCode = 6
|
||||||
|
emptiedComparators = append(emptiedComparators, a.ProductCode+":"+a.LastChange+" !compare! "+b.ProductCode+":"+b.LastChange)
|
||||||
|
}
|
||||||
|
|
||||||
|
timeA, err := time.Parse(layout, a.LastChange)
|
||||||
|
if err != nil {
|
||||||
|
// fmt.Println("Parse error! not in layout format: ", a.LastChange)
|
||||||
|
|
||||||
|
errorCode = 7
|
||||||
|
emptiedComparators = append(emptiedComparators, a.ProductCode+":"+a.LastChange)
|
||||||
|
}
|
||||||
|
|
||||||
|
timeB, err := time.Parse(layout, b.LastChange)
|
||||||
|
if err != nil {
|
||||||
|
// fmt.Println("Parse error! not in layout format: ", b.LastChange)
|
||||||
|
|
||||||
|
errorCode = 8
|
||||||
|
emptiedComparators = append(emptiedComparators, b.ProductCode+":"+b.LastChange)
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.LastChange == "" && b.LastChange != "" {
|
||||||
|
errorCode = 0
|
||||||
|
return 1
|
||||||
|
} else if a.LastChange != "" && b.LastChange == "" {
|
||||||
|
errorCode = 0
|
||||||
|
return -1
|
||||||
|
} else if a.LastChange == "" && b.LastChange == "" {
|
||||||
|
errorCode = 0
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return timeA.Compare(timeB)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if errorCode != 0 {
|
||||||
|
errStatus := fmt.Errorf("ERR[%v]", errorCode)
|
||||||
|
fmt.Println(errStatus)
|
||||||
|
return errStatus, emptiedComparators
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, emptiedComparators
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
|
|
@ -27,7 +26,7 @@ func NewRedisClient(address, password string) *RedisCli {
|
||||||
client := redis.NewClient(&options)
|
client := redis.NewClient(&options)
|
||||||
|
|
||||||
if err := client.Ping(context.Background()); err.Err() != nil {
|
if err := client.Ping(context.Background()); err.Err() != nil {
|
||||||
fmt.Println("trying localhost ...", err)
|
// //fmt.Println("trying localhost ...", err)
|
||||||
client = redis.NewClient(&redis.Options{
|
client = redis.NewClient(&redis.Options{
|
||||||
Addr: "localhost:6379",
|
Addr: "localhost:6379",
|
||||||
Password: password,
|
Password: password,
|
||||||
|
|
@ -35,13 +34,14 @@ func NewRedisClient(address, password string) *RedisCli {
|
||||||
})
|
})
|
||||||
|
|
||||||
if err_local := client.Ping(context.Background()); err_local.Err() != nil {
|
if err_local := client.Ping(context.Background()); err_local.Err() != nil {
|
||||||
fmt.Println("> result ====> ", err_local)
|
// //fmt.Println("> result ====> ", err_local)
|
||||||
|
|
||||||
// do as warning
|
// do as warning
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("\n> Localhost Redis OK!\n")
|
// //fmt.Println("\n> Localhost Redis OK!\n")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("\n> Redis OK! \n")
|
// //fmt.Println("\n> Redis OK! \n")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &RedisCli{
|
return &RedisCli{
|
||||||
|
|
@ -54,51 +54,51 @@ func (r *RedisCli) HealthCheck() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RedisCli) GetKeyTo(source string, dest interface{}) error {
|
func (r *RedisCli) GetKeyTo(source string, dest interface{}) error {
|
||||||
fmt.Println("Redis> GET ", source)
|
// //fmt.Println("Redis> GET ", source)
|
||||||
|
|
||||||
// if cannot pass healthcheck, return err
|
// if cannot pass healthcheck, return err
|
||||||
if err := r.HealthCheck(); err != nil {
|
if err := r.HealthCheck(); err != nil {
|
||||||
fmt.Println("HS> GET error ", err)
|
// //fmt.Println("HS> GET error ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
saved, err := r.Client.Get(context.Background(), source).Result()
|
saved, err := r.Client.Get(context.Background(), source).Result()
|
||||||
|
|
||||||
// chcek EOF
|
// chcek EOF
|
||||||
// fmt.Println("GET last char ", saved[len(saved)-1:])
|
// //fmt.Println("GET last char ", saved[len(saved)-1:])
|
||||||
|
|
||||||
if saved == "" || err != nil {
|
if saved == "" || err != nil {
|
||||||
fmt.Println("GET error (empty on error)|", err, "|while saved=", saved)
|
// //fmt.Println("GET error (empty on error)|", err, "|while saved=", saved)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// fmt.Println("GET ", saved)
|
// //fmt.Println("GET ", saved)
|
||||||
|
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// fmt.Println("GET error ", err)
|
// //fmt.Println("GET error ", err)
|
||||||
// return err
|
// return err
|
||||||
// }
|
// }
|
||||||
err = json.NewDecoder(bytes.NewBufferString(saved)).Decode(dest)
|
err = json.NewDecoder(bytes.NewBufferString(saved)).Decode(dest)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("GET error ", err)
|
// //fmt.Println("GET error ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RedisCli) SetToKey(key string, value interface{}) error {
|
func (r *RedisCli) SetToKey(key string, value interface{}) error {
|
||||||
fmt.Println("Redis> SET ", key)
|
// //fmt.Println("Redis> SET ", key)
|
||||||
|
|
||||||
// if cannot pass healthcheck, return err
|
// if cannot pass healthcheck, return err
|
||||||
if err := r.HealthCheck(); err != nil {
|
if err := r.HealthCheck(); err != nil {
|
||||||
fmt.Println("HS> SET error ", err)
|
// //fmt.Println("HS> SET error ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
saved, err := json.Marshal(value)
|
saved, err := json.Marshal(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("SET error ", err)
|
//fmt.Println("SET error ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,7 +106,7 @@ func (r *RedisCli) SetToKey(key string, value interface{}) error {
|
||||||
err = r.Client.Set(context.Background(), key, saved, redis.KeepTTL).Err()
|
err = r.Client.Set(context.Background(), key, saved, redis.KeepTTL).Err()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("error on SET ", err)
|
//fmt.Println("error on SET ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
|
@ -116,7 +116,7 @@ func (r *RedisCli) ExpireKey(key string) error {
|
||||||
|
|
||||||
// if cannot pass healthcheck, return err
|
// if cannot pass healthcheck, return err
|
||||||
if err := r.HealthCheck(); err != nil {
|
if err := r.HealthCheck(); err != nil {
|
||||||
fmt.Println("HS> EXPIRE error ", err)
|
//fmt.Println("HS> EXPIRE error ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,19 +127,19 @@ func (r *RedisCli) SetKeyTimeout(key string, value interface{}, timeout int) err
|
||||||
|
|
||||||
// if cannot pass healthcheck, return err
|
// if cannot pass healthcheck, return err
|
||||||
if err := r.HealthCheck(); err != nil {
|
if err := r.HealthCheck(); err != nil {
|
||||||
fmt.Println("HS> EXPIRE error ", err)
|
//fmt.Println("HS> EXPIRE error ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err := r.Client.Expire(context.Background(), key, time.Duration(timeout)*time.Second).Err()
|
err := r.Client.Expire(context.Background(), key, time.Duration(timeout)*time.Second).Err()
|
||||||
fmt.Println("error on EXPIRE ", err)
|
//fmt.Println("error on EXPIRE ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RedisCli) KeyList() ([]string, error) {
|
func (r *RedisCli) KeyList() ([]string, error) {
|
||||||
// if cannot pass healthcheck, return err
|
// if cannot pass healthcheck, return err
|
||||||
if err := r.HealthCheck(); err != nil {
|
if err := r.HealthCheck(); err != nil {
|
||||||
fmt.Println("HS> KEYS error ", err)
|
//fmt.Println("HS> KEYS error ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -153,7 +153,7 @@ func (r *RedisCli) KeyList() ([]string, error) {
|
||||||
func (r *RedisCli) GetList(key string) ([]string, error) {
|
func (r *RedisCli) GetList(key string) ([]string, error) {
|
||||||
// if cannot pass healthcheck, return err
|
// if cannot pass healthcheck, return err
|
||||||
if err := r.HealthCheck(); err != nil {
|
if err := r.HealthCheck(); err != nil {
|
||||||
fmt.Println("HS> List.GET error ", err)
|
//fmt.Println("HS> List.GET error ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -163,7 +163,7 @@ func (r *RedisCli) GetList(key string) ([]string, error) {
|
||||||
func (r *RedisCli) Add(key string, value interface{}) error {
|
func (r *RedisCli) Add(key string, value interface{}) error {
|
||||||
// if cannot pass healthcheck, return err
|
// if cannot pass healthcheck, return err
|
||||||
if err := r.HealthCheck(); err != nil {
|
if err := r.HealthCheck(); err != nil {
|
||||||
fmt.Println("HS> List.ADD error ", err)
|
//fmt.Println("HS> List.ADD error ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,9 @@ import (
|
||||||
func NewSqliteDatabase() *sqlx.DB {
|
func NewSqliteDatabase() *sqlx.DB {
|
||||||
|
|
||||||
// ensure that database exists
|
// ensure that database exists
|
||||||
info, err := os.Stat("./data/database.db")
|
_, err := os.Stat("./data/database.db")
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
fmt.Println("No database found. Check path: ", err)
|
fmt.Errorf("No database found. Check path: ", err)
|
||||||
} else {
|
|
||||||
fmt.Println("Database existed. ", info)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
db := sqlx.MustConnect("sqlite3", "./data/database.db")
|
db := sqlx.MustConnect("sqlite3", "./data/database.db")
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"recipe-manager/config"
|
"recipe-manager/config"
|
||||||
|
|
@ -63,7 +62,7 @@ func (ar *AuthRouter) Route(r chi.Router) {
|
||||||
var kind string
|
var kind string
|
||||||
state := r.URL.Query().Get("state")
|
state := r.URL.Query().Get("state")
|
||||||
|
|
||||||
fmt.Println("url query", r.URL.Query())
|
//fmt.Println("url query", r.URL.Query())
|
||||||
|
|
||||||
if state == "" {
|
if state == "" {
|
||||||
http.Error(w, "State not found", http.StatusBadRequest)
|
http.Error(w, "State not found", http.StatusBadRequest)
|
||||||
|
|
@ -76,7 +75,7 @@ func (ar *AuthRouter) Route(r chi.Router) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("val", val)
|
//fmt.Println("val", val)
|
||||||
|
|
||||||
redirectTo = val["redirect_to"]
|
redirectTo = val["redirect_to"]
|
||||||
kind = val["kind"]
|
kind = val["kind"]
|
||||||
|
|
|
||||||
|
|
@ -198,6 +198,8 @@ func (rr *RecipeRouter) Route(r chi.Router) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
r.Post("/sort/{country}/{filename}", rr.sortRecipe)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -594,7 +596,7 @@ func (rr *RecipeRouter) getSavedRecipes(w http.ResponseWriter, r *http.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
commits, err := data.GetCommitLogOfFilename(countryID, file_version)
|
commits, err := data.GetCommitLogOfFilename(countryID, file_version)
|
||||||
// fmt.Println("commits", commits)
|
// //fmt.Println("commits", commits)
|
||||||
rr.taoLogger.Log.Debug("RecipeRouter.getSavedRecipes", zap.Any("commits", commits))
|
rr.taoLogger.Log.Debug("RecipeRouter.getSavedRecipes", zap.Any("commits", commits))
|
||||||
|
|
||||||
if err != nil || len(commits) == 0 {
|
if err != nil || len(commits) == 0 {
|
||||||
|
|
@ -836,3 +838,37 @@ func lockThenTimeout(mutex *sync.Mutex, timeout time.Duration) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------ Sorting ------------------
|
||||||
|
func (rr *RecipeRouter) sortRecipe(w http.ResponseWriter, r *http.Request) {
|
||||||
|
country := chi.URLParam(r, "country")
|
||||||
|
filename := chi.URLParam(r, "filename")
|
||||||
|
|
||||||
|
// get sort type from body
|
||||||
|
var sortConfig map[string]interface{}
|
||||||
|
err := json.NewDecoder(r.Body).Decode(&sortConfig)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sortKey := sortConfig["sortKey"].(string)
|
||||||
|
|
||||||
|
// sort recipe
|
||||||
|
err, emptiedComparators := rr.data.SortRecipe(country, filename, sortKey)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
rr.taoLogger.Log.Error("RecipeRouter.sortRecipe", zap.Error(err), zap.Any("emptiedComparators", emptiedComparators))
|
||||||
|
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||||
|
"status": "OK",
|
||||||
|
"key": sortKey,
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ func NewToppingRouter(data *data.Data, taoLogger *logger.TaoLogger) *ToppingRout
|
||||||
func (tr *ToppingRouter) Route(r chi.Router) {
|
func (tr *ToppingRouter) Route(r chi.Router) {
|
||||||
|
|
||||||
// check incoming request
|
// check incoming request
|
||||||
// fmt.Println("topping router", r.Routes())
|
// //fmt.Println("topping router", r.Routes())
|
||||||
|
|
||||||
r.Route("/toppover", func(r chi.Router) {
|
r.Route("/toppover", func(r chi.Router) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,11 +32,10 @@ func (tl *TaoLogger) initConfig() *zap.Logger {
|
||||||
EncodeLevel: zapcore.LowercaseLevelEncoder,
|
EncodeLevel: zapcore.LowercaseLevelEncoder,
|
||||||
EncodeTime: zapcore.ISO8601TimeEncoder,
|
EncodeTime: zapcore.ISO8601TimeEncoder,
|
||||||
}), zapcore.AddSync(&lumberjack.Logger{
|
}), zapcore.AddSync(&lumberjack.Logger{
|
||||||
Filename: "services/logger/serverlog.log",
|
Filename: "services/logger/serverlog.log",
|
||||||
MaxSize: 500, // megabytes
|
MaxSize: 10, // megabytes
|
||||||
MaxBackups: 3,
|
MaxAge: 28, //days
|
||||||
MaxAge: 28, //days
|
LocalTime: true,
|
||||||
LocalTime: true,
|
|
||||||
}), enableDebugMode),
|
}), enableDebugMode),
|
||||||
zapcore.NewCore(zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
|
zapcore.NewCore(zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
|
||||||
TimeKey: "timestamp",
|
TimeKey: "timestamp",
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ func (rs *recipeService) GetRecipeDetailMat(request *contracts.RecipeDetailReque
|
||||||
break
|
break
|
||||||
} else if mat.MaterialName != "" {
|
} else if mat.MaterialName != "" {
|
||||||
mat_name = mat.MaterialName
|
mat_name = mat.MaterialName
|
||||||
// fmt.Println("SetMat", mat_name)
|
// //fmt.Println("SetMat", mat_name)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue