mirror of
				https://github.com/richard-loafle/fuse-angular.git
				synced 2025-10-31 20:23:34 +00:00 
			
		
		
		
	Merge branch 'master' of https://github.com/withinpixels/fuse2
This commit is contained in:
		
						commit
						786180958d
					
				
							
								
								
									
										918
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										918
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -1299,7 +1299,6 @@ | |||||||
|       "requires": { |       "requires": { | ||||||
|         "anymatch": "1.3.0", |         "anymatch": "1.3.0", | ||||||
|         "async-each": "1.0.1", |         "async-each": "1.0.1", | ||||||
|         "fsevents": "1.1.2", |  | ||||||
|         "glob-parent": "2.0.0", |         "glob-parent": "2.0.0", | ||||||
|         "inherits": "2.0.3", |         "inherits": "2.0.3", | ||||||
|         "is-binary-path": "1.0.1", |         "is-binary-path": "1.0.1", | ||||||
| @ -3443,905 +3442,6 @@ | |||||||
|       "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", |       "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", | ||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|     "fsevents": { |  | ||||||
|       "version": "1.1.2", |  | ||||||
|       "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.2.tgz", |  | ||||||
|       "integrity": "sha512-Sn44E5wQW4bTHXvQmvSHwqbuiXtduD6Rrjm2ZtUEGbyrig+nUH3t/QD4M4/ZXViY556TBpRgZkHLDx3JxPwxiw==", |  | ||||||
|       "dev": true, |  | ||||||
|       "optional": true, |  | ||||||
|       "requires": { |  | ||||||
|         "nan": "2.6.2", |  | ||||||
|         "node-pre-gyp": "0.6.36" |  | ||||||
|       }, |  | ||||||
|       "dependencies": { |  | ||||||
|         "abbrev": { |  | ||||||
|           "version": "1.1.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "ajv": { |  | ||||||
|           "version": "4.11.8", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "co": "4.6.0", |  | ||||||
|             "json-stable-stringify": "1.0.1" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "ansi-regex": { |  | ||||||
|           "version": "2.1.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "aproba": { |  | ||||||
|           "version": "1.1.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "are-we-there-yet": { |  | ||||||
|           "version": "1.1.4", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "delegates": "1.0.0", |  | ||||||
|             "readable-stream": "2.2.9" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "asn1": { |  | ||||||
|           "version": "0.2.3", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "assert-plus": { |  | ||||||
|           "version": "0.2.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "asynckit": { |  | ||||||
|           "version": "0.4.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "aws-sign2": { |  | ||||||
|           "version": "0.6.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "aws4": { |  | ||||||
|           "version": "1.6.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "balanced-match": { |  | ||||||
|           "version": "0.4.2", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "bcrypt-pbkdf": { |  | ||||||
|           "version": "1.0.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "tweetnacl": "0.14.5" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "block-stream": { |  | ||||||
|           "version": "0.0.9", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "inherits": "2.0.3" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "boom": { |  | ||||||
|           "version": "2.10.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "hoek": "2.16.3" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "brace-expansion": { |  | ||||||
|           "version": "1.1.7", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "balanced-match": "0.4.2", |  | ||||||
|             "concat-map": "0.0.1" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "buffer-shims": { |  | ||||||
|           "version": "1.0.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "caseless": { |  | ||||||
|           "version": "0.12.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "co": { |  | ||||||
|           "version": "4.6.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "code-point-at": { |  | ||||||
|           "version": "1.1.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "combined-stream": { |  | ||||||
|           "version": "1.0.5", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "delayed-stream": "1.0.0" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "concat-map": { |  | ||||||
|           "version": "0.0.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "console-control-strings": { |  | ||||||
|           "version": "1.1.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "core-util-is": { |  | ||||||
|           "version": "1.0.2", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "cryptiles": { |  | ||||||
|           "version": "2.0.5", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "boom": "2.10.1" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "dashdash": { |  | ||||||
|           "version": "1.14.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "assert-plus": "1.0.0" |  | ||||||
|           }, |  | ||||||
|           "dependencies": { |  | ||||||
|             "assert-plus": { |  | ||||||
|               "version": "1.0.0", |  | ||||||
|               "bundled": true, |  | ||||||
|               "dev": true, |  | ||||||
|               "optional": true |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "debug": { |  | ||||||
|           "version": "2.6.8", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "ms": "2.0.0" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "deep-extend": { |  | ||||||
|           "version": "0.4.2", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "delayed-stream": { |  | ||||||
|           "version": "1.0.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "delegates": { |  | ||||||
|           "version": "1.0.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "ecc-jsbn": { |  | ||||||
|           "version": "0.1.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "jsbn": "0.1.1" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "extend": { |  | ||||||
|           "version": "3.0.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "extsprintf": { |  | ||||||
|           "version": "1.0.2", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "forever-agent": { |  | ||||||
|           "version": "0.6.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "form-data": { |  | ||||||
|           "version": "2.1.4", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "asynckit": "0.4.0", |  | ||||||
|             "combined-stream": "1.0.5", |  | ||||||
|             "mime-types": "2.1.15" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "fs.realpath": { |  | ||||||
|           "version": "1.0.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "fstream": { |  | ||||||
|           "version": "1.0.11", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "graceful-fs": "4.1.11", |  | ||||||
|             "inherits": "2.0.3", |  | ||||||
|             "mkdirp": "0.5.1", |  | ||||||
|             "rimraf": "2.6.1" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "fstream-ignore": { |  | ||||||
|           "version": "1.0.5", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "fstream": "1.0.11", |  | ||||||
|             "inherits": "2.0.3", |  | ||||||
|             "minimatch": "3.0.4" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "gauge": { |  | ||||||
|           "version": "2.7.4", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "aproba": "1.1.1", |  | ||||||
|             "console-control-strings": "1.1.0", |  | ||||||
|             "has-unicode": "2.0.1", |  | ||||||
|             "object-assign": "4.1.1", |  | ||||||
|             "signal-exit": "3.0.2", |  | ||||||
|             "string-width": "1.0.2", |  | ||||||
|             "strip-ansi": "3.0.1", |  | ||||||
|             "wide-align": "1.1.2" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "getpass": { |  | ||||||
|           "version": "0.1.7", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "assert-plus": "1.0.0" |  | ||||||
|           }, |  | ||||||
|           "dependencies": { |  | ||||||
|             "assert-plus": { |  | ||||||
|               "version": "1.0.0", |  | ||||||
|               "bundled": true, |  | ||||||
|               "dev": true, |  | ||||||
|               "optional": true |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "glob": { |  | ||||||
|           "version": "7.1.2", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "fs.realpath": "1.0.0", |  | ||||||
|             "inflight": "1.0.6", |  | ||||||
|             "inherits": "2.0.3", |  | ||||||
|             "minimatch": "3.0.4", |  | ||||||
|             "once": "1.4.0", |  | ||||||
|             "path-is-absolute": "1.0.1" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "graceful-fs": { |  | ||||||
|           "version": "4.1.11", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "har-schema": { |  | ||||||
|           "version": "1.0.5", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "har-validator": { |  | ||||||
|           "version": "4.2.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "ajv": "4.11.8", |  | ||||||
|             "har-schema": "1.0.5" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "has-unicode": { |  | ||||||
|           "version": "2.0.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "hawk": { |  | ||||||
|           "version": "3.1.3", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "boom": "2.10.1", |  | ||||||
|             "cryptiles": "2.0.5", |  | ||||||
|             "hoek": "2.16.3", |  | ||||||
|             "sntp": "1.0.9" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "hoek": { |  | ||||||
|           "version": "2.16.3", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "http-signature": { |  | ||||||
|           "version": "1.1.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "assert-plus": "0.2.0", |  | ||||||
|             "jsprim": "1.4.0", |  | ||||||
|             "sshpk": "1.13.0" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "inflight": { |  | ||||||
|           "version": "1.0.6", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "once": "1.4.0", |  | ||||||
|             "wrappy": "1.0.2" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "inherits": { |  | ||||||
|           "version": "2.0.3", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "ini": { |  | ||||||
|           "version": "1.3.4", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "is-fullwidth-code-point": { |  | ||||||
|           "version": "1.0.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "number-is-nan": "1.0.1" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "is-typedarray": { |  | ||||||
|           "version": "1.0.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "isarray": { |  | ||||||
|           "version": "1.0.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "isstream": { |  | ||||||
|           "version": "0.1.2", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "jodid25519": { |  | ||||||
|           "version": "1.0.2", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "jsbn": "0.1.1" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "jsbn": { |  | ||||||
|           "version": "0.1.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "json-schema": { |  | ||||||
|           "version": "0.2.3", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "json-stable-stringify": { |  | ||||||
|           "version": "1.0.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "jsonify": "0.0.0" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "json-stringify-safe": { |  | ||||||
|           "version": "5.0.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "jsonify": { |  | ||||||
|           "version": "0.0.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "jsprim": { |  | ||||||
|           "version": "1.4.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "assert-plus": "1.0.0", |  | ||||||
|             "extsprintf": "1.0.2", |  | ||||||
|             "json-schema": "0.2.3", |  | ||||||
|             "verror": "1.3.6" |  | ||||||
|           }, |  | ||||||
|           "dependencies": { |  | ||||||
|             "assert-plus": { |  | ||||||
|               "version": "1.0.0", |  | ||||||
|               "bundled": true, |  | ||||||
|               "dev": true, |  | ||||||
|               "optional": true |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "mime-db": { |  | ||||||
|           "version": "1.27.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "mime-types": { |  | ||||||
|           "version": "2.1.15", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "mime-db": "1.27.0" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "minimatch": { |  | ||||||
|           "version": "3.0.4", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "brace-expansion": "1.1.7" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "minimist": { |  | ||||||
|           "version": "0.0.8", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "mkdirp": { |  | ||||||
|           "version": "0.5.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "minimist": "0.0.8" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "ms": { |  | ||||||
|           "version": "2.0.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "node-pre-gyp": { |  | ||||||
|           "version": "0.6.36", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "mkdirp": "0.5.1", |  | ||||||
|             "nopt": "4.0.1", |  | ||||||
|             "npmlog": "4.1.0", |  | ||||||
|             "rc": "1.2.1", |  | ||||||
|             "request": "2.81.0", |  | ||||||
|             "rimraf": "2.6.1", |  | ||||||
|             "semver": "5.3.0", |  | ||||||
|             "tar": "2.2.1", |  | ||||||
|             "tar-pack": "3.4.0" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "nopt": { |  | ||||||
|           "version": "4.0.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "abbrev": "1.1.0", |  | ||||||
|             "osenv": "0.1.4" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "npmlog": { |  | ||||||
|           "version": "4.1.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "are-we-there-yet": "1.1.4", |  | ||||||
|             "console-control-strings": "1.1.0", |  | ||||||
|             "gauge": "2.7.4", |  | ||||||
|             "set-blocking": "2.0.0" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "number-is-nan": { |  | ||||||
|           "version": "1.0.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "oauth-sign": { |  | ||||||
|           "version": "0.8.2", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "object-assign": { |  | ||||||
|           "version": "4.1.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "once": { |  | ||||||
|           "version": "1.4.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "wrappy": "1.0.2" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "os-homedir": { |  | ||||||
|           "version": "1.0.2", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "os-tmpdir": { |  | ||||||
|           "version": "1.0.2", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "osenv": { |  | ||||||
|           "version": "0.1.4", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "os-homedir": "1.0.2", |  | ||||||
|             "os-tmpdir": "1.0.2" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "path-is-absolute": { |  | ||||||
|           "version": "1.0.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "performance-now": { |  | ||||||
|           "version": "0.2.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "process-nextick-args": { |  | ||||||
|           "version": "1.0.7", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "punycode": { |  | ||||||
|           "version": "1.4.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "qs": { |  | ||||||
|           "version": "6.4.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "rc": { |  | ||||||
|           "version": "1.2.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "deep-extend": "0.4.2", |  | ||||||
|             "ini": "1.3.4", |  | ||||||
|             "minimist": "1.2.0", |  | ||||||
|             "strip-json-comments": "2.0.1" |  | ||||||
|           }, |  | ||||||
|           "dependencies": { |  | ||||||
|             "minimist": { |  | ||||||
|               "version": "1.2.0", |  | ||||||
|               "bundled": true, |  | ||||||
|               "dev": true, |  | ||||||
|               "optional": true |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "readable-stream": { |  | ||||||
|           "version": "2.2.9", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "buffer-shims": "1.0.0", |  | ||||||
|             "core-util-is": "1.0.2", |  | ||||||
|             "inherits": "2.0.3", |  | ||||||
|             "isarray": "1.0.0", |  | ||||||
|             "process-nextick-args": "1.0.7", |  | ||||||
|             "string_decoder": "1.0.1", |  | ||||||
|             "util-deprecate": "1.0.2" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "request": { |  | ||||||
|           "version": "2.81.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "aws-sign2": "0.6.0", |  | ||||||
|             "aws4": "1.6.0", |  | ||||||
|             "caseless": "0.12.0", |  | ||||||
|             "combined-stream": "1.0.5", |  | ||||||
|             "extend": "3.0.1", |  | ||||||
|             "forever-agent": "0.6.1", |  | ||||||
|             "form-data": "2.1.4", |  | ||||||
|             "har-validator": "4.2.1", |  | ||||||
|             "hawk": "3.1.3", |  | ||||||
|             "http-signature": "1.1.1", |  | ||||||
|             "is-typedarray": "1.0.0", |  | ||||||
|             "isstream": "0.1.2", |  | ||||||
|             "json-stringify-safe": "5.0.1", |  | ||||||
|             "mime-types": "2.1.15", |  | ||||||
|             "oauth-sign": "0.8.2", |  | ||||||
|             "performance-now": "0.2.0", |  | ||||||
|             "qs": "6.4.0", |  | ||||||
|             "safe-buffer": "5.0.1", |  | ||||||
|             "stringstream": "0.0.5", |  | ||||||
|             "tough-cookie": "2.3.2", |  | ||||||
|             "tunnel-agent": "0.6.0", |  | ||||||
|             "uuid": "3.0.1" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "rimraf": { |  | ||||||
|           "version": "2.6.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "glob": "7.1.2" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "safe-buffer": { |  | ||||||
|           "version": "5.0.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "semver": { |  | ||||||
|           "version": "5.3.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "set-blocking": { |  | ||||||
|           "version": "2.0.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "signal-exit": { |  | ||||||
|           "version": "3.0.2", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "sntp": { |  | ||||||
|           "version": "1.0.9", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "hoek": "2.16.3" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "sshpk": { |  | ||||||
|           "version": "1.13.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "asn1": "0.2.3", |  | ||||||
|             "assert-plus": "1.0.0", |  | ||||||
|             "bcrypt-pbkdf": "1.0.1", |  | ||||||
|             "dashdash": "1.14.1", |  | ||||||
|             "ecc-jsbn": "0.1.1", |  | ||||||
|             "getpass": "0.1.7", |  | ||||||
|             "jodid25519": "1.0.2", |  | ||||||
|             "jsbn": "0.1.1", |  | ||||||
|             "tweetnacl": "0.14.5" |  | ||||||
|           }, |  | ||||||
|           "dependencies": { |  | ||||||
|             "assert-plus": { |  | ||||||
|               "version": "1.0.0", |  | ||||||
|               "bundled": true, |  | ||||||
|               "dev": true, |  | ||||||
|               "optional": true |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "string-width": { |  | ||||||
|           "version": "1.0.2", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "code-point-at": "1.1.0", |  | ||||||
|             "is-fullwidth-code-point": "1.0.0", |  | ||||||
|             "strip-ansi": "3.0.1" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "string_decoder": { |  | ||||||
|           "version": "1.0.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "safe-buffer": "5.0.1" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "stringstream": { |  | ||||||
|           "version": "0.0.5", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "strip-ansi": { |  | ||||||
|           "version": "3.0.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "ansi-regex": "2.1.1" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "strip-json-comments": { |  | ||||||
|           "version": "2.0.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "tar": { |  | ||||||
|           "version": "2.2.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "requires": { |  | ||||||
|             "block-stream": "0.0.9", |  | ||||||
|             "fstream": "1.0.11", |  | ||||||
|             "inherits": "2.0.3" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "tar-pack": { |  | ||||||
|           "version": "3.4.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "debug": "2.6.8", |  | ||||||
|             "fstream": "1.0.11", |  | ||||||
|             "fstream-ignore": "1.0.5", |  | ||||||
|             "once": "1.4.0", |  | ||||||
|             "readable-stream": "2.2.9", |  | ||||||
|             "rimraf": "2.6.1", |  | ||||||
|             "tar": "2.2.1", |  | ||||||
|             "uid-number": "0.0.6" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "tough-cookie": { |  | ||||||
|           "version": "2.3.2", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "punycode": "1.4.1" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "tunnel-agent": { |  | ||||||
|           "version": "0.6.0", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "safe-buffer": "5.0.1" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "tweetnacl": { |  | ||||||
|           "version": "0.14.5", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "uid-number": { |  | ||||||
|           "version": "0.0.6", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "util-deprecate": { |  | ||||||
|           "version": "1.0.2", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         }, |  | ||||||
|         "uuid": { |  | ||||||
|           "version": "3.0.1", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true |  | ||||||
|         }, |  | ||||||
|         "verror": { |  | ||||||
|           "version": "1.3.6", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "extsprintf": "1.0.2" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "wide-align": { |  | ||||||
|           "version": "1.1.2", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true, |  | ||||||
|           "optional": true, |  | ||||||
|           "requires": { |  | ||||||
|             "string-width": "1.0.2" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "wrappy": { |  | ||||||
|           "version": "1.0.2", |  | ||||||
|           "bundled": true, |  | ||||||
|           "dev": true |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "fstream": { |     "fstream": { | ||||||
|       "version": "1.0.11", |       "version": "1.0.11", | ||||||
|       "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", |       "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", | ||||||
| @ -8940,6 +8040,15 @@ | |||||||
|       "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", |       "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", | ||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|  |     "string_decoder": { | ||||||
|  |       "version": "1.0.3", | ||||||
|  |       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", | ||||||
|  |       "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", | ||||||
|  |       "dev": true, | ||||||
|  |       "requires": { | ||||||
|  |         "safe-buffer": "5.1.1" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "string-width": { |     "string-width": { | ||||||
|       "version": "2.1.1", |       "version": "2.1.1", | ||||||
|       "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", |       "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", | ||||||
| @ -8967,15 +8076,6 @@ | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "string_decoder": { |  | ||||||
|       "version": "1.0.3", |  | ||||||
|       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", |  | ||||||
|       "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", |  | ||||||
|       "dev": true, |  | ||||||
|       "requires": { |  | ||||||
|         "safe-buffer": "5.1.1" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "stringstream": { |     "stringstream": { | ||||||
|       "version": "0.0.5", |       "version": "0.0.5", | ||||||
|       "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", |       "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", | ||||||
|  | |||||||
| @ -36,6 +36,10 @@ const appRoutes: Routes = [ | |||||||
|         path        : 'apps/calendar', |         path        : 'apps/calendar', | ||||||
|         loadChildren: './main/content/apps/calendar/calendar.module#FuseCalendarModule' |         loadChildren: './main/content/apps/calendar/calendar.module#FuseCalendarModule' | ||||||
|     }, |     }, | ||||||
|  |     { | ||||||
|  |         path        : 'apps/e-commerce', | ||||||
|  |         loadChildren: './main/content/apps/e-commerce/e-commerce.module#FuseEcommerceModule' | ||||||
|  |     }, | ||||||
|     { |     { | ||||||
|         path        : 'apps/todo', |         path        : 'apps/todo', | ||||||
|         loadChildren: './main/content/apps/todo/todo.module#FuseTodoModule' |         loadChildren: './main/content/apps/todo/todo.module#FuseTodoModule' | ||||||
|  | |||||||
| @ -82,10 +82,12 @@ export class FuseUtils | |||||||
|     { |     { | ||||||
|         function S4() |         function S4() | ||||||
|         { |         { | ||||||
|             return (((1 + Math.random()) * 0x10000) || 0).toString(16).substring(1); |             return Math.floor((1 + Math.random()) * 0x10000) | ||||||
|  |                        .toString(16) | ||||||
|  |                        .substring(1); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return (S4() + S4()); |         return S4() + S4(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static toggleInArray(item, array) |     public static toggleInArray(item, array) | ||||||
| @ -99,4 +101,14 @@ export class FuseUtils | |||||||
|             array.splice(array.indexOf(item), 1); |             array.splice(array.indexOf(item), 1); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     public static handleize(text) | ||||||
|  |     { | ||||||
|  |         return text.toString().toLowerCase() | ||||||
|  |                    .replace(/\s+/g, '-')           // Replace spaces with -
 | ||||||
|  |                    .replace(/[^\w\-]+/g, '')       // Remove all non-word chars
 | ||||||
|  |                    .replace(/\-\-+/g, '-')         // Replace multiple - with single -
 | ||||||
|  |                    .replace(/^-+/, '')             // Trim - from start of text
 | ||||||
|  |                    .replace(/-+$/, '');            // Trim - from end of text
 | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -187,6 +187,11 @@ $matColorHues: 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, A100, A200, A400 | |||||||
|         // Generate material element colors |         // Generate material element colors | ||||||
|         // based on current contrast color |         // based on current contrast color | ||||||
|         @include generateMaterialElementColors($contrastColor); |         @include generateMaterialElementColors($contrastColor); | ||||||
|  | 
 | ||||||
|  |         &[disabled] { | ||||||
|  |             background-color: rgba($color, .12) !important; | ||||||
|  |             color: rgba($contrastColor, .26) !important; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     .#{$colorName}#{$hue}-fg { |     .#{$colorName}#{$hue}-fg { | ||||||
|  | |||||||
| @ -96,7 +96,7 @@ $top-bg-image: url('assets/images/backgrounds/header-bg.png'); | |||||||
|                         max-height: $carded-toolbar-height; |                         max-height: $carded-toolbar-height; | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                     .content { |                     > .content { | ||||||
|                         display: flex; |                         display: flex; | ||||||
|                         flex: 1; |                         flex: 1; | ||||||
|                         overflow: auto; |                         overflow: auto; | ||||||
|  | |||||||
							
								
								
									
										3962
									
								
								src/app/fuse-fake-db/e-commerce.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3962
									
								
								src/app/fuse-fake-db/e-commerce.ts
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -15,6 +15,7 @@ import { ProjectsDashboardDb } from './projects-dashboard'; | |||||||
| import { ScrumboardFakeDb } from './scrumboard'; | import { ScrumboardFakeDb } from './scrumboard'; | ||||||
| import { FaqFakeDb } from './faq'; | import { FaqFakeDb } from './faq'; | ||||||
| import { KnowledgeBaseFakeDb } from './knowledge-base'; | import { KnowledgeBaseFakeDb } from './knowledge-base'; | ||||||
|  | import { ECommerceFakeDb } from './e-commerce'; | ||||||
| 
 | 
 | ||||||
| export class FuseFakeDbService implements InMemoryDbService | export class FuseFakeDbService implements InMemoryDbService | ||||||
| { | { | ||||||
| @ -48,7 +49,10 @@ export class FuseFakeDbService implements InMemoryDbService | |||||||
|             'projects-dashboard-widgets' : ProjectsDashboardDb.widgets, |             'projects-dashboard-widgets' : ProjectsDashboardDb.widgets, | ||||||
|             'scrumboard-boards'          : ScrumboardFakeDb.boards, |             'scrumboard-boards'          : ScrumboardFakeDb.boards, | ||||||
|             'faq'                        : FaqFakeDb.data, |             'faq'                        : FaqFakeDb.data, | ||||||
|             'knowledge-base'             : KnowledgeBaseFakeDb.data |             'knowledge-base'             : KnowledgeBaseFakeDb.data, | ||||||
|  |             'e-commerce-dashboard'       : ECommerceFakeDb.dashboard, | ||||||
|  |             'e-commerce-products'        : ECommerceFakeDb.products, | ||||||
|  |             'e-commerce-orders'        : ECommerceFakeDb.orders | ||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,325 @@ | |||||||
|  | <div id="e-commerce-dashboard" class="page-layout simple fullwidth"> | ||||||
|  | 
 | ||||||
|  |     <!-- CONTENT --> | ||||||
|  |     <div class="content p-24 w-100-p"> | ||||||
|  | 
 | ||||||
|  |         <!-- WIDGET GROUP --> | ||||||
|  |         <div class="widget-group" fxLayout="row" fxFlex="100" fxLayoutWrap fxLayoutAlign="start start" *fuseIfOnDom [@animateStagger]="{value:'50'}"> | ||||||
|  | 
 | ||||||
|  |             <!-- WIDGET 1 --> | ||||||
|  |             <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column" fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25"> | ||||||
|  | 
 | ||||||
|  |                 <!-- Front --> | ||||||
|  |                 <div class="fuse-widget-front mat-white-bg mat-elevation-z2"> | ||||||
|  |                     <div class="pl-16 pr-8 py-16 h-52" fxLayout="row" fxLayoutAlign="space-between center"> | ||||||
|  |                         <mat-form-field> | ||||||
|  |                             <mat-select class="simplified font-size-16" [(ngModel)]="widgets.widget1.currentRange" | ||||||
|  |                                         aria-label="Change range"> | ||||||
|  |                                 <mat-option *ngFor="let range of widgets.widget1.ranges | keys" | ||||||
|  |                                             [value]="range.key"> | ||||||
|  |                                     {{range.value}} | ||||||
|  |                                 </mat-option> | ||||||
|  |                             </mat-select> | ||||||
|  |                         </mat-form-field> | ||||||
|  |                         <button mat-icon-button fuseWidgetToggle aria-label="more"> | ||||||
|  |                             <mat-icon>more_vert</mat-icon> | ||||||
|  |                         </button> | ||||||
|  |                     </div> | ||||||
|  | 
 | ||||||
|  |                     <div class="pt-8 pb-32" fxLayout="column" fxLayoutAlign="center center"> | ||||||
|  |                         <div class="light-blue-fg font-size-72 line-height-72"> | ||||||
|  |                             {{widgets.widget1.data.count[widgets.widget1.currentRange]}} | ||||||
|  |                         </div> | ||||||
|  |                         <div class="h3 secondary-text font-weight-500">{{widgets.widget1.data.label}}</div> | ||||||
|  |                     </div> | ||||||
|  | 
 | ||||||
|  |                     <div class="p-16 grey-50-bg border-top" fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  |                         <span class="h4 secondary-text text-truncate">{{widgets.widget1.data.extra.label}}:</span> | ||||||
|  |                         <span class="h4 ml-8">{{widgets.widget1.data.extra.count[widgets.widget1.currentRange]}}</span> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 <!-- / Front --> | ||||||
|  | 
 | ||||||
|  |                 <!-- Back --> | ||||||
|  |                 <div class="fuse-widget-back p-16 pt-32 mat-white-bg mat-elevation-z2"> | ||||||
|  |                     <button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button" | ||||||
|  |                             aria-label="Flip widget"> | ||||||
|  |                         <mat-icon class="s-16">close</mat-icon> | ||||||
|  |                     </button> | ||||||
|  | 
 | ||||||
|  |                     <div> | ||||||
|  |                         {{widgets.widget1.detail}} | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 <!-- / Back --> | ||||||
|  | 
 | ||||||
|  |             </fuse-widget> | ||||||
|  |             <!-- / WIDGET 1 --> | ||||||
|  | 
 | ||||||
|  |             <!-- WIDGET 2 --> | ||||||
|  |             <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column" fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25"> | ||||||
|  | 
 | ||||||
|  |                 <!-- Front --> | ||||||
|  |                 <div class="fuse-widget-front mat-white-bg mat-elevation-z2"> | ||||||
|  |                     <div class="pl-16 pr-8 py-16 h-52" fxLayout="row" fxLayoutAlign="space-between center"> | ||||||
|  |                         <div class="h3">{{widgets.widget2.title}}</div> | ||||||
|  | 
 | ||||||
|  |                         <button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button" aria-label="more"> | ||||||
|  |                             <mat-icon>more_vert</mat-icon> | ||||||
|  |                         </button> | ||||||
|  |                     </div> | ||||||
|  | 
 | ||||||
|  |                     <div class="pt-8 pb-32" fxLayout="column" fxLayoutAlign="center center"> | ||||||
|  |                         <div class="red-fg font-size-72 line-height-72"> | ||||||
|  |                             {{widgets.widget2.data.count}} | ||||||
|  |                         </div> | ||||||
|  |                         <div class="h3 secondary-text font-weight-500">{{widgets.widget2.data.label}}</div> | ||||||
|  |                     </div> | ||||||
|  | 
 | ||||||
|  |                     <div class="p-16 grey-50-bg border-top" fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  |                         <span class="h4 secondary-text text-truncate">{{widgets.widget2.data.extra.label}}:</span> | ||||||
|  |                         <span class="h4 ml-8">{{widgets.widget2.data.extra.count}}</span> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 <!-- / Front --> | ||||||
|  | 
 | ||||||
|  |                 <!-- Back --> | ||||||
|  |                 <div class="fuse-widget-back p-16 pt-32 mat-white-bg mat-elevation-z2"> | ||||||
|  |                     <button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button" | ||||||
|  |                             aria-label="Flip widget"> | ||||||
|  |                         <mat-icon class="s-16">close</mat-icon> | ||||||
|  |                     </button> | ||||||
|  | 
 | ||||||
|  |                     <div> | ||||||
|  |                         {{widgets.widget2.detail}} | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 <!-- / Back --> | ||||||
|  | 
 | ||||||
|  |             </fuse-widget> | ||||||
|  |             <!-- / WIDGET 2 --> | ||||||
|  | 
 | ||||||
|  |             <!-- WIDGET 3 --> | ||||||
|  |             <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column" fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25"> | ||||||
|  | 
 | ||||||
|  |                 <!-- Front --> | ||||||
|  |                 <div class="fuse-widget-front mat-white-bg mat-elevation-z2"> | ||||||
|  |                     <div class="pl-16 pr-8 py-16 h-52" fxLayout="row" fxLayoutAlign="space-between center"> | ||||||
|  |                         <div class="h3">{{widgets.widget3.title}}</div> | ||||||
|  | 
 | ||||||
|  |                         <button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button" aria-label="more"> | ||||||
|  |                             <mat-icon>more_vert</mat-icon> | ||||||
|  |                         </button> | ||||||
|  |                     </div> | ||||||
|  | 
 | ||||||
|  |                     <div class="pt-8 pb-32" fxLayout="column" fxLayoutAlign="center center"> | ||||||
|  |                         <div class="orange-fg font-size-72 line-height-72"> | ||||||
|  |                             {{widgets.widget3.data.count}} | ||||||
|  |                         </div> | ||||||
|  |                         <div class="h3 secondary-text font-weight-500">{{widgets.widget3.data.label}}</div> | ||||||
|  |                     </div> | ||||||
|  | 
 | ||||||
|  |                     <div class="p-16 grey-50-bg border-top" fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  |                         <span class="h4 secondary-text text-truncate">{{widgets.widget3.data.extra.label}}:</span> | ||||||
|  |                         <span class="h4 ml-8">{{widgets.widget3.data.extra.count}}</span> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 <!-- / Front --> | ||||||
|  | 
 | ||||||
|  |                 <!-- Back --> | ||||||
|  |                 <div class="fuse-widget-back p-16 pt-32 mat-white-bg mat-elevation-z2"> | ||||||
|  |                     <button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button" | ||||||
|  |                             aria-label="Flip widget"> | ||||||
|  |                         <mat-icon class="s-16">close</mat-icon> | ||||||
|  |                     </button> | ||||||
|  | 
 | ||||||
|  |                     <div> | ||||||
|  |                         {{widgets.widget3.detail}} | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 <!-- / Back --> | ||||||
|  | 
 | ||||||
|  |             </fuse-widget> | ||||||
|  |             <!-- / WIDGET 3 --> | ||||||
|  | 
 | ||||||
|  |             <!-- WIDGET 4 --> | ||||||
|  |             <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column" fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25"> | ||||||
|  | 
 | ||||||
|  |                 <!-- Front --> | ||||||
|  |                 <div class="fuse-widget-front mat-white-bg mat-elevation-z2"> | ||||||
|  |                     <div class="pl-16 pr-8 py-16 h-52" fxLayout="row" fxLayoutAlign="space-between center"> | ||||||
|  |                         <div class="h3">{{widgets.widget4.title}}</div> | ||||||
|  | 
 | ||||||
|  |                         <button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button" aria-label="more"> | ||||||
|  |                             <mat-icon>more_vert</mat-icon> | ||||||
|  |                         </button> | ||||||
|  |                     </div> | ||||||
|  | 
 | ||||||
|  |                     <div class="pt-8 pb-32" fxLayout="column" fxLayoutAlign="center center"> | ||||||
|  |                         <div class="blue-grey-fg font-size-72 line-height-72">{{widgets.widget4.data.count}} | ||||||
|  |                         </div> | ||||||
|  |                         <div class="h3 secondary-text font-weight-500">{{widgets.widget4.data.label}}</div> | ||||||
|  |                     </div> | ||||||
|  | 
 | ||||||
|  |                     <div class="p-16 grey-50-bg border-top" fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  |                         <span class="h4 secondary-text text-truncate">{{widgets.widget4.data.extra.label}}:</span> | ||||||
|  |                         <span class="h4 ml-8">{{widgets.widget4.data.extra.count}}</span> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 <!-- / Front --> | ||||||
|  | 
 | ||||||
|  |                 <!-- Back --> | ||||||
|  |                 <div class="fuse-widget-back p-16 pt-32 mat-white-bg mat-elevation-z2"> | ||||||
|  |                     <button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button" | ||||||
|  |                             aria-label="Flip widget"> | ||||||
|  |                         <mat-icon class="s-16">close</mat-icon> | ||||||
|  |                     </button> | ||||||
|  | 
 | ||||||
|  |                     <div> | ||||||
|  |                         {{widgets.widget4.detail}} | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 <!-- / Back --> | ||||||
|  | 
 | ||||||
|  |             </fuse-widget> | ||||||
|  |             <!-- / WIDGET 4 --> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |             <!-- WIDGET 5 --> | ||||||
|  |             <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="row" fxFlex="100"> | ||||||
|  | 
 | ||||||
|  |                 <!-- Front --> | ||||||
|  |                 <div class="fuse-widget-front mat-white-bg mat-elevation-z2"> | ||||||
|  | 
 | ||||||
|  |                     <div class="px-16 border-bottom" fxLayout="row" fxLayoutAlign="space-between center" fxLayoutWrap> | ||||||
|  | 
 | ||||||
|  |                         <div fxFlex class="py-8 h3">{{widgets.widget5.title}}</div> | ||||||
|  | 
 | ||||||
|  |                         <div fxFlex="0 1 auto" class="py-8" fxLayout="row"> | ||||||
|  |                             <button mat-button class="px-16" | ||||||
|  |                                     *ngFor="let range of widgets.widget5.ranges | keys" | ||||||
|  |                                     (click)="widget5.currentRange = range.key" | ||||||
|  |                                     [disabled]="widget5.currentRange == range.key"> | ||||||
|  |                                 {{range.value}} | ||||||
|  |                             </button> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  | 
 | ||||||
|  |                     <div class="h-420"> | ||||||
|  |                         <ngx-charts-bar-vertical-stacked | ||||||
|  |                             *fuseIfOnDom | ||||||
|  |                             [scheme]="widget5.scheme" | ||||||
|  |                             [results]="this.widgets.widget5.mainChart[this.widget5.currentRange]" | ||||||
|  |                             [gradient]="widget5.gradient" | ||||||
|  |                             [xAxis]="widget5.xAxis" | ||||||
|  |                             [yAxis]="widget5.yAxis" | ||||||
|  |                             [legend]="widget5.legend" | ||||||
|  |                             [showXAxisLabel]="widget5.showXAxisLabel" | ||||||
|  |                             [showYAxisLabel]="widget5.showYAxisLabel" | ||||||
|  |                             [xAxisLabel]="widget5.xAxisLabel" | ||||||
|  |                             [yAxisLabel]="widget5.yAxisLabel" | ||||||
|  |                             (select)="widget5.onSelect($event)"> | ||||||
|  |                         </ngx-charts-bar-vertical-stacked> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 <!-- / Front --> | ||||||
|  | 
 | ||||||
|  |             </fuse-widget> | ||||||
|  |             <!-- / WIDGET 5 --> | ||||||
|  | 
 | ||||||
|  |             <!-- WIDGET 6 --> | ||||||
|  |             <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column" fxFlex="100" fxFlex.gt-sm="50"> | ||||||
|  | 
 | ||||||
|  |                 <!-- Front --> | ||||||
|  |                 <div class="fuse-widget-front mat-white-bg mat-elevation-z2"> | ||||||
|  | 
 | ||||||
|  |                     <div class="px-16 border-bottom" fxLayout="row" fxLayoutAlign="space-between center"> | ||||||
|  |                         <div class="h3">{{widgets.widget6.title}}</div> | ||||||
|  |                         <mat-form-field> | ||||||
|  |                             <mat-select class="simplified" [(ngModel)]="widget6.currentRange" aria-label="Change range"> | ||||||
|  |                                 <mat-option *ngFor="let range of widgets.widget6.ranges | keys" | ||||||
|  |                                             [value]="range.key"> | ||||||
|  |                                     {{range.value}} | ||||||
|  |                                 </mat-option> | ||||||
|  |                             </mat-select> | ||||||
|  |                         </mat-form-field> | ||||||
|  |                     </div> | ||||||
|  | 
 | ||||||
|  |                     <div class="h-400"> | ||||||
|  |                         <ngx-charts-pie-chart | ||||||
|  |                             *fuseIfOnDom | ||||||
|  |                             [scheme]="widget6.scheme" | ||||||
|  |                             [results]="widgets.widget6.mainChart[widget6.currentRange]" | ||||||
|  |                             [legend]="widget6.showLegend" | ||||||
|  |                             [explodeSlices]="widget6.explodeSlices" | ||||||
|  |                             [labels]="widget6.labels" | ||||||
|  |                             [doughnut]="widget6.doughnut" | ||||||
|  |                             [gradient]="widget6.gradient" | ||||||
|  |                             (select)="widget6.onSelect($event)"> | ||||||
|  |                         </ngx-charts-pie-chart> | ||||||
|  |                     </div> | ||||||
|  | 
 | ||||||
|  |                     <div class="py-8 mh-16 border-top" fxLayout="row" fxLayoutAlign="start center" fxLayoutWrap> | ||||||
|  |                         <div class="py-8 border-right" fxLayout="column" fxLayoutAlign="center center" fxFlex="100" fxFlex.gt-sm="50"> | ||||||
|  |                             <span class="mat-display-1 mb-0">{{widgets.widget6.footerLeft.count[widget6.currentRange]}}</span> | ||||||
|  |                             <span class="h4">{{widgets.widget6.footerLeft.title}}</span> | ||||||
|  |                         </div> | ||||||
|  | 
 | ||||||
|  |                         <div class="py-8" fxLayout="column" fxLayoutAlign="center center" fxFlex="100" fxFlex.gt-sm="50"> | ||||||
|  |                             <span class="mat-display-1 mb-0">{{widgets.widget6.footerRight.count[widget6.currentRange]}}</span> | ||||||
|  |                             <span class="h4">{{widgets.widget6.footerRight.title}}</span> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  | 
 | ||||||
|  |                 </div> | ||||||
|  |                 <!-- / Front --> | ||||||
|  | 
 | ||||||
|  |             </fuse-widget> | ||||||
|  |             <!-- / WIDGET 6 --> | ||||||
|  | 
 | ||||||
|  |             <!-- WIDGET 7 --> | ||||||
|  |             <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column" fxFlex="100" fxFlex.gt-sm="50"> | ||||||
|  | 
 | ||||||
|  |                 <!-- Front --> | ||||||
|  |                 <div class="fuse-widget-front mat-white-bg mat-elevation-z2"> | ||||||
|  | 
 | ||||||
|  |                     <div class="px-16 border-bottom" fxLayout="row" fxLayoutAlign="space-between center"> | ||||||
|  |                         <div class="h3">{{widgets.widget7.title}}</div> | ||||||
|  |                         <mat-form-field> | ||||||
|  |                             <mat-select class="simplified" [(ngModel)]="widget7.currentRange" | ||||||
|  |                                         aria-label="Change range"> | ||||||
|  |                                 <mat-option *ngFor="let range of widgets.widget7.ranges | keys" | ||||||
|  |                                             [value]="range.key"> | ||||||
|  |                                     {{range.value}} | ||||||
|  |                                 </mat-option> | ||||||
|  |                             </mat-select> | ||||||
|  |                         </mat-form-field> | ||||||
|  |                     </div> | ||||||
|  | 
 | ||||||
|  |                     <div class="p-16" fxLayout="row" fxLayoutAlign="space-between center" | ||||||
|  |                          *ngFor="let customer of widgets.widget7.customers[widget7.currentRange]"> | ||||||
|  |                         <div> | ||||||
|  |                             <div class="h3">{{customer.name}}</div> | ||||||
|  |                             <div> | ||||||
|  |                                 <span *ngIf="customer.location">{{customer.location}}</span> | ||||||
|  |                             </div> | ||||||
|  |                         </div> | ||||||
|  | 
 | ||||||
|  |                         <button mat-icon-button aria-label="More information"> | ||||||
|  |                             <mat-icon>more_vert</mat-icon> | ||||||
|  |                         </button> | ||||||
|  |                     </div> | ||||||
|  | 
 | ||||||
|  |                 </div> | ||||||
|  |                 <!-- / Front --> | ||||||
|  | 
 | ||||||
|  |             </fuse-widget> | ||||||
|  |             <!-- / WIDGET 7 --> | ||||||
|  | 
 | ||||||
|  |         </div> | ||||||
|  |         <!-- / WIDGET GROUP --> | ||||||
|  | 
 | ||||||
|  |     </div> | ||||||
|  |     <!-- / CONTENT --> | ||||||
|  | 
 | ||||||
|  | </div> | ||||||
| @ -0,0 +1,7 @@ | |||||||
|  | #e-commerce-dashboard { | ||||||
|  | 
 | ||||||
|  |     .content { | ||||||
|  |         flex: 1 0 auto; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,93 @@ | |||||||
|  | import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; | ||||||
|  | import { EcommerceDashboardService } from './dashboard.service'; | ||||||
|  | import * as shape from 'd3-shape'; | ||||||
|  | import { BehaviorSubject } from 'rxjs/BehaviorSubject'; | ||||||
|  | import { Observable } from 'rxjs/Observable'; | ||||||
|  | import { DataSource } from '@angular/cdk/collections'; | ||||||
|  | import { fuseAnimations } from '../../../../../core/animations'; | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |     selector     : 'fuse-e-commerce-dashboard', | ||||||
|  |     templateUrl  : './dashboard.component.html', | ||||||
|  |     styleUrls    : ['./dashboard.component.scss'], | ||||||
|  |     encapsulation: ViewEncapsulation.None, | ||||||
|  |     animations   : fuseAnimations | ||||||
|  | }) | ||||||
|  | export class FuseEcommerceDashboardComponent implements OnInit, OnDestroy | ||||||
|  | { | ||||||
|  |     projects: any[]; | ||||||
|  |     selectedProject: any; | ||||||
|  | 
 | ||||||
|  |     widgets: any; | ||||||
|  |     widget5: any = {}; | ||||||
|  |     widget6: any = {}; | ||||||
|  |     widget7: any = {}; | ||||||
|  | 
 | ||||||
|  |     dateNow = Date.now(); | ||||||
|  | 
 | ||||||
|  |     constructor(private projectsDashboardService: EcommerceDashboardService) | ||||||
|  |     { | ||||||
|  |         this.projects = this.projectsDashboardService.projects; | ||||||
|  | 
 | ||||||
|  |         this.selectedProject = this.projects[0]; | ||||||
|  | 
 | ||||||
|  |         this.widgets = this.projectsDashboardService.widgets; | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Widget 5 | ||||||
|  |          */ | ||||||
|  |         this.widget5 = { | ||||||
|  |             currentRange  : 'TW', | ||||||
|  |             xAxis         : true, | ||||||
|  |             yAxis         : true, | ||||||
|  |             gradient      : false, | ||||||
|  |             legend        : false, | ||||||
|  |             showXAxisLabel: false, | ||||||
|  |             xAxisLabel    : 'Days', | ||||||
|  |             showYAxisLabel: false, | ||||||
|  |             yAxisLabel    : 'Isues', | ||||||
|  |             scheme        : { | ||||||
|  |                 domain: ['#42BFF7', '#C6ECFD', '#C7B42C', '#AAAAAA'] | ||||||
|  |             }, | ||||||
|  |             onSelect      : (ev) => { | ||||||
|  |                 console.log(ev); | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Widget 6 | ||||||
|  |          */ | ||||||
|  |         this.widget6 = { | ||||||
|  |             currentRange : 'TW', | ||||||
|  |             legend       : false, | ||||||
|  |             explodeSlices: false, | ||||||
|  |             labels       : true, | ||||||
|  |             doughnut     : true, | ||||||
|  |             gradient     : false, | ||||||
|  |             scheme       : { | ||||||
|  |                 domain: ['#f44336', '#9c27b0', '#03a9f4', '#e91e63'] | ||||||
|  |             }, | ||||||
|  |             onSelect     : (ev) => { | ||||||
|  |                 console.log(ev); | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Widget 7 | ||||||
|  |          */ | ||||||
|  |         this.widget7 = { | ||||||
|  |             currentRange: 'T' | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ngOnInit() | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ngOnDestroy() | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| @ -0,0 +1,62 @@ | |||||||
|  | import { Injectable } from '@angular/core'; | ||||||
|  | import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; | ||||||
|  | import { Observable } from 'rxjs/Observable'; | ||||||
|  | import { HttpClient } from '@angular/common/http'; | ||||||
|  | 
 | ||||||
|  | @Injectable() | ||||||
|  | export class EcommerceDashboardService implements Resolve<any> | ||||||
|  | { | ||||||
|  |     projects: any[]; | ||||||
|  |     widgets: any[]; | ||||||
|  | 
 | ||||||
|  |     constructor( | ||||||
|  |         private http: HttpClient | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Resolve | ||||||
|  |      * @param {ActivatedRouteSnapshot} route | ||||||
|  |      * @param {RouterStateSnapshot} state | ||||||
|  |      * @returns {Observable<any> | Promise<any> | any} | ||||||
|  |      */ | ||||||
|  |     resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         return new Promise((resolve, reject) => { | ||||||
|  | 
 | ||||||
|  |             Promise.all([ | ||||||
|  |                 this.getProjects(), | ||||||
|  |                 this.getWidgets() | ||||||
|  |             ]).then( | ||||||
|  |                 () => { | ||||||
|  |                     resolve(); | ||||||
|  |                 }, | ||||||
|  |                 reject | ||||||
|  |             ); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     getProjects(): Promise<any> | ||||||
|  |     { | ||||||
|  |         return new Promise((resolve, reject) => { | ||||||
|  |             this.http.get('api/projects-dashboard-projects') | ||||||
|  |                 .subscribe((response: any) => { | ||||||
|  |                     this.projects = response; | ||||||
|  |                     resolve(response); | ||||||
|  |                 }, reject); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     getWidgets(): Promise<any> | ||||||
|  |     { | ||||||
|  |         return new Promise((resolve, reject) => { | ||||||
|  |             this.http.get('api/e-commerce-dashboard') | ||||||
|  |                 .subscribe((response: any) => { | ||||||
|  |                     this.widgets = response; | ||||||
|  |                     resolve(response); | ||||||
|  |                 }, reject); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										91
									
								
								src/app/main/content/apps/e-commerce/e-commerce.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/app/main/content/apps/e-commerce/e-commerce.module.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,91 @@ | |||||||
|  | import { NgModule } from '@angular/core'; | ||||||
|  | import { RouterModule, Routes } from '@angular/router'; | ||||||
|  | import { NgxChartsModule } from '@swimlane/ngx-charts'; | ||||||
|  | import { FuseEcommerceDashboardComponent } from './dashboard/dashboard.component'; | ||||||
|  | import { EcommerceDashboardService } from './dashboard/dashboard.service'; | ||||||
|  | import { SharedModule } from '../../../../core/modules/shared.module'; | ||||||
|  | import { FuseWidgetModule } from '../../../../core/components/widget/widget.module'; | ||||||
|  | import { FuseEcommerceProductsComponent } from './products/products.component'; | ||||||
|  | import { EcommerceProductsService } from './products/products.service'; | ||||||
|  | import { FuseEcommerceProductComponent } from './product/product.component'; | ||||||
|  | import { EcommerceProductService } from './product/product.service'; | ||||||
|  | import { FuseEcommerceOrdersComponent } from './orders/orders.component'; | ||||||
|  | import { EcommerceOrdersService } from './orders/orders.service'; | ||||||
|  | import { FuseEcommerceOrderComponent } from './order/order.component'; | ||||||
|  | import { EcommerceOrderService } from './order/order.service'; | ||||||
|  | import { AgmCoreModule } from '@agm/core'; | ||||||
|  | 
 | ||||||
|  | const routes: Routes = [ | ||||||
|  |     { | ||||||
|  |         path     : 'dashboard', | ||||||
|  |         component: FuseEcommerceDashboardComponent, | ||||||
|  |         resolve  : { | ||||||
|  |             data: EcommerceDashboardService | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         path     : 'products', | ||||||
|  |         component: FuseEcommerceProductsComponent, | ||||||
|  |         resolve  : { | ||||||
|  |             data: EcommerceProductsService | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         path     : 'products/:id', | ||||||
|  |         component: FuseEcommerceProductComponent, | ||||||
|  |         resolve  : { | ||||||
|  |             data: EcommerceProductService | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         path     : 'products/:id/:handle', | ||||||
|  |         component: FuseEcommerceProductComponent, | ||||||
|  |         resolve  : { | ||||||
|  |             data: EcommerceProductService | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         path     : 'orders', | ||||||
|  |         component: FuseEcommerceOrdersComponent, | ||||||
|  |         resolve  : { | ||||||
|  |             data: EcommerceOrdersService | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         path     : 'orders/:id', | ||||||
|  |         component: FuseEcommerceOrderComponent, | ||||||
|  |         resolve  : { | ||||||
|  |             data: EcommerceOrderService | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | ]; | ||||||
|  | 
 | ||||||
|  | @NgModule({ | ||||||
|  |     imports     : [ | ||||||
|  |         SharedModule, | ||||||
|  |         RouterModule.forChild(routes), | ||||||
|  |         FuseWidgetModule, | ||||||
|  |         NgxChartsModule, | ||||||
|  |         AgmCoreModule.forRoot({ | ||||||
|  |             apiKey: 'AIzaSyD81ecsCj4yYpcXSLFcYU97PvRsE_X8Bx8' | ||||||
|  |         }) | ||||||
|  |     ], | ||||||
|  |     declarations: [ | ||||||
|  |         FuseEcommerceDashboardComponent, | ||||||
|  |         FuseEcommerceProductsComponent, | ||||||
|  |         FuseEcommerceProductComponent, | ||||||
|  |         FuseEcommerceOrdersComponent, | ||||||
|  |         FuseEcommerceOrderComponent | ||||||
|  |     ], | ||||||
|  |     providers   : [ | ||||||
|  |         EcommerceDashboardService, | ||||||
|  |         EcommerceProductsService, | ||||||
|  |         EcommerceProductService, | ||||||
|  |         EcommerceOrdersService, | ||||||
|  |         EcommerceOrderService | ||||||
|  |     ] | ||||||
|  | }) | ||||||
|  | export class FuseEcommerceModule | ||||||
|  | { | ||||||
|  | } | ||||||
							
								
								
									
										72
									
								
								src/app/main/content/apps/e-commerce/order/order-statuses.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/app/main/content/apps/e-commerce/order/order-statuses.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,72 @@ | |||||||
|  | export const orderStatuses = [ | ||||||
|  |     { | ||||||
|  |         'id'   : 1, | ||||||
|  |         'name' : 'Awaiting check payment', | ||||||
|  |         'color': 'mat-blue-500-bg' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         'id'   : 2, | ||||||
|  |         'name' : 'Payment accepted', | ||||||
|  |         'color': 'mat-green-500-bg' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         'id'   : 3, | ||||||
|  |         'name' : 'Preparing the order', | ||||||
|  |         'color': 'mat-orange-500-bg' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         'id'   : 4, | ||||||
|  |         'name' : 'Shipped', | ||||||
|  |         'color': 'mat-purple-500-bg' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         'id'   : 5, | ||||||
|  |         'name' : 'Delivered', | ||||||
|  |         'color': 'mat-green-800-bg' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         'id'   : 6, | ||||||
|  |         'name' : 'Canceled', | ||||||
|  |         'color': 'mat-pink-500-bg' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         'id'   : 7, | ||||||
|  |         'name' : 'Refunded', | ||||||
|  |         'color': 'mat-red-500-bg' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         'id'   : 8, | ||||||
|  |         'name' : 'Payment error', | ||||||
|  |         'color': 'mat-red-900-bg' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         'id'   : 9, | ||||||
|  |         'name' : 'On pre-order (paid)', | ||||||
|  |         'color': 'mat-purple-300-bg' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         'id'   : 10, | ||||||
|  |         'name' : 'Awaiting bank wire payment', | ||||||
|  |         'color': 'mat-blue-500-bg' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         'id'   : 11, | ||||||
|  |         'name' : 'Awaiting PayPal payment', | ||||||
|  |         'color': 'mat-blue-500-bg' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         'id'   : 12, | ||||||
|  |         'name' : 'Remote payment accepted', | ||||||
|  |         'color': 'mat-green-500-bg' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         'id'   : 13, | ||||||
|  |         'name' : 'On pre-order (not paid)', | ||||||
|  |         'color': 'mat-purple-300-bg' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         'id'   : 14, | ||||||
|  |         'name' : 'Awaiting Cash-on-delivery payment', | ||||||
|  |         'color': 'mat-blue-500-bg' | ||||||
|  |     } | ||||||
|  | ]; | ||||||
							
								
								
									
										429
									
								
								src/app/main/content/apps/e-commerce/order/order.component.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										429
									
								
								src/app/main/content/apps/e-commerce/order/order.component.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,429 @@ | |||||||
|  | <div id="order" class="page-layout carded fullwidth" fusePerfectScrollbar> | ||||||
|  | 
 | ||||||
|  |     <!-- TOP BACKGROUND --> | ||||||
|  |     <div class="top-bg mat-accent-bg"></div> | ||||||
|  |     <!-- / TOP BACKGROUND --> | ||||||
|  | 
 | ||||||
|  |     <!-- CENTER --> | ||||||
|  |     <div class="center"> | ||||||
|  | 
 | ||||||
|  |         <!-- HEADER --> | ||||||
|  |         <div class="header white-fg" | ||||||
|  |              fxLayout="row" fxLayoutAlign="space-between center"> | ||||||
|  | 
 | ||||||
|  |             <!-- APP TITLE --> | ||||||
|  |             <div fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  | 
 | ||||||
|  |                 <button class="mr-16" mat-icon-button [routerLink]="'/apps/e-commerce/orders'"> | ||||||
|  |                     <mat-icon>arrow_back</mat-icon> | ||||||
|  |                 </button> | ||||||
|  | 
 | ||||||
|  |                 <div fxLayout="column" fxLayoutAlign="start start" | ||||||
|  |                      *fuseIfOnDom [@animate]="{value:'*',params:{delay:'100ms',x:'-25px'}}"> | ||||||
|  |                     <div class="h2"> | ||||||
|  |                         Order {{order.reference}} | ||||||
|  |                     </div> | ||||||
|  |                     <div class="subtitle secondary-text"> | ||||||
|  |                         <span>from</span> | ||||||
|  |                         <span>{{order.customer.firstName}} {{order.customer.lastName}}</span> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  |             <!-- / APP TITLE --> | ||||||
|  | 
 | ||||||
|  |         </div> | ||||||
|  |         <!-- / HEADER --> | ||||||
|  | 
 | ||||||
|  |         <!-- CONTENT CARD --> | ||||||
|  |         <div class="content-card mat-white-bg"> | ||||||
|  | 
 | ||||||
|  |             <!-- CONTENT --> | ||||||
|  |             <div class="content"> | ||||||
|  | 
 | ||||||
|  |                 <mat-tab-group> | ||||||
|  | 
 | ||||||
|  |                     <mat-tab label="Order Details"> | ||||||
|  | 
 | ||||||
|  |                         <div class="order-details tab-content p-24" fusePerfectScrollbar> | ||||||
|  | 
 | ||||||
|  |                             <div class="section pb-48"> | ||||||
|  | 
 | ||||||
|  |                                 <div class="pb-16" fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  |                                     <mat-icon class="m-0 mr-16">account_circle</mat-icon> | ||||||
|  |                                     <div class="h2 secondary-text">Customer</div> | ||||||
|  |                                 </div> | ||||||
|  | 
 | ||||||
|  |                                 <div class="customer"> | ||||||
|  |                                     <table class="simple"> | ||||||
|  |                                         <thead> | ||||||
|  |                                             <tr> | ||||||
|  |                                                 <th>Name</th> | ||||||
|  |                                                 <th>Email</th> | ||||||
|  |                                                 <th>Phone</th> | ||||||
|  |                                                 <th>Company</th> | ||||||
|  |                                             </tr> | ||||||
|  |                                         </thead> | ||||||
|  |                                         <tbody> | ||||||
|  |                                             <tr> | ||||||
|  |                                                 <td> | ||||||
|  |                                                     <div fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  |                                                         <img class="avatar" [src]="order.customer.avatar"> | ||||||
|  |                                                         <span class="name text-truncate">{{order.customer.firstName}} {{order.customer.lastName}}</span> | ||||||
|  |                                                     </div> | ||||||
|  |                                                 </td> | ||||||
|  |                                                 <td> | ||||||
|  |                                                     <span class="email text-truncate">{{order.customer.email}}</span> | ||||||
|  |                                                 </td> | ||||||
|  |                                                 <td> | ||||||
|  |                                                     <span class="phone text-truncate">{{order.customer.phone}}</span> | ||||||
|  |                                                 </td> | ||||||
|  |                                                 <td> | ||||||
|  |                                                     <span class="company text-truncate">{{order.customer.company}}</span> | ||||||
|  |                                                 </td> | ||||||
|  |                                             </tr> | ||||||
|  |                                         </tbody> | ||||||
|  |                                     </table> | ||||||
|  |                                 </div> | ||||||
|  | 
 | ||||||
|  |                                 <mat-tab-group class="addresses"> | ||||||
|  | 
 | ||||||
|  |                                     <mat-tab label="Shipping Address"> | ||||||
|  |                                         <div fxFlex fxLayout="column" *fuseIfOnDom> | ||||||
|  |                                             <div class="address h4 py-24">{{order.customer.shippingAddress.address}}</div> | ||||||
|  |                                             <agm-map class="w-100-p h-400" [zoom]="15" | ||||||
|  |                                                      [latitude]="order.customer.shippingAddress.lat" | ||||||
|  |                                                      [longitude]="order.customer.shippingAddress.lng"> | ||||||
|  |                                                 <agm-marker [latitude]="order.customer.shippingAddress.lat" | ||||||
|  |                                                             [longitude]="order.customer.shippingAddress.lng"> | ||||||
|  |                                                 </agm-marker> | ||||||
|  |                                             </agm-map> | ||||||
|  |                                         </div> | ||||||
|  |                                     </mat-tab> | ||||||
|  | 
 | ||||||
|  |                                     <mat-tab label="Invoice Address" fxLayout="column"> | ||||||
|  |                                         <div fxFlex fxLayout="column" *fuseIfOnDom> | ||||||
|  |                                             <div class="address h4 py-24">{{order.customer.invoiceAddress.address}}</div> | ||||||
|  |                                             <agm-map class="w-100-p h-400" [zoom]="15" | ||||||
|  |                                                      [latitude]="order.customer.invoiceAddress.lat" | ||||||
|  |                                                      [longitude]="order.customer.invoiceAddress.lng"> | ||||||
|  |                                                 <agm-marker [latitude]="order.customer.invoiceAddress.lat" | ||||||
|  |                                                             [longitude]="order.customer.invoiceAddress.lng"> | ||||||
|  |                                                 </agm-marker> | ||||||
|  |                                             </agm-map> | ||||||
|  |                                         </div> | ||||||
|  |                                     </mat-tab> | ||||||
|  |                                 </mat-tab-group> | ||||||
|  |                             </div> | ||||||
|  | 
 | ||||||
|  |                             <div class="section pb-48"> | ||||||
|  | 
 | ||||||
|  |                                 <div class="pb-16" fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  |                                     <mat-icon class="m-0 mr-16">access_time</mat-icon> | ||||||
|  |                                     <div class="h2 secondary-text">Order Status</div> | ||||||
|  |                                 </div> | ||||||
|  | 
 | ||||||
|  |                                 <table class="simple"> | ||||||
|  |                                     <thead> | ||||||
|  |                                         <tr> | ||||||
|  |                                             <th>Status</th> | ||||||
|  |                                             <th>Updated On</th> | ||||||
|  |                                         </tr> | ||||||
|  |                                     </thead> | ||||||
|  |                                     <tbody> | ||||||
|  | 
 | ||||||
|  |                                         <tr *ngFor="let status of order.status"> | ||||||
|  |                                             <td> | ||||||
|  |                                                 <span class="status h6 p-4" [ngClass]="status.color"> | ||||||
|  |                                                     {{status.name}} | ||||||
|  |                                                 </span> | ||||||
|  |                                             </td> | ||||||
|  |                                             <td> | ||||||
|  |                                                 <span> | ||||||
|  |                                                     {{status.date | date}} | ||||||
|  |                                                 </span> | ||||||
|  |                                             </td> | ||||||
|  |                                         </tr> | ||||||
|  |                                     </tbody> | ||||||
|  |                                 </table> | ||||||
|  | 
 | ||||||
|  |                                 <form class="update-status p-24" | ||||||
|  |                                       (ngSubmit)="updateStatus()" | ||||||
|  |                                       [formGroup]="statusForm" | ||||||
|  |                                       fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  | 
 | ||||||
|  |                                     <mat-form-field class="mr-16" fxFlex> | ||||||
|  |                                         <mat-select formControlName="newStatus" | ||||||
|  |                                                     placeholder="Select a status" required> | ||||||
|  |                                             <mat-option *ngFor="let status of orderStatuses" | ||||||
|  |                                                         [value]="status.id"> | ||||||
|  |                                                 {{status.name}} | ||||||
|  |                                             </mat-option> | ||||||
|  |                                         </mat-select> | ||||||
|  |                                     </mat-form-field> | ||||||
|  | 
 | ||||||
|  |                                     <button mat-raised-button class="mat-accent" | ||||||
|  |                                             [disabled]="statusForm.invalid"> | ||||||
|  |                                         Update Status | ||||||
|  |                                     </button> | ||||||
|  |                                 </form> | ||||||
|  | 
 | ||||||
|  |                             </div> | ||||||
|  | 
 | ||||||
|  |                             <div class="section pb-48"> | ||||||
|  | 
 | ||||||
|  |                                 <div class="pb-16" fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  |                                     <mat-icon class="m-0 mr-16">attach_money</mat-icon> | ||||||
|  |                                     <div class="h2 secondary-text">Payment</div> | ||||||
|  |                                 </div> | ||||||
|  | 
 | ||||||
|  |                                 <table class="simple"> | ||||||
|  |                                     <thead> | ||||||
|  |                                         <tr> | ||||||
|  |                                             <th>TransactionID</th> | ||||||
|  |                                             <th>Payment Method</th> | ||||||
|  |                                             <th>Amount</th> | ||||||
|  |                                             <th>Date</th> | ||||||
|  |                                         </tr> | ||||||
|  |                                     </thead> | ||||||
|  |                                     <tbody> | ||||||
|  |                                         <tr> | ||||||
|  |                                             <td> | ||||||
|  |                                                 <span class="text-truncate"> | ||||||
|  |                                                     {{order.payment.transactionId}} | ||||||
|  |                                                 </span> | ||||||
|  |                                             </td> | ||||||
|  |                                             <td> | ||||||
|  |                                                 <span class="text-truncate"> | ||||||
|  |                                                     {{order.payment.method}} | ||||||
|  |                                                 </span> | ||||||
|  |                                             </td> | ||||||
|  |                                             <td> | ||||||
|  |                                                 <span class="text-truncate"> | ||||||
|  |                                                     {{order.payment.amount}} | ||||||
|  |                                                 </span> | ||||||
|  |                                             </td> | ||||||
|  |                                             <td> | ||||||
|  |                                                 <span class="text-truncate"> | ||||||
|  |                                                     {{order.payment.date | date}} | ||||||
|  |                                                 </span> | ||||||
|  |                                             </td> | ||||||
|  |                                         </tr> | ||||||
|  |                                     </tbody> | ||||||
|  |                                 </table> | ||||||
|  |                             </div> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |                             <div class="section pb-48"> | ||||||
|  | 
 | ||||||
|  |                                 <div class="pb-16" fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  |                                     <mat-icon class="m-0 mr-16">local_shipping</mat-icon> | ||||||
|  |                                     <div class="h2 secondary-text">Shipping</div> | ||||||
|  |                                 </div> | ||||||
|  | 
 | ||||||
|  |                                 <table class="simple"> | ||||||
|  |                                     <thead> | ||||||
|  |                                         <tr> | ||||||
|  |                                             <th>Tracking Code</th> | ||||||
|  |                                             <th>Carrier</th> | ||||||
|  |                                             <th>Weight</th> | ||||||
|  |                                             <th>Fee</th> | ||||||
|  |                                             <th>Date</th> | ||||||
|  |                                         </tr> | ||||||
|  |                                     </thead> | ||||||
|  |                                     <tbody> | ||||||
|  |                                         <tr *ngFor="let shipping of order.shippingDetails"> | ||||||
|  |                                             <td class="tracking-code"> | ||||||
|  |                                                 {{shipping.tracking}} | ||||||
|  |                                             </td> | ||||||
|  |                                             <td> | ||||||
|  |                                                 {{shipping.carrier}} | ||||||
|  |                                             </td> | ||||||
|  |                                             <td> | ||||||
|  |                                                 {{shipping.weight}} | ||||||
|  |                                             </td> | ||||||
|  |                                             <td> | ||||||
|  |                                                 {{shipping.fee}} | ||||||
|  |                                             </td> | ||||||
|  |                                             <td> | ||||||
|  |                                                 {{shipping.date}} | ||||||
|  |                                             </td> | ||||||
|  |                                         </tr> | ||||||
|  |                                     </tbody> | ||||||
|  |                                 </table> | ||||||
|  |                             </div> | ||||||
|  | 
 | ||||||
|  |                         </div> | ||||||
|  |                     </mat-tab> | ||||||
|  | 
 | ||||||
|  |                     <mat-tab label="Products"> | ||||||
|  |                         <div class="products tab-content p-24" fusePerfectScrollbar> | ||||||
|  |                             <table class="simple"> | ||||||
|  |                                 <thead> | ||||||
|  |                                     <tr> | ||||||
|  |                                         <th>ID</th> | ||||||
|  |                                         <th>Image</th> | ||||||
|  |                                         <th>Name</th> | ||||||
|  |                                         <th>Price</th> | ||||||
|  |                                         <th>Quantity</th> | ||||||
|  |                                     </tr> | ||||||
|  |                                 </thead> | ||||||
|  |                                 <tbody> | ||||||
|  |                                     <tr class="product-row" | ||||||
|  |                                         *ngFor="let product of order.products" | ||||||
|  |                                         [routerLink]="'/apps/e-commerce/products/'+product.id+'/'+product.handle"> | ||||||
|  |                                         <td class="w-64"> | ||||||
|  |                                             {{product.id}} | ||||||
|  |                                         </td> | ||||||
|  |                                         <td class="w-80"> | ||||||
|  |                                             <img class="product-image" [src]="product.image"> | ||||||
|  |                                         </td> | ||||||
|  |                                         <td> | ||||||
|  |                                             {{product.name}} | ||||||
|  |                                         </td> | ||||||
|  |                                         <td> | ||||||
|  |                                             {{product.price}} | ||||||
|  |                                         </td> | ||||||
|  |                                         <td> | ||||||
|  |                                             {{product.quantity}} | ||||||
|  |                                         </td> | ||||||
|  |                                     </tr> | ||||||
|  |                                 </tbody> | ||||||
|  |                             </table> | ||||||
|  |                         </div> | ||||||
|  |                     </mat-tab> | ||||||
|  | 
 | ||||||
|  |                     <mat-tab label="Invoice"> | ||||||
|  | 
 | ||||||
|  |                         <div class="invoice tab-content p-24" fusePerfectScrollbar> | ||||||
|  | 
 | ||||||
|  |                             <div id="invoice" class="compact page-layout blank" fxLayout="row" fusePerfectScrollbar> | ||||||
|  | 
 | ||||||
|  |                                 <div class="invoice-container"> | ||||||
|  | 
 | ||||||
|  |                                     <!-- INVOICE --> | ||||||
|  |                                     <div class="card"> | ||||||
|  | 
 | ||||||
|  |                                         <div class="header"> | ||||||
|  |                                             <div class="invoice-date">{{order.date}}</div> | ||||||
|  | 
 | ||||||
|  |                                             <div fxLayout="row" fxLayoutAlign="space-between stretch"> | ||||||
|  |                                                 <div class="client"> | ||||||
|  |                                                     <div class="invoice-number" fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  |                                                         <span class="title">INVOICE</span> | ||||||
|  |                                                         <span class="number">{{order.reference}}</span> | ||||||
|  |                                                     </div> | ||||||
|  | 
 | ||||||
|  |                                                     <div class="info"> | ||||||
|  |                                                         <div class="title"> | ||||||
|  |                                                             {{order.customer.firstName}} | ||||||
|  |                                                             {{order.customer.lastName}} | ||||||
|  |                                                         </div> | ||||||
|  |                                                         <div class="address">{{order.customer.invoiceAddress}}</div> | ||||||
|  |                                                         <div class="phone">{{order.customer.phone}}</div> | ||||||
|  |                                                         <div class="email">{{order.customer.email}}</div> | ||||||
|  |                                                     </div> | ||||||
|  |                                                 </div> | ||||||
|  | 
 | ||||||
|  |                                                 <div class="issuer mat-accent-bg" fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  |                                                     <div class="logo"> | ||||||
|  |                                                         <img src="assets/images/logos/fuse.svg"> | ||||||
|  |                                                     </div> | ||||||
|  | 
 | ||||||
|  |                                                     <div class="info"> | ||||||
|  |                                                         <div class="title">FUSE INC.</div> | ||||||
|  |                                                         <div class="address">2810 Country Club Road Cranford, NJ 07016</div> | ||||||
|  |                                                         <div class="phone">+66 123 455 87</div> | ||||||
|  |                                                         <div class="email">hello@fuseinc.com</div> | ||||||
|  |                                                         <div class="website">www.fuseinc.com</div> | ||||||
|  |                                                     </div> | ||||||
|  |                                                 </div> | ||||||
|  |                                             </div> | ||||||
|  |                                         </div> | ||||||
|  | 
 | ||||||
|  |                                         <div class="content"> | ||||||
|  | 
 | ||||||
|  |                                             <table class="simple invoice-table"> | ||||||
|  |                                                 <thead> | ||||||
|  |                                                     <tr> | ||||||
|  |                                                         <th>PRODUCT</th> | ||||||
|  |                                                         <th class="text-right">PRICE</th> | ||||||
|  |                                                         <th class="text-right">QUANTITY</th> | ||||||
|  |                                                         <th class="text-right">TOTAL</th> | ||||||
|  |                                                     </tr> | ||||||
|  |                                                 </thead> | ||||||
|  |                                                 <tbody> | ||||||
|  |                                                     <tr *ngFor="let product of order.products"> | ||||||
|  |                                                         <td> | ||||||
|  |                                                             <div class="title"> | ||||||
|  |                                                                 {{product.name}} | ||||||
|  |                                                             </div> | ||||||
|  |                                                         </td> | ||||||
|  |                                                         <td class="text-right"> | ||||||
|  |                                                             {{product.price | currency:'USD':true}} | ||||||
|  |                                                         </td> | ||||||
|  |                                                         <td class="text-right"> | ||||||
|  |                                                             {{product.quantity}} | ||||||
|  |                                                         </td> | ||||||
|  |                                                         <td class="text-right"> | ||||||
|  |                                                             {{product.total | currency:'USD':true}} | ||||||
|  |                                                         </td> | ||||||
|  |                                                     </tr> | ||||||
|  |                                                 </tbody> | ||||||
|  |                                             </table> | ||||||
|  | 
 | ||||||
|  |                                             <table class="simple invoice-table-footer"> | ||||||
|  |                                                 <tbody> | ||||||
|  |                                                     <tr class="subtotal"> | ||||||
|  |                                                         <td>SUBTOTAL</td> | ||||||
|  |                                                         <td>{{order.subtotal | currency:'USD':true}}</td> | ||||||
|  |                                                     </tr> | ||||||
|  |                                                     <tr class="tax"> | ||||||
|  |                                                         <td>TAX</td> | ||||||
|  |                                                         <td>{{order.tax | currency:'USD':true}}</td> | ||||||
|  |                                                     </tr> | ||||||
|  |                                                     <tr class="discount"> | ||||||
|  |                                                         <td>DISCOUNT</td> | ||||||
|  |                                                         <td>-{{order.discount | currency:'USD':true}}</td> | ||||||
|  |                                                     </tr> | ||||||
|  |                                                     <tr class="total"> | ||||||
|  |                                                         <td>TOTAL</td> | ||||||
|  |                                                         <td>{{order.total | currency:'USD':true}}</td> | ||||||
|  |                                                     </tr> | ||||||
|  |                                                 </tbody> | ||||||
|  |                                             </table> | ||||||
|  |                                         </div> | ||||||
|  | 
 | ||||||
|  |                                         <div class="footer"> | ||||||
|  |                                             <div class="note">Please pay within 15 days. Thank you for your business.</div> | ||||||
|  |                                             <div fxLayout="row" fxLayoutAlign="start start"> | ||||||
|  |                                                 <div class="logo"> | ||||||
|  |                                                     <img src="assets/images/logos/fuse.svg"> | ||||||
|  |                                                 </div> | ||||||
|  |                                                 <div class="small-note"> | ||||||
|  |                                                     In condimentum malesuada efficitur. Mauris volutpat placerat auctor. Ut ac congue dolor. Quisque | ||||||
|  |                                                     scelerisque lacus sed feugiat fermentum. Cras aliquet facilisis pellentesque. Nunc hendrerit | ||||||
|  |                                                     quam at leo commodo, a suscipit tellus dapibus. Etiam at felis volutpat est mollis lacinia. | ||||||
|  |                                                     Mauris placerat sem sit amet velit mollis, in porttitor ex finibus. Proin eu nibh id libero | ||||||
|  |                                                     tincidunt lacinia et eget eros. | ||||||
|  |                                                 </div> | ||||||
|  |                                             </div> | ||||||
|  |                                         </div> | ||||||
|  |                                     </div> | ||||||
|  |                                     <!-- / INVOICE --> | ||||||
|  | 
 | ||||||
|  |                                 </div> | ||||||
|  |                             </div> | ||||||
|  |                         </div> | ||||||
|  |                     </mat-tab> | ||||||
|  | 
 | ||||||
|  |                 </mat-tab-group> | ||||||
|  | 
 | ||||||
|  |             </div> | ||||||
|  |             <!-- / CONTENT --> | ||||||
|  | 
 | ||||||
|  |         </div> | ||||||
|  |         <!-- / CONTENT CARD --> | ||||||
|  | 
 | ||||||
|  |     </div> | ||||||
|  |     <!-- / CENTER --> | ||||||
|  | </div> | ||||||
							
								
								
									
										395
									
								
								src/app/main/content/apps/e-commerce/order/order.component.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										395
									
								
								src/app/main/content/apps/e-commerce/order/order.component.scss
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,395 @@ | |||||||
|  | @import "src/app/core/scss/fuse"; | ||||||
|  | 
 | ||||||
|  | #order { | ||||||
|  | 
 | ||||||
|  |     .header { | ||||||
|  | 
 | ||||||
|  |         .subtitle { | ||||||
|  |             margin: 6px 0 0 0; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     .content { | ||||||
|  | 
 | ||||||
|  |         .mat-tab-group, | ||||||
|  |         .mat-tab-body-wrapper, | ||||||
|  |         .tab-content { | ||||||
|  |             flex: 1 1 auto; | ||||||
|  |             max-width: 100%; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .tab-content { | ||||||
|  |             flex: 1 1 auto; | ||||||
|  | 
 | ||||||
|  |             &.products { | ||||||
|  | 
 | ||||||
|  |                 .product-row { | ||||||
|  |                     cursor: pointer; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             &.invoice { | ||||||
|  | 
 | ||||||
|  |                 #invoice { | ||||||
|  | 
 | ||||||
|  |                     &.compact { | ||||||
|  |                         padding: 0; | ||||||
|  |                         overflow: auto; | ||||||
|  | 
 | ||||||
|  |                         .invoice-container { | ||||||
|  |                             padding: 64px; | ||||||
|  | 
 | ||||||
|  |                             .card { | ||||||
|  |                                 width: 1020px; | ||||||
|  |                                 min-width: 1020px; | ||||||
|  |                                 max-width: 1020px; | ||||||
|  |                                 padding: 64px 88px; | ||||||
|  |                                 overflow: hidden; | ||||||
|  |                                 background: #FFFFFF; | ||||||
|  |                                 @include mat-elevation(7); | ||||||
|  | 
 | ||||||
|  |                                 .header { | ||||||
|  | 
 | ||||||
|  |                                     .invoice-date { | ||||||
|  |                                         font-size: 14px; | ||||||
|  |                                         color: rgba(0, 0, 0, 0.54); | ||||||
|  |                                         margin-bottom: 32px; | ||||||
|  |                                     } | ||||||
|  | 
 | ||||||
|  |                                     .client { | ||||||
|  | 
 | ||||||
|  |                                         .invoice-number { | ||||||
|  |                                             font-size: 18px; | ||||||
|  |                                             padding-bottom: 2px; | ||||||
|  | 
 | ||||||
|  |                                             .title { | ||||||
|  |                                                 color: rgba(0, 0, 0, 0.54); | ||||||
|  |                                             } | ||||||
|  | 
 | ||||||
|  |                                             .number { | ||||||
|  |                                                 padding-left: 6px; | ||||||
|  |                                             } | ||||||
|  |                                         } | ||||||
|  | 
 | ||||||
|  |                                         .due-date { | ||||||
|  |                                             font-size: 18px; | ||||||
|  |                                             padding-bottom: 16px; | ||||||
|  | 
 | ||||||
|  |                                             .title { | ||||||
|  |                                                 color: rgba(0, 0, 0, 0.54); | ||||||
|  |                                             } | ||||||
|  | 
 | ||||||
|  |                                             .date { | ||||||
|  |                                                 padding-left: 6px; | ||||||
|  |                                             } | ||||||
|  |                                         } | ||||||
|  | 
 | ||||||
|  |                                         .info { | ||||||
|  |                                             color: rgba(0, 0, 0, 0.54); | ||||||
|  |                                             line-height: 22px; | ||||||
|  |                                         } | ||||||
|  |                                     } | ||||||
|  | 
 | ||||||
|  |                                     .issuer { | ||||||
|  |                                         margin-right: -88px; | ||||||
|  |                                         padding-right: 66px; | ||||||
|  | 
 | ||||||
|  |                                         .logo { | ||||||
|  |                                             width: 96px; | ||||||
|  |                                             padding: 0 8px; | ||||||
|  |                                             border-right: 1px solid rgba(255, 255, 255, 0.7); | ||||||
|  |                                         } | ||||||
|  | 
 | ||||||
|  |                                         .info { | ||||||
|  |                                             padding: 16px; | ||||||
|  |                                         } | ||||||
|  |                                     } | ||||||
|  |                                 } | ||||||
|  | 
 | ||||||
|  |                                 .content { | ||||||
|  | 
 | ||||||
|  |                                     .invoice-table { | ||||||
|  |                                         margin-top: 64px; | ||||||
|  |                                         font-size: 15px; | ||||||
|  | 
 | ||||||
|  |                                         thead { | ||||||
|  | 
 | ||||||
|  |                                             tr { | ||||||
|  | 
 | ||||||
|  |                                                 th { | ||||||
|  | 
 | ||||||
|  |                                                     &:first-child { | ||||||
|  |                                                         padding-left: 8px; | ||||||
|  |                                                     } | ||||||
|  | 
 | ||||||
|  |                                                     &:last-child { | ||||||
|  |                                                         padding-right: 8px; | ||||||
|  |                                                     } | ||||||
|  |                                                 } | ||||||
|  |                                             } | ||||||
|  |                                         } | ||||||
|  | 
 | ||||||
|  |                                         tbody { | ||||||
|  | 
 | ||||||
|  |                                             tr { | ||||||
|  | 
 | ||||||
|  |                                                 td { | ||||||
|  | 
 | ||||||
|  |                                                     &:first-child { | ||||||
|  |                                                         padding-left: 8px; | ||||||
|  |                                                     } | ||||||
|  | 
 | ||||||
|  |                                                     &:last-child { | ||||||
|  |                                                         padding-right: 8px; | ||||||
|  |                                                     } | ||||||
|  |                                                 } | ||||||
|  |                                             } | ||||||
|  |                                         } | ||||||
|  | 
 | ||||||
|  |                                         .title { | ||||||
|  |                                             font-size: 16px; | ||||||
|  |                                         } | ||||||
|  | 
 | ||||||
|  |                                         .detail { | ||||||
|  |                                             margin-top: 8px; | ||||||
|  |                                             font-size: 12px; | ||||||
|  |                                             color: rgba(0, 0, 0, 0.54); | ||||||
|  |                                             max-width: 360px; | ||||||
|  |                                         } | ||||||
|  |                                     } | ||||||
|  | 
 | ||||||
|  |                                     .invoice-table-footer { | ||||||
|  |                                         margin: 32px 0 72px 0; | ||||||
|  | 
 | ||||||
|  |                                         tr { | ||||||
|  | 
 | ||||||
|  |                                             td { | ||||||
|  |                                                 text-align: right; | ||||||
|  |                                                 font-size: 16px; | ||||||
|  |                                                 font-weight: 500; | ||||||
|  |                                                 color: rgba(0, 0, 0, 0.54); | ||||||
|  |                                                 border-bottom: none; | ||||||
|  |                                                 padding: 4px 8px; | ||||||
|  | 
 | ||||||
|  |                                                 &:first-child { | ||||||
|  |                                                     text-align: left; | ||||||
|  |                                                 } | ||||||
|  |                                             } | ||||||
|  | 
 | ||||||
|  |                                             &.discount { | ||||||
|  | 
 | ||||||
|  |                                                 td { | ||||||
|  |                                                     padding-bottom: 32px; | ||||||
|  |                                                 } | ||||||
|  |                                             } | ||||||
|  | 
 | ||||||
|  |                                             &.total { | ||||||
|  | 
 | ||||||
|  |                                                 td { | ||||||
|  |                                                     padding: 24px 8px; | ||||||
|  |                                                     border-top: 1px solid rgba(0, 0, 0, 0.12); | ||||||
|  |                                                     font-size: 35px; | ||||||
|  |                                                     font-weight: 300; | ||||||
|  |                                                     color: rgba(0, 0, 0, 1); | ||||||
|  |                                                 } | ||||||
|  |                                             } | ||||||
|  |                                         } | ||||||
|  |                                     } | ||||||
|  |                                 } | ||||||
|  | 
 | ||||||
|  |                                 .footer { | ||||||
|  | 
 | ||||||
|  |                                     .note { | ||||||
|  |                                         font-size: 15px; | ||||||
|  |                                         font-weight: 500; | ||||||
|  |                                         margin-bottom: 24px; | ||||||
|  |                                     } | ||||||
|  | 
 | ||||||
|  |                                     // IE10 fix | ||||||
|  |                                     .logo, .small-note { | ||||||
|  |                                         -ms-flex: 0 1 auto; | ||||||
|  |                                     } | ||||||
|  | 
 | ||||||
|  |                                     .logo { | ||||||
|  |                                         width: 32px; | ||||||
|  |                                         min-width: 32px; | ||||||
|  |                                         margin-right: 24px; | ||||||
|  |                                     } | ||||||
|  | 
 | ||||||
|  |                                     .small-note { | ||||||
|  |                                         font-size: 12px; | ||||||
|  |                                         font-weight: 500; | ||||||
|  |                                         color: rgba(0, 0, 0, 0.54); | ||||||
|  |                                         line-height: 18px; | ||||||
|  |                                     } | ||||||
|  |                                 } | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 /* PRINT STYLES */ | ||||||
|  |                 @media print { | ||||||
|  | 
 | ||||||
|  |                     /* Invoice Specific Styles */ | ||||||
|  |                     #invoice { | ||||||
|  | 
 | ||||||
|  |                         &.compact { | ||||||
|  | 
 | ||||||
|  |                             .invoice-container { | ||||||
|  |                                 padding: 0; | ||||||
|  | 
 | ||||||
|  |                                 .card { | ||||||
|  |                                     width: 100%; | ||||||
|  |                                     min-width: 0; | ||||||
|  |                                     background: none; | ||||||
|  |                                     padding: 0; | ||||||
|  |                                     box-shadow: none; | ||||||
|  | 
 | ||||||
|  |                                     .header { | ||||||
|  | 
 | ||||||
|  |                                         .invoice-date { | ||||||
|  |                                             margin-bottom: 16pt; | ||||||
|  |                                         } | ||||||
|  | 
 | ||||||
|  |                                         .issuer { | ||||||
|  |                                             padding-right: 0; | ||||||
|  |                                             margin-right: 0; | ||||||
|  |                                         } | ||||||
|  |                                     } | ||||||
|  | 
 | ||||||
|  |                                     .content { | ||||||
|  | 
 | ||||||
|  |                                         .invoice-table { | ||||||
|  |                                             margin-top: 16pt; | ||||||
|  | 
 | ||||||
|  |                                             thead { | ||||||
|  | 
 | ||||||
|  |                                                 tr { | ||||||
|  | 
 | ||||||
|  |                                                     th { | ||||||
|  |                                                         font-size: 10pt; | ||||||
|  |                                                         max-width: 60pt; | ||||||
|  | 
 | ||||||
|  |                                                         &:first-child { | ||||||
|  |                                                             padding-left: 0; | ||||||
|  |                                                         } | ||||||
|  | 
 | ||||||
|  |                                                         &:last-child { | ||||||
|  |                                                             padding-right: 0; | ||||||
|  |                                                         } | ||||||
|  |                                                     } | ||||||
|  |                                                 } | ||||||
|  |                                             } | ||||||
|  | 
 | ||||||
|  |                                             tbody { | ||||||
|  | 
 | ||||||
|  |                                                 tr { | ||||||
|  | 
 | ||||||
|  |                                                     td { | ||||||
|  | 
 | ||||||
|  |                                                         &:first-child { | ||||||
|  |                                                             padding-left: 0; | ||||||
|  |                                                         } | ||||||
|  | 
 | ||||||
|  |                                                         &:last-child { | ||||||
|  |                                                             padding-right: 0; | ||||||
|  |                                                         } | ||||||
|  |                                                     } | ||||||
|  |                                                 } | ||||||
|  |                                             } | ||||||
|  | 
 | ||||||
|  |                                             .title { | ||||||
|  |                                                 font-size: 10pt; | ||||||
|  |                                             } | ||||||
|  | 
 | ||||||
|  |                                             .detail { | ||||||
|  |                                                 margin-top: 4pt; | ||||||
|  |                                                 font-size: 9pt; | ||||||
|  |                                                 max-width: none; | ||||||
|  |                                             } | ||||||
|  |                                         } | ||||||
|  | 
 | ||||||
|  |                                         .invoice-table-footer { | ||||||
|  |                                             margin: 16pt 0; | ||||||
|  | 
 | ||||||
|  |                                             tr { | ||||||
|  | 
 | ||||||
|  |                                                 td { | ||||||
|  |                                                     font-size: 13pt; | ||||||
|  |                                                     padding: 4pt 4pt; | ||||||
|  | 
 | ||||||
|  |                                                     &:first-child { | ||||||
|  |                                                         text-align: left; | ||||||
|  |                                                         padding-left: 0; | ||||||
|  |                                                     } | ||||||
|  | 
 | ||||||
|  |                                                     &:last-child { | ||||||
|  |                                                         padding-right: 0; | ||||||
|  |                                                     } | ||||||
|  |                                                 } | ||||||
|  | 
 | ||||||
|  |                                                 &.discount { | ||||||
|  | 
 | ||||||
|  |                                                     td { | ||||||
|  |                                                         padding-bottom: 16pt; | ||||||
|  |                                                     } | ||||||
|  |                                                 } | ||||||
|  | 
 | ||||||
|  |                                                 &.total { | ||||||
|  | 
 | ||||||
|  |                                                     td { | ||||||
|  |                                                         padding: 16pt 4pt 0 4pt; | ||||||
|  |                                                         font-size: 16pt; | ||||||
|  | 
 | ||||||
|  |                                                         &:first-child { | ||||||
|  |                                                             padding-left: 0; | ||||||
|  |                                                         } | ||||||
|  | 
 | ||||||
|  |                                                         &:last-child { | ||||||
|  |                                                             padding-right: 0; | ||||||
|  |                                                         } | ||||||
|  |                                                     } | ||||||
|  |                                                 } | ||||||
|  |                                             } | ||||||
|  |                                         } | ||||||
|  |                                     } | ||||||
|  | 
 | ||||||
|  |                                     .footer { | ||||||
|  | 
 | ||||||
|  |                                         .note { | ||||||
|  |                                             font-size: 10pt; | ||||||
|  |                                             margin-bottom: 8pt; | ||||||
|  |                                         } | ||||||
|  | 
 | ||||||
|  |                                         .logo { | ||||||
|  |                                             margin-right: 8pt; | ||||||
|  |                                         } | ||||||
|  | 
 | ||||||
|  |                                         .small-note { | ||||||
|  |                                             font-size: 8pt; | ||||||
|  |                                             line-height: normal; | ||||||
|  |                                         } | ||||||
|  |                                     } | ||||||
|  |                                 } | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .mat-tab-body-content { | ||||||
|  |             display: flex; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .mat-tab-label { | ||||||
|  |             height: 64px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         table { | ||||||
|  |             table-layout: fixed; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,78 @@ | |||||||
|  | import { Component, ElementRef, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; | ||||||
|  | import { EcommerceOrderService } from './order.service'; | ||||||
|  | import { fuseAnimations } from '../../../../../core/animations'; | ||||||
|  | import 'rxjs/add/operator/startWith'; | ||||||
|  | import 'rxjs/add/observable/merge'; | ||||||
|  | import 'rxjs/add/operator/map'; | ||||||
|  | import 'rxjs/add/operator/debounceTime'; | ||||||
|  | import 'rxjs/add/operator/distinctUntilChanged'; | ||||||
|  | import 'rxjs/add/observable/fromEvent'; | ||||||
|  | import { Subscription } from 'rxjs/Subscription'; | ||||||
|  | import { Order } from './order.model'; | ||||||
|  | import { FormBuilder, FormGroup } from '@angular/forms'; | ||||||
|  | import { FuseUtils } from '../../../../../core/fuseUtils'; | ||||||
|  | import { MatSnackBar } from '@angular/material'; | ||||||
|  | import { Location } from '@angular/common'; | ||||||
|  | import { orderStatuses } from './order-statuses'; | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |     selector     : 'fuse-e-commerce-order', | ||||||
|  |     templateUrl  : './order.component.html', | ||||||
|  |     styleUrls    : ['./order.component.scss'], | ||||||
|  |     encapsulation: ViewEncapsulation.None, | ||||||
|  |     animations   : fuseAnimations | ||||||
|  | }) | ||||||
|  | export class FuseEcommerceOrderComponent implements OnInit, OnDestroy | ||||||
|  | { | ||||||
|  |     order = new Order(); | ||||||
|  |     onOrderChanged: Subscription; | ||||||
|  |     statusForm: FormGroup; | ||||||
|  |     orderStatuses = orderStatuses; | ||||||
|  | 
 | ||||||
|  |     constructor( | ||||||
|  |         private orderService: EcommerceOrderService, | ||||||
|  |         private formBuilder: FormBuilder, | ||||||
|  |         public snackBar: MatSnackBar, | ||||||
|  |         private location: Location | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ngOnInit() | ||||||
|  |     { | ||||||
|  |         // Subscribe to update order on changes
 | ||||||
|  |         this.onOrderChanged = | ||||||
|  |             this.orderService.onOrderChanged | ||||||
|  |                 .subscribe(order => { | ||||||
|  |                     this.order = new Order(order); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |         this.statusForm = this.formBuilder.group({ | ||||||
|  |             newStatus: [''] | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     updateStatus() | ||||||
|  |     { | ||||||
|  |         const newStatusId = Number.parseInt(this.statusForm.get('newStatus').value); | ||||||
|  | 
 | ||||||
|  |         if ( !newStatusId ) | ||||||
|  |         { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         const newStatus = this.orderStatuses.find((status) => { | ||||||
|  |             return status.id === newStatusId; | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         newStatus['date'] = new Date().toString(); | ||||||
|  | 
 | ||||||
|  |         this.order.status.unshift(newStatus); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ngOnDestroy() | ||||||
|  |     { | ||||||
|  |         this.onOrderChanged.unsubscribe(); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										34
									
								
								src/app/main/content/apps/e-commerce/order/order.model.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/app/main/content/apps/e-commerce/order/order.model.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | import { FuseUtils } from '../../../../../core/fuseUtils'; | ||||||
|  | 
 | ||||||
|  | export class Order | ||||||
|  | { | ||||||
|  |     id: string; | ||||||
|  |     reference: string; | ||||||
|  |     subtotal: string; | ||||||
|  |     tax: string; | ||||||
|  |     discount: string; | ||||||
|  |     total: string; | ||||||
|  |     date: string; | ||||||
|  |     customer: any; | ||||||
|  |     products: any[]; | ||||||
|  |     status: any[]; | ||||||
|  |     payment: any; | ||||||
|  |     shippingDetails: any[]; | ||||||
|  | 
 | ||||||
|  |     constructor(order?) | ||||||
|  |     { | ||||||
|  |         order = order || {}; | ||||||
|  |         this.id = order.id || FuseUtils.generateGUID(); | ||||||
|  |         this.reference = order.reference || FuseUtils.generateGUID(); | ||||||
|  |         this.subtotal = order.subtotal || 0; | ||||||
|  |         this.tax = order.tax || 0; | ||||||
|  |         this.discount = order.discount || 0; | ||||||
|  |         this.total = order.total || 0; | ||||||
|  |         this.date = order.date || ''; | ||||||
|  |         this.customer = order.customer || {}; | ||||||
|  |         this.products = order.products || []; | ||||||
|  |         this.status = order.status || []; | ||||||
|  |         this.payment = order.payment || {}; | ||||||
|  |         this.shippingDetails = order.shippingDetails || []; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										75
									
								
								src/app/main/content/apps/e-commerce/order/order.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src/app/main/content/apps/e-commerce/order/order.service.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | |||||||
|  | import { Injectable } from '@angular/core'; | ||||||
|  | import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; | ||||||
|  | import { Observable } from 'rxjs/Observable'; | ||||||
|  | import { HttpClient } from '@angular/common/http'; | ||||||
|  | import { BehaviorSubject } from 'rxjs/BehaviorSubject'; | ||||||
|  | 
 | ||||||
|  | @Injectable() | ||||||
|  | export class EcommerceOrderService implements Resolve<any> | ||||||
|  | { | ||||||
|  |     routeParams: any; | ||||||
|  |     order: any; | ||||||
|  |     onOrderChanged: BehaviorSubject<any> = new BehaviorSubject({}); | ||||||
|  | 
 | ||||||
|  |     constructor( | ||||||
|  |         private http: HttpClient | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Resolve | ||||||
|  |      * @param {ActivatedRouteSnapshot} route | ||||||
|  |      * @param {RouterStateSnapshot} state | ||||||
|  |      * @returns {Observable<any> | Promise<any> | any} | ||||||
|  |      */ | ||||||
|  |     resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         this.routeParams = route.params; | ||||||
|  | 
 | ||||||
|  |         return new Promise((resolve, reject) => { | ||||||
|  | 
 | ||||||
|  |             Promise.all([ | ||||||
|  |                 this.getOrder() | ||||||
|  |             ]).then( | ||||||
|  |                 () => { | ||||||
|  |                     resolve(); | ||||||
|  |                 }, | ||||||
|  |                 reject | ||||||
|  |             ); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     getOrder(): Promise<any> | ||||||
|  |     { | ||||||
|  |         return new Promise((resolve, reject) => { | ||||||
|  |             this.http.get('api/e-commerce-orders/' + this.routeParams.id) | ||||||
|  |                 .subscribe((response: any) => { | ||||||
|  |                     this.order = response; | ||||||
|  |                     this.onOrderChanged.next(this.order); | ||||||
|  |                     resolve(response); | ||||||
|  |                 }, reject); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     saveOrder(order) | ||||||
|  |     { | ||||||
|  |         return new Promise((resolve, reject) => { | ||||||
|  |             this.http.post('api/e-commerce-orders/' + order.id, order) | ||||||
|  |                 .subscribe((response: any) => { | ||||||
|  |                     resolve(response); | ||||||
|  |                 }, reject); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     addOrder(order) | ||||||
|  |     { | ||||||
|  |         return new Promise((resolve, reject) => { | ||||||
|  |             this.http.post('api/e-commerce-orders/', order) | ||||||
|  |                 .subscribe((response: any) => { | ||||||
|  |                     resolve(response); | ||||||
|  |                 }, reject); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,133 @@ | |||||||
|  | <div id="orders" class="page-layout carded fullwidth" fusePerfectScrollbar> | ||||||
|  | 
 | ||||||
|  |     <!-- TOP BACKGROUND --> | ||||||
|  |     <div class="top-bg mat-accent-bg"></div> | ||||||
|  |     <!-- / TOP BACKGROUND --> | ||||||
|  | 
 | ||||||
|  |     <!-- CENTER --> | ||||||
|  |     <div class="center"> | ||||||
|  | 
 | ||||||
|  |         <!-- HEADER --> | ||||||
|  |         <div class="header white-fg" | ||||||
|  |              fxLayout="column" fxLayoutAlign="center center" | ||||||
|  |              fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="space-between center"> | ||||||
|  | 
 | ||||||
|  |             <!-- APP TITLE --> | ||||||
|  |             <div class="logo" | ||||||
|  |                  fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  |                 <mat-icon class="logo-icon mr-16" *fuseIfOnDom [@animate]="{value:'*',params:{delay:'50ms',scale:'0.2'}}">shopping_basket</mat-icon> | ||||||
|  |                 <span class="logo-text h1" *fuseIfOnDom [@animate]="{value:'*',params:{delay:'100ms',x:'-25px'}}">Orders</span> | ||||||
|  |             </div> | ||||||
|  |             <!-- / APP TITLE --> | ||||||
|  | 
 | ||||||
|  |             <!-- SEARCH --> | ||||||
|  |             <div class="search-input-wrapper ml-8 m-sm-0" | ||||||
|  |                  fxFlex="1 0 auto" fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  |                 <label for="search" class="mr-8"> | ||||||
|  |                     <mat-icon class="secondary-text">search</mat-icon> | ||||||
|  |                 </label> | ||||||
|  |                 <mat-form-field floatPlaceholder="never" fxFlex="1 0 auto"> | ||||||
|  |                     <input id="search" matInput #filter placeholder="Search"> | ||||||
|  |                 </mat-form-field> | ||||||
|  |             </div> | ||||||
|  |             <!-- / SEARCH --> | ||||||
|  |         </div> | ||||||
|  |         <!-- / HEADER --> | ||||||
|  | 
 | ||||||
|  |         <!-- CONTENT CARD --> | ||||||
|  |         <div class="content-card mat-white-bg"> | ||||||
|  | 
 | ||||||
|  |             <mat-table class="orders-table" | ||||||
|  |                        #table [dataSource]="dataSource" | ||||||
|  |                        matSort | ||||||
|  |                        [@animateStagger]="{value:'50'}" | ||||||
|  |                        fusePerfectScrollbar> | ||||||
|  | 
 | ||||||
|  |                 <!-- ID Column --> | ||||||
|  |                 <ng-container cdkColumnDef="id"> | ||||||
|  |                     <mat-header-cell *cdkHeaderCellDef mat-sort-header>ID</mat-header-cell> | ||||||
|  |                     <mat-cell *cdkCellDef="let order"> | ||||||
|  |                         <p class="text-truncate">{{order.id}}</p> | ||||||
|  |                     </mat-cell> | ||||||
|  |                 </ng-container> | ||||||
|  | 
 | ||||||
|  |                 <!-- Reference Column --> | ||||||
|  |                 <ng-container cdkColumnDef="reference"> | ||||||
|  |                     <mat-header-cell *cdkHeaderCellDef mat-sort-header fxHide fxShow.gt-sm>Reference</mat-header-cell> | ||||||
|  |                     <mat-cell *cdkCellDef="let order" fxHide fxShow.gt-sm> | ||||||
|  |                         <p class="text-truncate">{{order.reference}}</p> | ||||||
|  |                     </mat-cell> | ||||||
|  |                 </ng-container> | ||||||
|  | 
 | ||||||
|  |                 <!-- Name Column --> | ||||||
|  |                 <ng-container cdkColumnDef="customer"> | ||||||
|  |                     <mat-header-cell *cdkHeaderCellDef mat-sort-header>Customer</mat-header-cell> | ||||||
|  |                     <mat-cell *cdkCellDef="let order"> | ||||||
|  |                         <p class="text-truncate"> | ||||||
|  |                             {{order.customer.firstName}} | ||||||
|  |                             {{order.customer.lastName}} | ||||||
|  |                         </p> | ||||||
|  |                     </mat-cell> | ||||||
|  |                 </ng-container> | ||||||
|  | 
 | ||||||
|  |                 <!-- Total Price Column --> | ||||||
|  |                 <ng-container cdkColumnDef="total"> | ||||||
|  |                     <mat-header-cell *cdkHeaderCellDef mat-sort-header fxHide fxShow.gt-md>Total</mat-header-cell> | ||||||
|  |                     <mat-cell *cdkCellDef="let order" fxHide fxShow.gt-md> | ||||||
|  |                         <p class="total-price text-truncate"> | ||||||
|  |                             {{order.total | currency:'USD':true}} | ||||||
|  |                         </p> | ||||||
|  |                     </mat-cell> | ||||||
|  |                 </ng-container> | ||||||
|  | 
 | ||||||
|  |                 <!-- Payment Column --> | ||||||
|  |                 <ng-container cdkColumnDef="payment"> | ||||||
|  |                     <mat-header-cell *cdkHeaderCellDef mat-sort-header fxHide fxShow.gt-sm>Payment</mat-header-cell> | ||||||
|  |                     <mat-cell *cdkCellDef="let order" fxHide fxShow.gt-sm> | ||||||
|  |                         <p class="text-truncate"> | ||||||
|  |                             {{order.payment.method}} | ||||||
|  |                         </p> | ||||||
|  |                     </mat-cell> | ||||||
|  |                 </ng-container> | ||||||
|  | 
 | ||||||
|  |                 <!-- Status Column --> | ||||||
|  |                 <ng-container cdkColumnDef="status"> | ||||||
|  |                     <mat-header-cell *cdkHeaderCellDef mat-sort-header >Status</mat-header-cell> | ||||||
|  |                     <mat-cell *cdkCellDef="let order"> | ||||||
|  |                         <p class="status text-truncate h6 p-4" [ngClass]="order.status[0].color"> | ||||||
|  |                             {{order.status[0].name}} | ||||||
|  |                         </p> | ||||||
|  |                     </mat-cell> | ||||||
|  |                 </ng-container> | ||||||
|  | 
 | ||||||
|  |                 <!-- Date Column --> | ||||||
|  |                 <ng-container cdkColumnDef="date"> | ||||||
|  |                     <mat-header-cell *cdkHeaderCellDef mat-sort-header fxHide fxShow.gt-sm>Date</mat-header-cell> | ||||||
|  |                     <mat-cell *cdkCellDef="let order" fxHide fxShow.gt-sm> | ||||||
|  |                         <p class="text-truncate"> | ||||||
|  |                             {{order.date}} | ||||||
|  |                         </p> | ||||||
|  |                     </mat-cell> | ||||||
|  |                 </ng-container> | ||||||
|  | 
 | ||||||
|  |                 <mat-header-row *cdkHeaderRowDef="displayedColumns"></mat-header-row> | ||||||
|  | 
 | ||||||
|  |                 <mat-row *cdkRowDef="let order; columns: displayedColumns;" | ||||||
|  |                          class="order" | ||||||
|  |                          matRipple | ||||||
|  |                          [routerLink]="'/apps/e-commerce/orders/'+order.id"> | ||||||
|  |                 </mat-row> | ||||||
|  |             </mat-table> | ||||||
|  | 
 | ||||||
|  |             <mat-paginator #paginator | ||||||
|  |                            [length]="dataSource.filteredData.length" | ||||||
|  |                            [pageIndex]="0" | ||||||
|  |                            [pageSize]="10" | ||||||
|  |                            [pageSizeOptions]="[5, 10, 25, 100]"> | ||||||
|  |             </mat-paginator> | ||||||
|  | 
 | ||||||
|  |         </div> | ||||||
|  |         <!-- / CONTENT CARD --> | ||||||
|  |     </div> | ||||||
|  |     <!-- / CENTER --> | ||||||
|  | </div> | ||||||
| @ -0,0 +1,73 @@ | |||||||
|  | :host { | ||||||
|  | 
 | ||||||
|  |     .header { | ||||||
|  | 
 | ||||||
|  |         .search-input-wrapper { | ||||||
|  |             max-width: 480px; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     .mat-tab-group, | ||||||
|  |     .mat-tab-body-wrapper, | ||||||
|  |     .tab-content{ | ||||||
|  |         flex: 1 1 auto; | ||||||
|  |         max-width: 100%; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     .orders-table { | ||||||
|  |         flex: 1 1 auto; | ||||||
|  |         border-bottom: 1px solid rgba(0, 0, 0, .12); | ||||||
|  | 
 | ||||||
|  |         .mat-header-row { | ||||||
|  |             min-height: 64px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .order { | ||||||
|  |             position: relative; | ||||||
|  |             cursor: pointer; | ||||||
|  |             height: 84px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .mat-cell { | ||||||
|  |             min-width: 0; | ||||||
|  |             display: flex; | ||||||
|  |             align-items: center; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .mat-column-id { | ||||||
|  |             flex: 0 1 84px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .mat-column-image { | ||||||
|  |             flex: 0 1 84px; | ||||||
|  | 
 | ||||||
|  |             .product-image { | ||||||
|  |                 width: 52px; | ||||||
|  |                 height: 52px; | ||||||
|  |                 border: 1px solid rgba(0, 0, 0, .12); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .mat-column-buttons { | ||||||
|  |             flex: 0 1 80px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .quantity-indicator { | ||||||
|  |             display: inline-block; | ||||||
|  |             vertical-align: middle; | ||||||
|  |             width: 8px; | ||||||
|  |             height: 8px; | ||||||
|  |             border-radius: 4px; | ||||||
|  |             margin-right: 8px; | ||||||
|  | 
 | ||||||
|  |             & + span { | ||||||
|  |                 display: inline-block; | ||||||
|  |                 vertical-align: middle; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .active-icon { | ||||||
|  |             border-radius: 50%; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										169
									
								
								src/app/main/content/apps/e-commerce/orders/orders.component.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								src/app/main/content/apps/e-commerce/orders/orders.component.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,169 @@ | |||||||
|  | import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; | ||||||
|  | import { EcommerceOrdersService } from './orders.service'; | ||||||
|  | import { DataSource } from '@angular/cdk/collections'; | ||||||
|  | import { Observable } from 'rxjs/Observable'; | ||||||
|  | import { fuseAnimations } from '../../../../../core/animations'; | ||||||
|  | import { MatPaginator, MatSort } from '@angular/material'; | ||||||
|  | import { BehaviorSubject } from 'rxjs/BehaviorSubject'; | ||||||
|  | import 'rxjs/add/operator/startWith'; | ||||||
|  | import 'rxjs/add/observable/merge'; | ||||||
|  | import 'rxjs/add/operator/map'; | ||||||
|  | import 'rxjs/add/operator/debounceTime'; | ||||||
|  | import 'rxjs/add/operator/distinctUntilChanged'; | ||||||
|  | import 'rxjs/add/observable/fromEvent'; | ||||||
|  | import { FuseUtils } from '../../../../../core/fuseUtils'; | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |     selector   : 'fuse-e-commerce-orders', | ||||||
|  |     templateUrl: './orders.component.html', | ||||||
|  |     styleUrls  : ['./orders.component.scss'], | ||||||
|  |     animations : fuseAnimations | ||||||
|  | }) | ||||||
|  | export class FuseEcommerceOrdersComponent implements OnInit | ||||||
|  | { | ||||||
|  |     dataSource: FilesDataSource | null; | ||||||
|  |     displayedColumns = ['id', 'reference', 'customer', 'total', 'payment', 'status', 'date']; | ||||||
|  | 
 | ||||||
|  |     @ViewChild(MatPaginator) paginator: MatPaginator; | ||||||
|  |     @ViewChild('filter') filter: ElementRef; | ||||||
|  |     @ViewChild(MatSort) sort: MatSort; | ||||||
|  | 
 | ||||||
|  |     constructor( | ||||||
|  |         private ordersService: EcommerceOrdersService | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ngOnInit() | ||||||
|  |     { | ||||||
|  |         this.dataSource = new FilesDataSource(this.ordersService, this.paginator, this.sort); | ||||||
|  | 
 | ||||||
|  |         Observable.fromEvent(this.filter.nativeElement, 'keyup') | ||||||
|  |                   .debounceTime(150) | ||||||
|  |                   .distinctUntilChanged() | ||||||
|  |                   .subscribe(() => { | ||||||
|  |                       if ( !this.dataSource ) | ||||||
|  |                       { | ||||||
|  |                           return; | ||||||
|  |                       } | ||||||
|  |                       this.dataSource.filter = this.filter.nativeElement.value; | ||||||
|  |                   }); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export class FilesDataSource extends DataSource<any> | ||||||
|  | { | ||||||
|  |     _filterChange = new BehaviorSubject(''); | ||||||
|  |     _filteredDataChange = new BehaviorSubject(''); | ||||||
|  | 
 | ||||||
|  |     get filteredData(): any | ||||||
|  |     { | ||||||
|  |         return this._filteredDataChange.value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     set filteredData(value: any) | ||||||
|  |     { | ||||||
|  |         this._filteredDataChange.next(value); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     get filter(): string | ||||||
|  |     { | ||||||
|  |         return this._filterChange.value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     set filter(filter: string) | ||||||
|  |     { | ||||||
|  |         this._filterChange.next(filter); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     constructor( | ||||||
|  |         private ordersService: EcommerceOrdersService, | ||||||
|  |         private _paginator: MatPaginator, | ||||||
|  |         private _sort: MatSort | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |         super(); | ||||||
|  |         this.filteredData = this.ordersService.orders; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** Connect function called by the table to retrieve one stream containing the data to render. */ | ||||||
|  |     connect(): Observable<any[]> | ||||||
|  |     { | ||||||
|  |         const displayDataChanges = [ | ||||||
|  |             this.ordersService.onOrdersChanged, | ||||||
|  |             this._paginator.page, | ||||||
|  |             this._filterChange, | ||||||
|  |             this._sort.sortChange | ||||||
|  |         ]; | ||||||
|  |         return Observable.merge(...displayDataChanges).map(() => { | ||||||
|  |             let data = this.ordersService.orders.slice(); | ||||||
|  | 
 | ||||||
|  |             data = this.filterData(data); | ||||||
|  | 
 | ||||||
|  |             this.filteredData = [...data]; | ||||||
|  | 
 | ||||||
|  |             data = this.sortData(data); | ||||||
|  | 
 | ||||||
|  |             // Grab the page's slice of data.
 | ||||||
|  |             const startIndex = this._paginator.pageIndex * this._paginator.pageSize; | ||||||
|  |             return data.splice(startIndex, this._paginator.pageSize); | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     filterData(data) | ||||||
|  |     { | ||||||
|  |         if ( !this.filter ) | ||||||
|  |         { | ||||||
|  |             return data; | ||||||
|  |         } | ||||||
|  |         return FuseUtils.filterArrayByString(data, this.filter); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     sortData(data): any[] | ||||||
|  |     { | ||||||
|  |         if ( !this._sort.active || this._sort.direction === '' ) | ||||||
|  |         { | ||||||
|  |             return data; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return data.sort((a, b) => { | ||||||
|  |             let propertyA: number | string = ''; | ||||||
|  |             let propertyB: number | string = ''; | ||||||
|  | 
 | ||||||
|  |             switch ( this._sort.active ) | ||||||
|  |             { | ||||||
|  |                 case 'id': | ||||||
|  |                     [propertyA, propertyB] = [a.id, b.id]; | ||||||
|  |                     break; | ||||||
|  |                 case 'reference': | ||||||
|  |                     [propertyA, propertyB] = [a.reference, b.reference]; | ||||||
|  |                     break; | ||||||
|  |                 case 'customer': | ||||||
|  |                     [propertyA, propertyB] = [a.customer.firstName, b.customer.firstName]; | ||||||
|  |                     break; | ||||||
|  |                 case 'total': | ||||||
|  |                     [propertyA, propertyB] = [a.total, b.total]; | ||||||
|  |                     break; | ||||||
|  |                 case 'payment': | ||||||
|  |                     [propertyA, propertyB] = [a.payment.method, b.payment.method]; | ||||||
|  |                     break; | ||||||
|  |                 case 'status': | ||||||
|  |                     [propertyA, propertyB] = [a.status[0].name, b.status[0].name]; | ||||||
|  |                     break; | ||||||
|  |                 case 'date': | ||||||
|  |                     [propertyA, propertyB] = [a.date, b.date]; | ||||||
|  |                     break; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             const valueA = isNaN(+propertyA) ? propertyA : +propertyA; | ||||||
|  |             const valueB = isNaN(+propertyB) ? propertyB : +propertyB; | ||||||
|  | 
 | ||||||
|  |             return (valueA < valueB ? -1 : 1) * (this._sort.direction === 'asc' ? 1 : -1); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     disconnect() | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,52 @@ | |||||||
|  | import { Injectable } from '@angular/core'; | ||||||
|  | import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; | ||||||
|  | import { Observable } from 'rxjs/Observable'; | ||||||
|  | import { HttpClient } from '@angular/common/http'; | ||||||
|  | import { BehaviorSubject } from 'rxjs/BehaviorSubject'; | ||||||
|  | 
 | ||||||
|  | @Injectable() | ||||||
|  | export class EcommerceOrdersService implements Resolve<any> | ||||||
|  | { | ||||||
|  |     orders: any[]; | ||||||
|  |     onOrdersChanged: BehaviorSubject<any> = new BehaviorSubject({}); | ||||||
|  | 
 | ||||||
|  |     constructor( | ||||||
|  |         private http: HttpClient | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Resolve | ||||||
|  |      * @param {ActivatedRouteSnapshot} route | ||||||
|  |      * @param {RouterStateSnapshot} state | ||||||
|  |      * @returns {Observable<any> | Promise<any> | any} | ||||||
|  |      */ | ||||||
|  |     resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         return new Promise((resolve, reject) => { | ||||||
|  | 
 | ||||||
|  |             Promise.all([ | ||||||
|  |                 this.getOrders() | ||||||
|  |             ]).then( | ||||||
|  |                 () => { | ||||||
|  |                     resolve(); | ||||||
|  |                 }, | ||||||
|  |                 reject | ||||||
|  |             ); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     getOrders(): Promise<any> | ||||||
|  |     { | ||||||
|  |         return new Promise((resolve, reject) => { | ||||||
|  |             this.http.get('api/e-commerce-orders') | ||||||
|  |                 .subscribe((response: any) => { | ||||||
|  |                     this.orders = response; | ||||||
|  |                     this.onOrdersChanged.next(this.orders); | ||||||
|  |                     resolve(response); | ||||||
|  |                 }, reject); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,255 @@ | |||||||
|  | <div id="product" class="page-layout carded fullwidth" fusePerfectScrollbar> | ||||||
|  | 
 | ||||||
|  |     <!-- TOP BACKGROUND --> | ||||||
|  |     <div class="top-bg mat-accent-bg"></div> | ||||||
|  |     <!-- / TOP BACKGROUND --> | ||||||
|  | 
 | ||||||
|  |     <!-- CENTER --> | ||||||
|  |     <div class="center"> | ||||||
|  | 
 | ||||||
|  |         <!-- HEADER --> | ||||||
|  |         <div class="header white-fg" fxLayout="row" fxLayoutAlign="space-between center"> | ||||||
|  | 
 | ||||||
|  |             <!-- APP TITLE --> | ||||||
|  |             <div fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  | 
 | ||||||
|  |                 <button class="mr-0 mr-sm-16" mat-icon-button [routerLink]="'/apps/e-commerce/products'"> | ||||||
|  |                     <mat-icon>arrow_back</mat-icon> | ||||||
|  |                 </button> | ||||||
|  | 
 | ||||||
|  |                 <div class="product-image mr-8 mr-sm-16" *fuseIfOnDom [@animate]="{value:'*',params:{delay:'50ms',scale:'0.2'}}"> | ||||||
|  |                     <img *ngIf="product.images[0]" [src]="product.images[0].url"> | ||||||
|  |                     <img *ngIf="!product.images[0]" [src]="'assets/images/ecommerce/product-image-placeholder.png'"> | ||||||
|  |                 </div> | ||||||
|  | 
 | ||||||
|  |                 <div fxLayout="column" fxLayoutAlign="start start" | ||||||
|  |                      *fuseIfOnDom [@animate]="{value:'*',params:{delay:'100ms',x:'-25px'}}"> | ||||||
|  |                     <div class="h2" *ngIf="pageType ==='edit'"> | ||||||
|  |                         {{product.name}} | ||||||
|  |                     </div> | ||||||
|  |                     <div class="h2" *ngIf="pageType ==='new'"> | ||||||
|  |                         New Product | ||||||
|  |                     </div> | ||||||
|  |                     <div class="subtitle secondary-text"> | ||||||
|  |                         <span>Product Detail</span> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  |             <!-- / APP TITLE --> | ||||||
|  | 
 | ||||||
|  |             <button mat-raised-button | ||||||
|  |                     class="save-product-button mat-white-bg mt-16 mt-sm-0" | ||||||
|  |                     [disabled]="productForm.invalid" | ||||||
|  |                     *ngIf="pageType ==='new'" (click)="addProduct()"> | ||||||
|  |                 <span>ADD</span> | ||||||
|  |             </button> | ||||||
|  | 
 | ||||||
|  |             <button mat-raised-button | ||||||
|  |                     class="save-product-button mat-white-bg mt-16 mt-sm-0" | ||||||
|  |                     [disabled]="productForm.invalid || productForm.pristine" | ||||||
|  |                     *ngIf="pageType ==='edit'" (click)="saveProduct()"> | ||||||
|  |                 <span>SAVE</span> | ||||||
|  |             </button> | ||||||
|  |         </div> | ||||||
|  |         <!-- / HEADER --> | ||||||
|  | 
 | ||||||
|  |         <!-- CONTENT CARD --> | ||||||
|  |         <div class="content-card mat-white-bg"> | ||||||
|  | 
 | ||||||
|  |             <!-- CONTENT --> | ||||||
|  |             <div class="content"> | ||||||
|  | 
 | ||||||
|  |                 <form name="productForm" [formGroup]="productForm" class="product w-100-p" fxLayout="column" fxFlex> | ||||||
|  | 
 | ||||||
|  |                     <mat-tab-group> | ||||||
|  | 
 | ||||||
|  |                         <mat-tab label="Basic Info"> | ||||||
|  |                             <div class="tab-content p-24" fusePerfectScrollbar> | ||||||
|  | 
 | ||||||
|  |                                 <mat-form-field class="w-100-p"> | ||||||
|  |                                     <input matInput | ||||||
|  |                                            name="name" | ||||||
|  |                                            formControlName="name" | ||||||
|  |                                            placeholder="Product Name" | ||||||
|  |                                            required> | ||||||
|  |                                 </mat-form-field> | ||||||
|  | 
 | ||||||
|  |                                 <mat-form-field class="w-100-p"> | ||||||
|  |                                     <textarea matInput | ||||||
|  |                                               name="description" | ||||||
|  |                                               formControlName="description" | ||||||
|  |                                               placeholder="Product Description" | ||||||
|  |                                               rows="10"> | ||||||
|  |                                     </textarea> | ||||||
|  |                                 </mat-form-field> | ||||||
|  | 
 | ||||||
|  |                                 <h3 class="mb-0">Categories</h3> | ||||||
|  |                                 <mat-form-field class="w-100-p" floatPlaceholder="never"> | ||||||
|  |                                     <mat-chip-list matPrefix #categoryList | ||||||
|  |                                                    name="categories" | ||||||
|  |                                                    formControlName="categories"> | ||||||
|  | 
 | ||||||
|  |                                         <mat-chip *ngFor="let category of product.categories" | ||||||
|  |                                                   removable="true" (remove)="product.removeCategory(category)"> | ||||||
|  |                                             {{category}} | ||||||
|  |                                             <mat-icon matChipRemove>cancel</mat-icon> | ||||||
|  |                                         </mat-chip> | ||||||
|  |                                     </mat-chip-list> | ||||||
|  |                                     <input matInput | ||||||
|  |                                            matChipInputAddOnBlur="true" | ||||||
|  |                                            (matChipInputTokenEnd)="product.addCategory($event)" | ||||||
|  |                                            placeholder="Add category..." | ||||||
|  |                                            [matChipInputFor]="categoryList"/> | ||||||
|  |                                 </mat-form-field> | ||||||
|  | 
 | ||||||
|  |                                 <h3 class="mb-0">Tags</h3> | ||||||
|  |                                 <mat-form-field class="w-100-p" floatPlaceholder="never"> | ||||||
|  |                                     <mat-chip-list matPrefix #tagList | ||||||
|  |                                                    name="tags" | ||||||
|  |                                                    formControlName="tags"> | ||||||
|  | 
 | ||||||
|  |                                         <mat-chip *ngFor="let tag of product.tags" | ||||||
|  |                                                   removable="true" (remove)="product.removeTag(tag)"> | ||||||
|  |                                             {{tag}} | ||||||
|  |                                             <mat-icon matChipRemove>cancel</mat-icon> | ||||||
|  |                                         </mat-chip> | ||||||
|  |                                     </mat-chip-list> | ||||||
|  |                                     <input matInput | ||||||
|  |                                            matChipInputAddOnBlur="true" | ||||||
|  |                                            (matChipInputTokenEnd)="product.addTag($event)" | ||||||
|  |                                            placeholder="Add tag..." | ||||||
|  |                                            [matChipInputFor]="tagList"/> | ||||||
|  |                                 </mat-form-field> | ||||||
|  |                             </div> | ||||||
|  |                         </mat-tab> | ||||||
|  | 
 | ||||||
|  |                         <mat-tab label="Product Images"> | ||||||
|  |                             <div class="tab-content p-24" fusePerfectScrollbar> | ||||||
|  |                                 <div fxLayout="row" fxLayoutAlign="start start" fxLayoutWrap> | ||||||
|  | 
 | ||||||
|  |                                     <div *ngIf="product.images.length === 0" | ||||||
|  |                                          class="product-image" fxlayout="row" fxLayoutAlign="center center"> | ||||||
|  |                                         <img class="media" [src]="'assets/images/ecommerce/product-image-placeholder.png'"> | ||||||
|  |                                     </div> | ||||||
|  | 
 | ||||||
|  |                                     <div *ngFor="let image of product.images"> | ||||||
|  |                                         <div *ngIf="product.images.length > 0" | ||||||
|  |                                              class="product-image" fxlayout="row" fxLayoutAlign="center center"> | ||||||
|  |                                             <img class="media" [src]="image.url"> | ||||||
|  |                                         </div> | ||||||
|  |                                     </div> | ||||||
|  |                                 </div> | ||||||
|  |                             </div> | ||||||
|  |                         </mat-tab> | ||||||
|  | 
 | ||||||
|  |                         <mat-tab label="Pricing"> | ||||||
|  |                             <div class="tab-content p-24" fusePerfectScrollbar> | ||||||
|  | 
 | ||||||
|  |                                 <mat-form-field class="w-100-p"> | ||||||
|  |                                     <input matInput | ||||||
|  |                                            name="priceTaxExcl" | ||||||
|  |                                            formControlName="priceTaxExcl" | ||||||
|  |                                            placeholder="Tax Excluded Price" type="number"> | ||||||
|  |                                     <span matPrefix>$ </span> | ||||||
|  |                                 </mat-form-field> | ||||||
|  | 
 | ||||||
|  |                                 <mat-form-field class="w-100-p"> | ||||||
|  |                                     <input matInput | ||||||
|  |                                            name="priceTaxIncl" | ||||||
|  |                                            formControlName="priceTaxIncl" | ||||||
|  |                                            placeholder="Tax Included Price" type="number"> | ||||||
|  |                                     <span matPrefix>$ </span> | ||||||
|  |                                 </mat-form-field> | ||||||
|  | 
 | ||||||
|  |                                 <mat-form-field class="w-100-p"> | ||||||
|  |                                     <input matInput | ||||||
|  |                                            name="taxRate" | ||||||
|  |                                            formControlName="taxRate" | ||||||
|  |                                            placeholder="Tax Rate" type="number"> | ||||||
|  |                                     <span matPrefix>%</span> | ||||||
|  |                                 </mat-form-field> | ||||||
|  | 
 | ||||||
|  |                                 <mat-form-field class="w-100-p"> | ||||||
|  |                                     <input matInput | ||||||
|  |                                            name="comparedPrice" | ||||||
|  |                                            formControlName="comparedPrice" | ||||||
|  |                                            placeholder="Compared Price" type="number"> | ||||||
|  |                                     <span matPrefix>$ </span> | ||||||
|  |                                     <mat-hint align="start">Add a compare price to show next to the real price</mat-hint> | ||||||
|  |                                 </mat-form-field> | ||||||
|  | 
 | ||||||
|  |                             </div> | ||||||
|  |                         </mat-tab> | ||||||
|  | 
 | ||||||
|  |                         <mat-tab label="Inventory"> | ||||||
|  |                             <div class="tab-content p-24" fusePerfectScrollbar> | ||||||
|  | 
 | ||||||
|  |                                 <mat-form-field class="w-100-p"> | ||||||
|  |                                     <input matInput | ||||||
|  |                                            name="sku" | ||||||
|  |                                            formControlName="sku" | ||||||
|  |                                            placeholder="SKU"> | ||||||
|  |                                 </mat-form-field> | ||||||
|  | 
 | ||||||
|  |                                 <mat-form-field class="w-100-p"> | ||||||
|  |                                     <input matInput | ||||||
|  |                                            name="quantity" | ||||||
|  |                                            formControlName="quantity" | ||||||
|  |                                            placeholder="Quantity" type="number"> | ||||||
|  |                                 </mat-form-field> | ||||||
|  |                             </div> | ||||||
|  |                         </mat-tab> | ||||||
|  | 
 | ||||||
|  |                         <mat-tab label="Shipping"> | ||||||
|  |                             <div class="tab-content p-24" fusePerfectScrollbar fxLayout="column"> | ||||||
|  | 
 | ||||||
|  |                                 <div class="py-16" fxFlex="1 0 auto" fxLayout="row"> | ||||||
|  |                                     <mat-form-field fxFlex> | ||||||
|  |                                         <input matInput | ||||||
|  |                                                name="Width" | ||||||
|  |                                                formControlName="width" | ||||||
|  |                                                placeholder="Width"> | ||||||
|  |                                     </mat-form-field> | ||||||
|  |                                     <mat-form-field fxFlex> | ||||||
|  |                                         <input matInput | ||||||
|  |                                                name="Height" | ||||||
|  |                                                formControlName="height" | ||||||
|  |                                                placeholder="Height"> | ||||||
|  |                                     </mat-form-field> | ||||||
|  |                                     <mat-form-field fxFlex> | ||||||
|  |                                         <input matInput | ||||||
|  |                                                name="Depth" | ||||||
|  |                                                formControlName="depth" | ||||||
|  |                                                placeholder="Depth"> | ||||||
|  |                                     </mat-form-field> | ||||||
|  |                                 </div> | ||||||
|  | 
 | ||||||
|  |                                 <mat-form-field class="w-100-p"> | ||||||
|  |                                     <input matInput | ||||||
|  |                                            name="Weight" | ||||||
|  |                                            formControlName="weight" | ||||||
|  |                                            placeholder="Weight"> | ||||||
|  |                                 </mat-form-field> | ||||||
|  | 
 | ||||||
|  |                                 <mat-form-field class="w-100-p"> | ||||||
|  |                                     <input matInput | ||||||
|  |                                            name="extraShippingFee" | ||||||
|  |                                            formControlName="extraShippingFee" | ||||||
|  |                                            placeholder="Extra Shipping Fee" type="number"> | ||||||
|  |                                     <span matPrefix>$ </span> | ||||||
|  |                                 </mat-form-field> | ||||||
|  |                             </div> | ||||||
|  |                         </mat-tab> | ||||||
|  | 
 | ||||||
|  |                     </mat-tab-group> | ||||||
|  |                 </form> | ||||||
|  | 
 | ||||||
|  |             </div> | ||||||
|  |             <!-- / CONTENT --> | ||||||
|  | 
 | ||||||
|  |         </div> | ||||||
|  |         <!-- / CONTENT CARD --> | ||||||
|  | 
 | ||||||
|  |     </div> | ||||||
|  |     <!-- / CENTER --> | ||||||
|  | </div> | ||||||
| @ -0,0 +1,57 @@ | |||||||
|  | #product { | ||||||
|  | 
 | ||||||
|  |     .header { | ||||||
|  | 
 | ||||||
|  |         .product-image { | ||||||
|  |             overflow: hidden; | ||||||
|  |             width: 56px; | ||||||
|  |             height: 56px; | ||||||
|  |             border: 3px solid rgba(0, 0, 0, 0.12); | ||||||
|  | 
 | ||||||
|  |             img { | ||||||
|  |                 height: 100%; | ||||||
|  |                 width: auto; | ||||||
|  |                 max-width: none; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .subtitle { | ||||||
|  |             margin: 6px 0 0 0; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     .content { | ||||||
|  | 
 | ||||||
|  |         .mat-tab-group, | ||||||
|  |         .mat-tab-body-wrapper, | ||||||
|  |         .tab-content{ | ||||||
|  |             flex: 1 1 auto; | ||||||
|  |             max-width: 100%; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .mat-tab-body-content { | ||||||
|  |             display: flex; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .mat-tab-label { | ||||||
|  |             height: 64px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .product-image { | ||||||
|  |             overflow: hidden; | ||||||
|  |             width: 128px; | ||||||
|  |             height: 128px; | ||||||
|  |             margin-right: 16px; | ||||||
|  |             margin-bottom: 16px; | ||||||
|  |             border: 3px solid rgba(0, 0, 0, 0.12); | ||||||
|  | 
 | ||||||
|  |             img { | ||||||
|  |                 height: 100%; | ||||||
|  |                 width: auto; | ||||||
|  |                 max-width: none; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,132 @@ | |||||||
|  | import { Component, ElementRef, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; | ||||||
|  | import { EcommerceProductService } from './product.service'; | ||||||
|  | import { fuseAnimations } from '../../../../../core/animations'; | ||||||
|  | import 'rxjs/add/operator/startWith'; | ||||||
|  | import 'rxjs/add/observable/merge'; | ||||||
|  | import 'rxjs/add/operator/map'; | ||||||
|  | import 'rxjs/add/operator/debounceTime'; | ||||||
|  | import 'rxjs/add/operator/distinctUntilChanged'; | ||||||
|  | import 'rxjs/add/observable/fromEvent'; | ||||||
|  | import { Subscription } from 'rxjs/Subscription'; | ||||||
|  | import { Product } from './product.model'; | ||||||
|  | import { FormBuilder, FormGroup } from '@angular/forms'; | ||||||
|  | import { FuseUtils } from '../../../../../core/fuseUtils'; | ||||||
|  | import { MatSnackBar } from '@angular/material'; | ||||||
|  | import { Location } from '@angular/common'; | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |     selector     : 'fuse-e-commerce-product', | ||||||
|  |     templateUrl  : './product.component.html', | ||||||
|  |     styleUrls    : ['./product.component.scss'], | ||||||
|  |     encapsulation: ViewEncapsulation.None, | ||||||
|  |     animations   : fuseAnimations | ||||||
|  | }) | ||||||
|  | export class FuseEcommerceProductComponent implements OnInit, OnDestroy | ||||||
|  | { | ||||||
|  |     product = new Product(); | ||||||
|  |     onProductChanged: Subscription; | ||||||
|  |     pageType: string; | ||||||
|  |     productForm: FormGroup; | ||||||
|  | 
 | ||||||
|  |     constructor( | ||||||
|  |         private productService: EcommerceProductService, | ||||||
|  |         private formBuilder: FormBuilder, | ||||||
|  |         public snackBar: MatSnackBar, | ||||||
|  |         private location: Location | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ngOnInit() | ||||||
|  |     { | ||||||
|  |         // Subscribe to update product on changes
 | ||||||
|  |         this.onProductChanged = | ||||||
|  |             this.productService.onProductChanged | ||||||
|  |                 .subscribe(product => { | ||||||
|  | 
 | ||||||
|  |                     if ( product ) | ||||||
|  |                     { | ||||||
|  |                         this.product = new Product(product); | ||||||
|  |                         this.pageType = 'edit'; | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         this.pageType = 'new'; | ||||||
|  |                         this.product = new Product(); | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     this.productForm = this.createProductForm(); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     createProductForm() | ||||||
|  |     { | ||||||
|  |         return this.formBuilder.group({ | ||||||
|  |             id              : [this.product.id], | ||||||
|  |             name            : [this.product.name], | ||||||
|  |             handle          : [this.product.handle], | ||||||
|  |             description     : [this.product.description], | ||||||
|  |             categories      : [this.product.categories], | ||||||
|  |             tags            : [this.product.tags], | ||||||
|  |             images          : [this.product.images], | ||||||
|  |             priceTaxExcl    : [this.product.priceTaxExcl], | ||||||
|  |             priceTaxIncl    : [this.product.priceTaxIncl], | ||||||
|  |             taxRate         : [this.product.taxRate], | ||||||
|  |             comparedPrice   : [this.product.comparedPrice], | ||||||
|  |             quantity        : [this.product.quantity], | ||||||
|  |             sku             : [this.product.sku], | ||||||
|  |             width           : [this.product.width], | ||||||
|  |             height          : [this.product.height], | ||||||
|  |             depth           : [this.product.depth], | ||||||
|  |             weight          : [this.product.weight], | ||||||
|  |             extraShippingFee: [this.product.extraShippingFee], | ||||||
|  |             active          : [this.product.active] | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     saveProduct() | ||||||
|  |     { | ||||||
|  |         const data = this.productForm.getRawValue(); | ||||||
|  |         data.handle = FuseUtils.handleize(data.name); | ||||||
|  |         this.productService.saveProduct(data) | ||||||
|  |             .then(() => { | ||||||
|  | 
 | ||||||
|  |                 // Trigger the subscription with new data
 | ||||||
|  |                 this.productService.onProductChanged.next(data); | ||||||
|  | 
 | ||||||
|  |                 // Show the success message
 | ||||||
|  |                 this.snackBar.open('Product saved', 'OK', { | ||||||
|  |                     verticalPosition: 'top', | ||||||
|  |                     duration        : 2000 | ||||||
|  |                 }); | ||||||
|  |             }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     addProduct() | ||||||
|  |     { | ||||||
|  |         const data = this.productForm.getRawValue(); | ||||||
|  |         data.handle = FuseUtils.handleize(data.name); | ||||||
|  |         this.productService.addProduct(data) | ||||||
|  |             .then(() => { | ||||||
|  | 
 | ||||||
|  |                 // Trigger the subscription with new data
 | ||||||
|  |                 this.productService.onProductChanged.next(data); | ||||||
|  | 
 | ||||||
|  |                 // Show the success message
 | ||||||
|  |                 this.snackBar.open('Product added', 'OK', { | ||||||
|  |                     verticalPosition: 'top', | ||||||
|  |                     duration        : 2000 | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |                 // Change the location with new one
 | ||||||
|  |                 this.location.go('apps/e-commerce/products/' + this.product.id + '/' + this.product.handle); | ||||||
|  |             }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ngOnDestroy() | ||||||
|  |     { | ||||||
|  |         this.onProductChanged.unsubscribe(); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										110
									
								
								src/app/main/content/apps/e-commerce/product/product.model.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								src/app/main/content/apps/e-commerce/product/product.model.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,110 @@ | |||||||
|  | import { FuseUtils } from '../../../../../core/fuseUtils'; | ||||||
|  | import { MatChipInputEvent } from '@angular/material'; | ||||||
|  | 
 | ||||||
|  | export class Product | ||||||
|  | { | ||||||
|  |     id: string; | ||||||
|  |     name: string; | ||||||
|  |     handle: string; | ||||||
|  |     description: string; | ||||||
|  |     categories: string[]; | ||||||
|  |     tags: string[]; | ||||||
|  |     images: { | ||||||
|  |         default: boolean, | ||||||
|  |         id: string, | ||||||
|  |         url: string, | ||||||
|  |         type: string | ||||||
|  |     }[]; | ||||||
|  |     priceTaxExcl: number; | ||||||
|  |     priceTaxIncl: number; | ||||||
|  |     taxRate: number; | ||||||
|  |     comparedPrice: number; | ||||||
|  |     quantity: number; | ||||||
|  |     sku: string; | ||||||
|  |     width: string; | ||||||
|  |     height: string; | ||||||
|  |     depth: string; | ||||||
|  |     weight: string; | ||||||
|  |     extraShippingFee: number; | ||||||
|  |     active: boolean; | ||||||
|  | 
 | ||||||
|  |     constructor(product?) | ||||||
|  |     { | ||||||
|  |         product = product || {}; | ||||||
|  |         this.id = product.id || FuseUtils.generateGUID(); | ||||||
|  |         this.name = product.name || ''; | ||||||
|  |         this.handle = product.handle || FuseUtils.handleize(this.name); | ||||||
|  |         this.description = product.description || ''; | ||||||
|  |         this.categories = product.categories || []; | ||||||
|  |         this.tags = product.tags || []; | ||||||
|  |         this.images = product.images || []; | ||||||
|  |         this.priceTaxExcl = product.priceTaxExcl || 0; | ||||||
|  |         this.priceTaxIncl = product.priceTaxIncl || 0; | ||||||
|  |         this.taxRate = product.taxRate || 0; | ||||||
|  |         this.comparedPrice = product.comparedPrice || 0; | ||||||
|  |         this.quantity = product.quantity || 0; | ||||||
|  |         this.sku = product.sku || 0; | ||||||
|  |         this.width = product.width || 0; | ||||||
|  |         this.height = product.height || 0; | ||||||
|  |         this.depth = product.depth || 0; | ||||||
|  |         this.weight = product.weight || 0; | ||||||
|  |         this.extraShippingFee = product.extraShippingFee || 0; | ||||||
|  |         this.active = product.active || true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     addCategory(event: MatChipInputEvent): void | ||||||
|  |     { | ||||||
|  |         const input = event.input; | ||||||
|  |         const value = event.value; | ||||||
|  | 
 | ||||||
|  |         // Add category
 | ||||||
|  |         if ( value ) | ||||||
|  |         { | ||||||
|  |             this.categories.push(value); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Reset the input value
 | ||||||
|  |         if ( input ) | ||||||
|  |         { | ||||||
|  |             input.value = ''; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     removeCategory(category) | ||||||
|  |     { | ||||||
|  |         const index = this.categories.indexOf(category); | ||||||
|  | 
 | ||||||
|  |         if ( index >= 0 ) | ||||||
|  |         { | ||||||
|  |             this.categories.splice(index, 1); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     addTag(event: MatChipInputEvent): void | ||||||
|  |     { | ||||||
|  |         const input = event.input; | ||||||
|  |         const value = event.value; | ||||||
|  | 
 | ||||||
|  |         // Add tag
 | ||||||
|  |         if ( value ) | ||||||
|  |         { | ||||||
|  |             this.tags.push(value); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Reset the input value
 | ||||||
|  |         if ( input ) | ||||||
|  |         { | ||||||
|  |             input.value = ''; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     removeTag(tag) | ||||||
|  |     { | ||||||
|  |         const index = this.tags.indexOf(tag); | ||||||
|  | 
 | ||||||
|  |         if ( index >= 0 ) | ||||||
|  |         { | ||||||
|  |             this.tags.splice(index, 1); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,83 @@ | |||||||
|  | import { Injectable } from '@angular/core'; | ||||||
|  | import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; | ||||||
|  | import { Observable } from 'rxjs/Observable'; | ||||||
|  | import { HttpClient } from '@angular/common/http'; | ||||||
|  | import { BehaviorSubject } from 'rxjs/BehaviorSubject'; | ||||||
|  | 
 | ||||||
|  | @Injectable() | ||||||
|  | export class EcommerceProductService implements Resolve<any> | ||||||
|  | { | ||||||
|  |     routeParams: any; | ||||||
|  |     product: any; | ||||||
|  |     onProductChanged: BehaviorSubject<any> = new BehaviorSubject({}); | ||||||
|  | 
 | ||||||
|  |     constructor( | ||||||
|  |         private http: HttpClient | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Resolve | ||||||
|  |      * @param {ActivatedRouteSnapshot} route | ||||||
|  |      * @param {RouterStateSnapshot} state | ||||||
|  |      * @returns {Observable<any> | Promise<any> | any} | ||||||
|  |      */ | ||||||
|  |     resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         this.routeParams = route.params; | ||||||
|  | 
 | ||||||
|  |         return new Promise((resolve, reject) => { | ||||||
|  | 
 | ||||||
|  |             Promise.all([ | ||||||
|  |                 this.getProduct() | ||||||
|  |             ]).then( | ||||||
|  |                 () => { | ||||||
|  |                     resolve(); | ||||||
|  |                 }, | ||||||
|  |                 reject | ||||||
|  |             ); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     getProduct(): Promise<any> | ||||||
|  |     { | ||||||
|  |         return new Promise((resolve, reject) => { | ||||||
|  |             if ( this.routeParams.id === 'new' ) | ||||||
|  |             { | ||||||
|  |                 this.onProductChanged.next(false); | ||||||
|  |                 resolve(false); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 this.http.get('api/e-commerce-products/' + this.routeParams.id) | ||||||
|  |                     .subscribe((response: any) => { | ||||||
|  |                         this.product = response; | ||||||
|  |                         this.onProductChanged.next(this.product); | ||||||
|  |                         resolve(response); | ||||||
|  |                     }, reject); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     saveProduct(product) | ||||||
|  |     { | ||||||
|  |         return new Promise((resolve, reject) => { | ||||||
|  |             this.http.post('api/e-commerce-products/' + product.id, product) | ||||||
|  |                 .subscribe((response: any) => { | ||||||
|  |                     resolve(response); | ||||||
|  |                 }, reject); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     addProduct(product) | ||||||
|  |     { | ||||||
|  |         return new Promise((resolve, reject) => { | ||||||
|  |             this.http.post('api/e-commerce-products/', product) | ||||||
|  |                 .subscribe((response: any) => { | ||||||
|  |                     resolve(response); | ||||||
|  |                 }, reject); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,145 @@ | |||||||
|  | <div id="products" class="page-layout carded fullwidth" fusePerfectScrollbar> | ||||||
|  | 
 | ||||||
|  |     <!-- TOP BACKGROUND --> | ||||||
|  |     <div class="top-bg mat-accent-bg"></div> | ||||||
|  |     <!-- / TOP BACKGROUND --> | ||||||
|  | 
 | ||||||
|  |     <!-- CENTER --> | ||||||
|  |     <div class="center"> | ||||||
|  | 
 | ||||||
|  |         <!-- HEADER --> | ||||||
|  |         <div class="header white-fg" | ||||||
|  |              fxLayout="column" fxLayoutAlign="center center" | ||||||
|  |              fxLayout.gt-xs="row" fxLayoutAlign.gt-xs="space-between center"> | ||||||
|  | 
 | ||||||
|  |             <!-- APP TITLE --> | ||||||
|  |             <div class="logo my-12 m-sm-0" | ||||||
|  |                  fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  |                 <mat-icon class="logo-icon mr-16" *fuseIfOnDom [@animate]="{value:'*',params:{delay:'50ms',scale:'0.2'}}">shopping_basket</mat-icon> | ||||||
|  |                 <span class="logo-text h1" *fuseIfOnDom [@animate]="{value:'*',params:{delay:'100ms',x:'-25px'}}">Products</span> | ||||||
|  |             </div> | ||||||
|  |             <!-- / APP TITLE --> | ||||||
|  | 
 | ||||||
|  |             <!-- SEARCH --> | ||||||
|  |             <div class="search-input-wrapper mx-12 m-md-0" | ||||||
|  |                  fxFlex="1 0 auto" fxLayout="row" fxLayoutAlign="start center"> | ||||||
|  |                 <label for="search" class="mr-8"> | ||||||
|  |                     <mat-icon class="secondary-text">search</mat-icon> | ||||||
|  |                 </label> | ||||||
|  |                 <mat-form-field floatPlaceholder="never" fxFlex="1 0 auto"> | ||||||
|  |                     <input id="search" matInput #filter placeholder="Search"> | ||||||
|  |                 </mat-form-field> | ||||||
|  |             </div> | ||||||
|  |             <!-- / SEARCH --> | ||||||
|  | 
 | ||||||
|  |             <button mat-raised-button | ||||||
|  |                     [routerLink]="'/apps/e-commerce/products/new'" | ||||||
|  |                     class="add-product-button mat-white-bg my-12 mt-sm-0"> | ||||||
|  |                 <span>ADD NEW PRODUCT</span> | ||||||
|  |             </button> | ||||||
|  | 
 | ||||||
|  |         </div> | ||||||
|  |         <!-- / HEADER --> | ||||||
|  | 
 | ||||||
|  |         <!-- CONTENT CARD --> | ||||||
|  |         <div class="content-card mat-white-bg"> | ||||||
|  | 
 | ||||||
|  |             <mat-table class="products-table" | ||||||
|  |                        #table [dataSource]="dataSource" | ||||||
|  |                        matSort | ||||||
|  |                        [@animateStagger]="{value:'50'}" | ||||||
|  |                        fusePerfectScrollbar> | ||||||
|  | 
 | ||||||
|  |                 <!-- ID Column --> | ||||||
|  |                 <ng-container cdkColumnDef="id"> | ||||||
|  |                     <mat-header-cell *cdkHeaderCellDef mat-sort-header>ID</mat-header-cell> | ||||||
|  |                     <mat-cell *cdkCellDef="let product"> | ||||||
|  |                         <p class="text-truncate">{{product.id}}</p> | ||||||
|  |                     </mat-cell> | ||||||
|  |                 </ng-container> | ||||||
|  | 
 | ||||||
|  |                 <!-- Image Column --> | ||||||
|  |                 <ng-container cdkColumnDef="image"> | ||||||
|  |                     <mat-header-cell *cdkHeaderCellDef></mat-header-cell> | ||||||
|  |                     <mat-cell *cdkCellDef="let product"> | ||||||
|  |                         <img class="product-image" | ||||||
|  |                              *ngIf="product.images[0]" [alt]="product.name" | ||||||
|  |                              [src]="product.images[0].url"/> | ||||||
|  |                         <img *ngIf="!product.images[0]" [src]="'assets/images/ecommerce/product-image-placeholder.png'"> | ||||||
|  |                     </mat-cell> | ||||||
|  |                 </ng-container> | ||||||
|  | 
 | ||||||
|  |                 <!-- Name Column --> | ||||||
|  |                 <ng-container cdkColumnDef="name"> | ||||||
|  |                     <mat-header-cell *cdkHeaderCellDef mat-sort-header>Name</mat-header-cell> | ||||||
|  |                     <mat-cell *cdkCellDef="let product"> | ||||||
|  |                         <p class="text-truncate">{{product.name}}</p> | ||||||
|  |                     </mat-cell> | ||||||
|  |                 </ng-container> | ||||||
|  | 
 | ||||||
|  |                 <!-- Category Column --> | ||||||
|  |                 <ng-container cdkColumnDef="category"> | ||||||
|  |                     <mat-header-cell *cdkHeaderCellDef fxHide mat-sort-header fxShow.gt-md>Category</mat-header-cell> | ||||||
|  |                     <mat-cell *cdkCellDef="let product" fxHide fxShow.gt-md> | ||||||
|  |                         <p class="category text-truncate"> | ||||||
|  |                             {{product.categories[0]}} | ||||||
|  |                         </p> | ||||||
|  |                     </mat-cell> | ||||||
|  |                 </ng-container> | ||||||
|  | 
 | ||||||
|  |                 <!-- Price Column --> | ||||||
|  |                 <ng-container cdkColumnDef="price"> | ||||||
|  |                     <mat-header-cell *cdkHeaderCellDef mat-sort-header fxHide fxShow.gt-xs>Price</mat-header-cell> | ||||||
|  |                     <mat-cell *cdkCellDef="let product" fxHide fxShow.gt-xs> | ||||||
|  |                         <p class="price text-truncate"> | ||||||
|  |                             {{product.priceTaxIncl | currency:'USD':true}} | ||||||
|  |                         </p> | ||||||
|  |                     </mat-cell> | ||||||
|  |                 </ng-container> | ||||||
|  | 
 | ||||||
|  |                 <!-- Quantity Column --> | ||||||
|  |                 <ng-container cdkColumnDef="quantity"> | ||||||
|  |                     <mat-header-cell *cdkHeaderCellDef mat-sort-header fxHide fxShow.gt-sm>Quantity</mat-header-cell> | ||||||
|  |                     <mat-cell *cdkCellDef="let product" fxHide fxShow.gt-sm> | ||||||
|  | 
 | ||||||
|  |                         <span class="quantity-indicator text-truncate" | ||||||
|  |                               [ngClass]="{'mat-red-500-bg':product.quantity <= 5, 'mat-amber-500-bg':product.quantity > 5 && product.quantity <= 25,'mat-green-600-bg':product.quantity > 25}"> | ||||||
|  |                         </span> | ||||||
|  |                         <span> | ||||||
|  |                             {{product.quantity}} | ||||||
|  |                         </span> | ||||||
|  | 
 | ||||||
|  |                     </mat-cell> | ||||||
|  |                 </ng-container> | ||||||
|  | 
 | ||||||
|  |                 <!-- Active Column --> | ||||||
|  |                 <ng-container cdkColumnDef="active"> | ||||||
|  |                     <mat-header-cell *cdkHeaderCellDef mat-sort-header fxHide fxShow.gt-xs>Active</mat-header-cell> | ||||||
|  |                     <mat-cell *cdkCellDef="let product" fxHide fxShow.gt-xs> | ||||||
|  |                         <mat-icon *ngIf="product.active" class="active-icon mat-green-600-bg s-16">check</mat-icon> | ||||||
|  |                         <mat-icon *ngIf="!product.active" class="active-icon mat-red-500-bg s-16">close</mat-icon> | ||||||
|  |                     </mat-cell> | ||||||
|  |                 </ng-container> | ||||||
|  | 
 | ||||||
|  |                 <mat-header-row *cdkHeaderRowDef="displayedColumns"></mat-header-row> | ||||||
|  | 
 | ||||||
|  |                 <mat-row *cdkRowDef="let product; columns: displayedColumns;" | ||||||
|  |                          class="product" | ||||||
|  |                          matRipple | ||||||
|  |                          [routerLink]="'/apps/e-commerce/products/'+product.id+'/'+product.handle"> | ||||||
|  |                 </mat-row> | ||||||
|  | 
 | ||||||
|  |             </mat-table> | ||||||
|  | 
 | ||||||
|  |             <mat-paginator #paginator | ||||||
|  |                            [length]="dataSource.filteredData.length" | ||||||
|  |                            [pageIndex]="0" | ||||||
|  |                            [pageSize]="10" | ||||||
|  |                            [pageSizeOptions]="[5, 10, 25, 100]"> | ||||||
|  |             </mat-paginator> | ||||||
|  | 
 | ||||||
|  |         </div> | ||||||
|  |         <!-- / CONTENT CARD --> | ||||||
|  |     </div> | ||||||
|  |     <!-- / CENTER --> | ||||||
|  | </div> | ||||||
| @ -0,0 +1,80 @@ | |||||||
|  | @import "src/app/core/scss/fuse"; | ||||||
|  | 
 | ||||||
|  | :host { | ||||||
|  | 
 | ||||||
|  |     .header { | ||||||
|  | 
 | ||||||
|  |         .search-input-wrapper { | ||||||
|  |             max-width: 480px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @include media-breakpoint-down(xs) { | ||||||
|  |             height: 176px !important; | ||||||
|  |             min-height: 176px !important; | ||||||
|  |             max-height: 176px !important; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     .top-bg { | ||||||
|  |         @include media-breakpoint-down(xs) { | ||||||
|  |             height: 240px; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     .products-table { | ||||||
|  |         flex: 1 1 auto; | ||||||
|  |         border-bottom: 1px solid rgba(0, 0, 0, .12); | ||||||
|  | 
 | ||||||
|  |         .mat-header-row { | ||||||
|  |             min-height: 64px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .product { | ||||||
|  |             position: relative; | ||||||
|  |             cursor: pointer; | ||||||
|  |             height: 84px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .mat-cell { | ||||||
|  |             min-width: 0; | ||||||
|  |             display: flex; | ||||||
|  |             align-items: center; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .mat-column-id { | ||||||
|  |             flex: 0 1 84px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .mat-column-image { | ||||||
|  |             flex: 0 1 84px; | ||||||
|  | 
 | ||||||
|  |             .product-image { | ||||||
|  |                 width: 52px; | ||||||
|  |                 height: 52px; | ||||||
|  |                 border: 1px solid rgba(0, 0, 0, .12); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .mat-column-buttons { | ||||||
|  |             flex: 0 1 80px; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .quantity-indicator { | ||||||
|  |             display: inline-block; | ||||||
|  |             vertical-align: middle; | ||||||
|  |             width: 8px; | ||||||
|  |             height: 8px; | ||||||
|  |             border-radius: 4px; | ||||||
|  |             margin-right: 8px; | ||||||
|  | 
 | ||||||
|  |             & + span { | ||||||
|  |                 display: inline-block; | ||||||
|  |                 vertical-align: middle; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .active-icon { | ||||||
|  |             border-radius: 50%; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,165 @@ | |||||||
|  | import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; | ||||||
|  | import { EcommerceProductsService } from './products.service'; | ||||||
|  | import { DataSource } from '@angular/cdk/collections'; | ||||||
|  | import { Observable } from 'rxjs/Observable'; | ||||||
|  | import { fuseAnimations } from '../../../../../core/animations'; | ||||||
|  | import { MatPaginator, MatSort } from '@angular/material'; | ||||||
|  | import { BehaviorSubject } from 'rxjs/BehaviorSubject'; | ||||||
|  | import 'rxjs/add/operator/startWith'; | ||||||
|  | import 'rxjs/add/observable/merge'; | ||||||
|  | import 'rxjs/add/operator/map'; | ||||||
|  | import 'rxjs/add/operator/debounceTime'; | ||||||
|  | import 'rxjs/add/operator/distinctUntilChanged'; | ||||||
|  | import 'rxjs/add/observable/fromEvent'; | ||||||
|  | import { FuseUtils } from '../../../../../core/fuseUtils'; | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |     selector   : 'fuse-e-commerce-products', | ||||||
|  |     templateUrl: './products.component.html', | ||||||
|  |     styleUrls  : ['./products.component.scss'], | ||||||
|  |     animations : fuseAnimations | ||||||
|  | }) | ||||||
|  | export class FuseEcommerceProductsComponent implements OnInit | ||||||
|  | { | ||||||
|  |     dataSource: FilesDataSource | null; | ||||||
|  |     displayedColumns = ['id', 'image', 'name', 'category', 'price', 'quantity', 'active']; | ||||||
|  | 
 | ||||||
|  |     @ViewChild(MatPaginator) paginator: MatPaginator; | ||||||
|  |     @ViewChild('filter') filter: ElementRef; | ||||||
|  |     @ViewChild(MatSort) sort: MatSort; | ||||||
|  | 
 | ||||||
|  |     constructor( | ||||||
|  |         private productsService: EcommerceProductsService | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ngOnInit() | ||||||
|  |     { | ||||||
|  |         this.dataSource = new FilesDataSource(this.productsService, this.paginator, this.sort); | ||||||
|  |         Observable.fromEvent(this.filter.nativeElement, 'keyup') | ||||||
|  |                   .debounceTime(150) | ||||||
|  |                   .distinctUntilChanged() | ||||||
|  |                   .subscribe(() => { | ||||||
|  |                       if ( !this.dataSource ) | ||||||
|  |                       { | ||||||
|  |                           return; | ||||||
|  |                       } | ||||||
|  |                       this.dataSource.filter = this.filter.nativeElement.value; | ||||||
|  |                   }); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export class FilesDataSource extends DataSource<any> | ||||||
|  | { | ||||||
|  |     _filterChange = new BehaviorSubject(''); | ||||||
|  |     _filteredDataChange = new BehaviorSubject(''); | ||||||
|  | 
 | ||||||
|  |     get filteredData(): any | ||||||
|  |     { | ||||||
|  |         return this._filteredDataChange.value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     set filteredData(value: any) | ||||||
|  |     { | ||||||
|  |         this._filteredDataChange.next(value); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     get filter(): string | ||||||
|  |     { | ||||||
|  |         return this._filterChange.value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     set filter(filter: string) | ||||||
|  |     { | ||||||
|  |         this._filterChange.next(filter); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     constructor( | ||||||
|  |         private productsService: EcommerceProductsService, | ||||||
|  |         private _paginator: MatPaginator, | ||||||
|  |         private _sort: MatSort | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |         super(); | ||||||
|  |         this.filteredData = this.productsService.products; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** Connect function called by the table to retrieve one stream containing the data to render. */ | ||||||
|  |     connect(): Observable<any[]> | ||||||
|  |     { | ||||||
|  |         const displayDataChanges = [ | ||||||
|  |             this.productsService.onProductsChanged, | ||||||
|  |             this._paginator.page, | ||||||
|  |             this._filterChange, | ||||||
|  |             this._sort.sortChange | ||||||
|  |         ]; | ||||||
|  | 
 | ||||||
|  |         return Observable.merge(...displayDataChanges).map(() => { | ||||||
|  |             let data = this.productsService.products.slice(); | ||||||
|  | 
 | ||||||
|  |             data = this.filterData(data); | ||||||
|  | 
 | ||||||
|  |             this.filteredData = [...data]; | ||||||
|  | 
 | ||||||
|  |             data = this.sortData(data); | ||||||
|  | 
 | ||||||
|  |             // Grab the page's slice of data.
 | ||||||
|  |             const startIndex = this._paginator.pageIndex * this._paginator.pageSize; | ||||||
|  |             return data.splice(startIndex, this._paginator.pageSize); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     filterData(data) | ||||||
|  |     { | ||||||
|  |         if ( !this.filter ) | ||||||
|  |         { | ||||||
|  |             return data; | ||||||
|  |         } | ||||||
|  |         return FuseUtils.filterArrayByString(data, this.filter); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     sortData(data): any[] | ||||||
|  |     { | ||||||
|  |         if ( !this._sort.active || this._sort.direction === '' ) | ||||||
|  |         { | ||||||
|  |             return data; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return data.sort((a, b) => { | ||||||
|  |             let propertyA: number | string = ''; | ||||||
|  |             let propertyB: number | string = ''; | ||||||
|  | 
 | ||||||
|  |             switch ( this._sort.active ) | ||||||
|  |             { | ||||||
|  |                 case 'id': | ||||||
|  |                     [propertyA, propertyB] = [a.id, b.id]; | ||||||
|  |                     break; | ||||||
|  |                 case 'name': | ||||||
|  |                     [propertyA, propertyB] = [a.name, b.name]; | ||||||
|  |                     break; | ||||||
|  |                 case 'categories': | ||||||
|  |                     [propertyA, propertyB] = [a.categories[0], b.categories[0]]; | ||||||
|  |                     break; | ||||||
|  |                 case 'price': | ||||||
|  |                     [propertyA, propertyB] = [a.priceTaxIncl, b.priceTaxIncl]; | ||||||
|  |                     break; | ||||||
|  |                 case 'quantity': | ||||||
|  |                     [propertyA, propertyB] = [a.quantity, b.quantity]; | ||||||
|  |                     break; | ||||||
|  |                 case 'active': | ||||||
|  |                     [propertyA, propertyB] = [a.active, b.active]; | ||||||
|  |                     break; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             const valueA = isNaN(+propertyA) ? propertyA : +propertyA; | ||||||
|  |             const valueB = isNaN(+propertyB) ? propertyB : +propertyB; | ||||||
|  | 
 | ||||||
|  |             return (valueA < valueB ? -1 : 1) * (this._sort.direction === 'asc' ? 1 : -1); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     disconnect() | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,52 @@ | |||||||
|  | import { Injectable } from '@angular/core'; | ||||||
|  | import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; | ||||||
|  | import { Observable } from 'rxjs/Observable'; | ||||||
|  | import { HttpClient } from '@angular/common/http'; | ||||||
|  | import { BehaviorSubject } from 'rxjs/BehaviorSubject'; | ||||||
|  | 
 | ||||||
|  | @Injectable() | ||||||
|  | export class EcommerceProductsService implements Resolve<any> | ||||||
|  | { | ||||||
|  |     products: any[]; | ||||||
|  |     onProductsChanged: BehaviorSubject<any> = new BehaviorSubject({}); | ||||||
|  | 
 | ||||||
|  |     constructor( | ||||||
|  |         private http: HttpClient | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Resolve | ||||||
|  |      * @param {ActivatedRouteSnapshot} route | ||||||
|  |      * @param {RouterStateSnapshot} state | ||||||
|  |      * @returns {Observable<any> | Promise<any> | any} | ||||||
|  |      */ | ||||||
|  |     resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         return new Promise((resolve, reject) => { | ||||||
|  | 
 | ||||||
|  |             Promise.all([ | ||||||
|  |                 this.getProducts() | ||||||
|  |             ]).then( | ||||||
|  |                 () => { | ||||||
|  |                     resolve(); | ||||||
|  |                 }, | ||||||
|  |                 reject | ||||||
|  |             ); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     getProducts(): Promise<any> | ||||||
|  |     { | ||||||
|  |         return new Promise((resolve, reject) => { | ||||||
|  |             this.http.get('api/e-commerce-products') | ||||||
|  |                 .subscribe((response: any) => { | ||||||
|  |                     this.products = response; | ||||||
|  |                     this.onProductsChanged.next(this.products); | ||||||
|  |                     resolve(response); | ||||||
|  |                 }, reject); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -32,6 +32,32 @@ export class NavigationModel | |||||||
|                         'icon' : 'today', |                         'icon' : 'today', | ||||||
|                         'url'  : '/apps/calendar' |                         'url'  : '/apps/calendar' | ||||||
|                     }, |                     }, | ||||||
|  |                     { | ||||||
|  |                         'id'      : 'e-commerce', | ||||||
|  |                         'title'   : 'E-Commerce', | ||||||
|  |                         'type'    : 'collapse', | ||||||
|  |                         'icon'    : 'shopping_cart', | ||||||
|  |                         'children': [ | ||||||
|  |                             { | ||||||
|  |                                 'id'   : 'dashboard', | ||||||
|  |                                 'title': 'Dashboard', | ||||||
|  |                                 'type' : 'item', | ||||||
|  |                                 'url'  : '/apps/e-commerce/dashboard' | ||||||
|  |                             }, | ||||||
|  |                             { | ||||||
|  |                                 'id'   : 'dashboard', | ||||||
|  |                                 'title': 'Products', | ||||||
|  |                                 'type' : 'item', | ||||||
|  |                                 'url'  : '/apps/e-commerce/products' | ||||||
|  |                             }, | ||||||
|  |                             { | ||||||
|  |                                 'id'   : 'dashboard', | ||||||
|  |                                 'title': 'Orders', | ||||||
|  |                                 'type' : 'item', | ||||||
|  |                                 'url'  : '/apps/e-commerce/orders' | ||||||
|  |                             } | ||||||
|  |                         ] | ||||||
|  |                     }, | ||||||
|                     { |                     { | ||||||
|                         'id'   : 'mail', |                         'id'   : 'mail', | ||||||
|                         'title': 'Mail', |                         'title': 'Mail', | ||||||
| @ -807,3 +833,4 @@ export class NavigationModel | |||||||
|         ]; |         ]; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user