mirror of
				https://github.com/nitnelave/lldap.git
				synced 2023-04-12 14:25:13 +00:00 
			
		
		
		
	Refactor to context and reducer
This commit is contained in:
		
							parent
							
								
									cbc6c87d48
								
							
						
					
					
						commit
						e2fd9686a8
					
				
							
								
								
									
										210
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										210
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -1532,6 +1532,25 @@ dependencies = [
 | 
				
			|||||||
 "gloo-utils",
 | 
					 "gloo-utils",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "gloo"
 | 
				
			||||||
 | 
					version = "0.8.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "3a4bef6b277b3ab073253d4bca60761240cf8d6998f4bd142211957b69a61b20"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "gloo-console",
 | 
				
			||||||
 | 
					 "gloo-dialogs",
 | 
				
			||||||
 | 
					 "gloo-events",
 | 
				
			||||||
 | 
					 "gloo-file",
 | 
				
			||||||
 | 
					 "gloo-history",
 | 
				
			||||||
 | 
					 "gloo-net",
 | 
				
			||||||
 | 
					 "gloo-render",
 | 
				
			||||||
 | 
					 "gloo-storage",
 | 
				
			||||||
 | 
					 "gloo-timers",
 | 
				
			||||||
 | 
					 "gloo-utils",
 | 
				
			||||||
 | 
					 "gloo-worker 0.2.1",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "gloo-console"
 | 
					name = "gloo-console"
 | 
				
			||||||
version = "0.2.3"
 | 
					version = "0.2.3"
 | 
				
			||||||
@ -1578,6 +1597,22 @@ dependencies = [
 | 
				
			|||||||
 "web-sys",
 | 
					 "web-sys",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "gloo-history"
 | 
				
			||||||
 | 
					version = "0.1.3"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "dd451019e0b7a2b8a7a7b23e74916601abf1135c54664e57ff71dcc26dfcdeb7"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "gloo-events",
 | 
				
			||||||
 | 
					 "gloo-utils",
 | 
				
			||||||
 | 
					 "serde",
 | 
				
			||||||
 | 
					 "serde-wasm-bindgen 0.4.5",
 | 
				
			||||||
 | 
					 "serde_urlencoded",
 | 
				
			||||||
 | 
					 "thiserror",
 | 
				
			||||||
 | 
					 "wasm-bindgen",
 | 
				
			||||||
 | 
					 "web-sys",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "gloo-net"
 | 
					name = "gloo-net"
 | 
				
			||||||
version = "0.2.6"
 | 
					version = "0.2.6"
 | 
				
			||||||
@ -1648,6 +1683,40 @@ dependencies = [
 | 
				
			|||||||
 "web-sys",
 | 
					 "web-sys",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "gloo-worker"
 | 
				
			||||||
 | 
					version = "0.1.2"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "09110b5555bcafe508cee0fb94308af9aac7a85f980d3c88b270d117c6c6911d"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "anymap2",
 | 
				
			||||||
 | 
					 "bincode",
 | 
				
			||||||
 | 
					 "gloo-console",
 | 
				
			||||||
 | 
					 "gloo-utils",
 | 
				
			||||||
 | 
					 "js-sys",
 | 
				
			||||||
 | 
					 "serde",
 | 
				
			||||||
 | 
					 "slab",
 | 
				
			||||||
 | 
					 "wasm-bindgen",
 | 
				
			||||||
 | 
					 "web-sys",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "gloo-worker"
 | 
				
			||||||
 | 
					version = "0.2.1"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "13471584da78061a28306d1359dd0178d8d6fc1c7c80e5e35d27260346e0516a"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "anymap2",
 | 
				
			||||||
 | 
					 "bincode",
 | 
				
			||||||
 | 
					 "gloo-console",
 | 
				
			||||||
 | 
					 "gloo-utils",
 | 
				
			||||||
 | 
					 "js-sys",
 | 
				
			||||||
 | 
					 "serde",
 | 
				
			||||||
 | 
					 "wasm-bindgen",
 | 
				
			||||||
 | 
					 "wasm-bindgen-futures",
 | 
				
			||||||
 | 
					 "web-sys",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "graphql-introspection-query"
 | 
					name = "graphql-introspection-query"
 | 
				
			||||||
version = "0.2.0"
 | 
					version = "0.2.0"
 | 
				
			||||||
@ -2044,6 +2113,15 @@ dependencies = [
 | 
				
			|||||||
 "num-traits",
 | 
					 "num-traits",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "implicit-clone"
 | 
				
			||||||
 | 
					version = "0.3.5"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "40fc102e70475c320b185cd18c1e48bba2d7210b63970a4d581ef903e4368ef7"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "indexmap",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "indexmap"
 | 
					name = "indexmap"
 | 
				
			||||||
version = "1.6.2"
 | 
					version = "1.6.2"
 | 
				
			||||||
@ -2410,7 +2488,7 @@ dependencies = [
 | 
				
			|||||||
 "tracing-forest",
 | 
					 "tracing-forest",
 | 
				
			||||||
 "tracing-log",
 | 
					 "tracing-log",
 | 
				
			||||||
 "tracing-subscriber",
 | 
					 "tracing-subscriber",
 | 
				
			||||||
 "uuid 0.8.2",
 | 
					 "uuid 1.3.0",
 | 
				
			||||||
 "webpki-roots",
 | 
					 "webpki-roots",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2439,7 +2517,7 @@ dependencies = [
 | 
				
			|||||||
 "wasm-bindgen",
 | 
					 "wasm-bindgen",
 | 
				
			||||||
 "wasm-bindgen-futures",
 | 
					 "wasm-bindgen-futures",
 | 
				
			||||||
 "web-sys",
 | 
					 "web-sys",
 | 
				
			||||||
 "yew",
 | 
					 "yew 0.19.3",
 | 
				
			||||||
 "yew-agent",
 | 
					 "yew-agent",
 | 
				
			||||||
 "yew-router",
 | 
					 "yew-router",
 | 
				
			||||||
 "yew_form",
 | 
					 "yew_form",
 | 
				
			||||||
@ -2537,12 +2615,6 @@ dependencies = [
 | 
				
			|||||||
 "digest 0.10.6",
 | 
					 "digest 0.10.6",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "md5"
 | 
					 | 
				
			||||||
version = "0.7.0"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "memchr"
 | 
					name = "memchr"
 | 
				
			||||||
version = "2.5.0"
 | 
					version = "2.5.0"
 | 
				
			||||||
@ -3003,6 +3075,17 @@ version = "0.1.0"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 | 
					checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "pinned"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "a829027bd95e54cfe13e3e258a1ae7b645960553fb82b75ff852c29688ee595b"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "futures",
 | 
				
			||||||
 | 
					 "rustversion",
 | 
				
			||||||
 | 
					 "thiserror",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "pkcs1"
 | 
					name = "pkcs1"
 | 
				
			||||||
version = "0.3.3"
 | 
					version = "0.3.3"
 | 
				
			||||||
@ -3067,6 +3150,16 @@ dependencies = [
 | 
				
			|||||||
 "termtree",
 | 
					 "termtree",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "prettyplease"
 | 
				
			||||||
 | 
					version = "0.1.25"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "proc-macro2",
 | 
				
			||||||
 | 
					 "syn",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "proc-macro-error"
 | 
					name = "proc-macro-error"
 | 
				
			||||||
version = "1.0.4"
 | 
					version = "1.0.4"
 | 
				
			||||||
@ -3113,6 +3206,23 @@ dependencies = [
 | 
				
			|||||||
 "yansi",
 | 
					 "yansi",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "prokio"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "03b55e106e5791fa5a13abd13c85d6127312e8e09098059ca2bc9b03ca4cf488"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "futures",
 | 
				
			||||||
 | 
					 "gloo 0.8.0",
 | 
				
			||||||
 | 
					 "num_cpus",
 | 
				
			||||||
 | 
					 "once_cell",
 | 
				
			||||||
 | 
					 "pin-project",
 | 
				
			||||||
 | 
					 "pinned",
 | 
				
			||||||
 | 
					 "tokio",
 | 
				
			||||||
 | 
					 "tokio-stream",
 | 
				
			||||||
 | 
					 "wasm-bindgen-futures",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "quote"
 | 
					name = "quote"
 | 
				
			||||||
version = "1.0.23"
 | 
					version = "1.0.23"
 | 
				
			||||||
@ -3645,6 +3755,17 @@ dependencies = [
 | 
				
			|||||||
 "wasm-bindgen",
 | 
					 "wasm-bindgen",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "serde-wasm-bindgen"
 | 
				
			||||||
 | 
					version = "0.4.5"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "js-sys",
 | 
				
			||||||
 | 
					 "serde",
 | 
				
			||||||
 | 
					 "wasm-bindgen",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "serde_bytes"
 | 
					name = "serde_bytes"
 | 
				
			||||||
version = "0.11.9"
 | 
					version = "0.11.9"
 | 
				
			||||||
@ -4411,9 +4532,6 @@ name = "uuid"
 | 
				
			|||||||
version = "0.8.2"
 | 
					version = "0.8.2"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
 | 
					checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "md5",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "uuid"
 | 
					name = "uuid"
 | 
				
			||||||
@ -4422,6 +4540,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			|||||||
checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
 | 
					checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "getrandom 0.2.8",
 | 
					 "getrandom 0.2.8",
 | 
				
			||||||
 | 
					 "md-5",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -4775,7 +4894,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			|||||||
checksum = "2a1ccb53e57d3f7d847338cf5758befa811cabe207df07f543c06f502f9998cd"
 | 
					checksum = "2a1ccb53e57d3f7d847338cf5758befa811cabe207df07f543c06f502f9998cd"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "console_error_panic_hook",
 | 
					 "console_error_panic_hook",
 | 
				
			||||||
 "gloo",
 | 
					 "gloo 0.4.2",
 | 
				
			||||||
 "gloo-utils",
 | 
					 "gloo-utils",
 | 
				
			||||||
 "indexmap",
 | 
					 "indexmap",
 | 
				
			||||||
 "js-sys",
 | 
					 "js-sys",
 | 
				
			||||||
@ -4784,26 +4903,42 @@ dependencies = [
 | 
				
			|||||||
 "wasm-bindgen",
 | 
					 "wasm-bindgen",
 | 
				
			||||||
 "wasm-bindgen-futures",
 | 
					 "wasm-bindgen-futures",
 | 
				
			||||||
 "web-sys",
 | 
					 "web-sys",
 | 
				
			||||||
 "yew-macro",
 | 
					 "yew-macro 0.19.3",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "yew"
 | 
				
			||||||
 | 
					version = "0.20.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "5dbecfe44343b70cc2932c3eb445425969ae21754a8ab3a0966981c1cf7af1cc"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "console_error_panic_hook",
 | 
				
			||||||
 | 
					 "futures",
 | 
				
			||||||
 | 
					 "gloo 0.8.0",
 | 
				
			||||||
 | 
					 "implicit-clone",
 | 
				
			||||||
 | 
					 "indexmap",
 | 
				
			||||||
 | 
					 "js-sys",
 | 
				
			||||||
 | 
					 "prokio",
 | 
				
			||||||
 | 
					 "rustversion",
 | 
				
			||||||
 | 
					 "serde",
 | 
				
			||||||
 | 
					 "slab",
 | 
				
			||||||
 | 
					 "thiserror",
 | 
				
			||||||
 | 
					 "tokio",
 | 
				
			||||||
 | 
					 "tracing",
 | 
				
			||||||
 | 
					 "wasm-bindgen",
 | 
				
			||||||
 | 
					 "wasm-bindgen-futures",
 | 
				
			||||||
 | 
					 "web-sys",
 | 
				
			||||||
 | 
					 "yew-macro 0.20.0",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "yew-agent"
 | 
					name = "yew-agent"
 | 
				
			||||||
version = "0.1.0"
 | 
					version = "0.2.0"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "616700dc3851945658c44ba4477ede6b77c795462fbbb9b0ad9a8b6273a3ca77"
 | 
					checksum = "b06f7c5ed97fff22816bb00d3d82ebc0fc1119d7bbb9e07e62c0d2853f51920a"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "anymap2",
 | 
					 "gloo-worker 0.1.2",
 | 
				
			||||||
 "bincode",
 | 
					 "yew 0.20.0",
 | 
				
			||||||
 "gloo-console",
 | 
					 | 
				
			||||||
 "gloo-utils",
 | 
					 | 
				
			||||||
 "js-sys",
 | 
					 | 
				
			||||||
 "serde",
 | 
					 | 
				
			||||||
 "slab",
 | 
					 | 
				
			||||||
 "wasm-bindgen",
 | 
					 | 
				
			||||||
 "wasm-bindgen-futures",
 | 
					 | 
				
			||||||
 "web-sys",
 | 
					 | 
				
			||||||
 "yew",
 | 
					 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -4820,23 +4955,38 @@ dependencies = [
 | 
				
			|||||||
 "syn",
 | 
					 "syn",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "yew-macro"
 | 
				
			||||||
 | 
					version = "0.20.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "b64c253c1d401f1ea868ca9988db63958cfa15a69f739101f338d6f05eea8301"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "boolinator",
 | 
				
			||||||
 | 
					 "once_cell",
 | 
				
			||||||
 | 
					 "prettyplease",
 | 
				
			||||||
 | 
					 "proc-macro-error",
 | 
				
			||||||
 | 
					 "proc-macro2",
 | 
				
			||||||
 | 
					 "quote",
 | 
				
			||||||
 | 
					 "syn",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "yew-router"
 | 
					name = "yew-router"
 | 
				
			||||||
version = "0.16.0"
 | 
					version = "0.16.0"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "155804f6f3aa309f596d5c3fa14486a94e7756f1edd7634569949e401d5099f2"
 | 
					checksum = "155804f6f3aa309f596d5c3fa14486a94e7756f1edd7634569949e401d5099f2"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "gloo",
 | 
					 "gloo 0.4.2",
 | 
				
			||||||
 "gloo-utils",
 | 
					 "gloo-utils",
 | 
				
			||||||
 "js-sys",
 | 
					 "js-sys",
 | 
				
			||||||
 "route-recognizer",
 | 
					 "route-recognizer",
 | 
				
			||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
 "serde-wasm-bindgen",
 | 
					 "serde-wasm-bindgen 0.3.1",
 | 
				
			||||||
 "serde_urlencoded",
 | 
					 "serde_urlencoded",
 | 
				
			||||||
 "thiserror",
 | 
					 "thiserror",
 | 
				
			||||||
 "wasm-bindgen",
 | 
					 "wasm-bindgen",
 | 
				
			||||||
 "web-sys",
 | 
					 "web-sys",
 | 
				
			||||||
 "yew",
 | 
					 "yew 0.19.3",
 | 
				
			||||||
 "yew-router-macro",
 | 
					 "yew-router-macro",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -4861,7 +5011,7 @@ dependencies = [
 | 
				
			|||||||
 "validator_derive",
 | 
					 "validator_derive",
 | 
				
			||||||
 "wasm-bindgen",
 | 
					 "wasm-bindgen",
 | 
				
			||||||
 "web-sys",
 | 
					 "web-sys",
 | 
				
			||||||
 "yew",
 | 
					 "yew 0.19.3",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,7 @@ wasm-bindgen = "0.2"
 | 
				
			|||||||
wasm-bindgen-futures = "*"
 | 
					wasm-bindgen-futures = "*"
 | 
				
			||||||
yew = "0.19.3"
 | 
					yew = "0.19.3"
 | 
				
			||||||
yew-router = "0.16"
 | 
					yew-router = "0.16"
 | 
				
			||||||
yew-agent = "0.1.0"
 | 
					yew-agent = "0.2.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Needed because of https://github.com/tkaitchuck/aHash/issues/95
 | 
					# Needed because of https://github.com/tkaitchuck/aHash/issues/95
 | 
				
			||||||
indexmap = "=1.6.2"
 | 
					indexmap = "=1.6.2"
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
query GetUserAvatar($id: String!) {
 | 
					query GetUserAvatar($id: String!) {
 | 
				
			||||||
  user(userId: $id) {
 | 
					  user(userId: $id) {
 | 
				
			||||||
 | 
					    id
 | 
				
			||||||
    avatar
 | 
					    avatar
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    components::{
 | 
					    components::{
 | 
				
			||||||
        avatar::ShowAvatar,
 | 
					        avatar::ShowAvatar,
 | 
				
			||||||
 | 
					        avatar_cache::*,
 | 
				
			||||||
        change_password::ChangePasswordForm,
 | 
					        change_password::ChangePasswordForm,
 | 
				
			||||||
        create_group::CreateGroupForm,
 | 
					        create_group::CreateGroupForm,
 | 
				
			||||||
        create_user::CreateUserForm,
 | 
					        create_user::CreateUserForm,
 | 
				
			||||||
@ -137,8 +138,19 @@ impl Component for App {
 | 
				
			|||||||
        let link = ctx.link().clone();
 | 
					        let link = ctx.link().clone();
 | 
				
			||||||
        let is_admin = self.is_admin();
 | 
					        let is_admin = self.is_admin();
 | 
				
			||||||
        let password_reset_enabled = self.password_reset_enabled;
 | 
					        let password_reset_enabled = self.password_reset_enabled;
 | 
				
			||||||
 | 
					        let mode = self
 | 
				
			||||||
 | 
					            .user_info
 | 
				
			||||||
 | 
					            .clone()
 | 
				
			||||||
 | 
					            .map(|(username, is_admin)| {
 | 
				
			||||||
 | 
					                if is_admin {
 | 
				
			||||||
 | 
					                    CacheMode::AllUsers
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    CacheMode::SingleUser(username)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .unwrap_or(CacheMode::None);
 | 
				
			||||||
        html! {
 | 
					        html! {
 | 
				
			||||||
          <div>
 | 
					          <AvatarCacheProvider {mode}>
 | 
				
			||||||
            {self.view_banner(ctx)}
 | 
					            {self.view_banner(ctx)}
 | 
				
			||||||
            <div class="container py-3 bg-kug">
 | 
					            <div class="container py-3 bg-kug">
 | 
				
			||||||
              <div class="row justify-content-center" style="padding-bottom: 80px;">
 | 
					              <div class="row justify-content-center" style="padding-bottom: 80px;">
 | 
				
			||||||
@ -150,7 +162,7 @@ impl Component for App {
 | 
				
			|||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
              {self.view_footer()}
 | 
					              {self.view_footer()}
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
          </div>
 | 
					          </AvatarCacheProvider>
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,126 +1,31 @@
 | 
				
			|||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    components::avatar_event_bus::{AvatarEventBus, Response},
 | 
					    components::avatar_cache::{AvatarCacheContext},
 | 
				
			||||||
    infra::common_component::{CommonComponent, CommonComponentParts},
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use anyhow::{bail, Result};
 | 
					use yew::{function_component, prelude::*};
 | 
				
			||||||
use graphql_client::GraphQLQuery;
 | 
					 | 
				
			||||||
use serde::{Deserialize, Serialize};
 | 
					 | 
				
			||||||
use yew::prelude::*;
 | 
					 | 
				
			||||||
use yew_agent::{Bridge, Bridged};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(GraphQLQuery)]
 | 
					#[derive(Properties, PartialEq)]
 | 
				
			||||||
#[graphql(
 | 
					 | 
				
			||||||
    schema_path = "../schema.graphql",
 | 
					 | 
				
			||||||
    query_path = "queries/get_user_avatar.graphql",
 | 
					 | 
				
			||||||
    response_derives = "Debug",
 | 
					 | 
				
			||||||
    custom_scalars_module = "crate::infra::graphql"
 | 
					 | 
				
			||||||
)]
 | 
					 | 
				
			||||||
pub struct GetUserAvatar;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
 | 
					 | 
				
			||||||
pub struct AvatarData(String);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl AvatarData {
 | 
					 | 
				
			||||||
    pub fn new(data: String) -> Self {
 | 
					 | 
				
			||||||
        AvatarData(data)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub struct ShowAvatar {
 | 
					 | 
				
			||||||
    common: CommonComponentParts<Self>,
 | 
					 | 
				
			||||||
    avatar: Option<AvatarData>,
 | 
					 | 
				
			||||||
    _producer: Box<dyn Bridge<AvatarEventBus>>,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// State machine describing the possible transitions of the component state.
 | 
					 | 
				
			||||||
/// It starts out by fetching the user's details from the backend when loading.
 | 
					 | 
				
			||||||
pub enum Msg {
 | 
					 | 
				
			||||||
    /// Received the user details response, either the user data or an error.
 | 
					 | 
				
			||||||
    UserAvatarResponse(Result<get_user_avatar::ResponseData>),
 | 
					 | 
				
			||||||
    Update(Response),
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(yew::Properties, Clone, PartialEq, Eq)]
 | 
					 | 
				
			||||||
pub struct Props {
 | 
					pub struct Props {
 | 
				
			||||||
    pub username: String,
 | 
					    pub username: String,
 | 
				
			||||||
    pub width: i32,
 | 
					    pub width: i32,
 | 
				
			||||||
    pub height: i32,
 | 
					    pub height: i32,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl CommonComponent<ShowAvatar> for ShowAvatar {
 | 
					#[function_component(ShowAvatar)]
 | 
				
			||||||
    fn handle_msg(
 | 
					pub fn show_avatar(props: &Props) -> Html {
 | 
				
			||||||
        &mut self,
 | 
					    let cache = use_context::<AvatarCacheContext>().expect("no ctx found");
 | 
				
			||||||
        ctx: &Context<Self>,
 | 
					    let avatar = cache.avatars.get(&props.username).map(|val| val.clone()).unwrap_or(None);
 | 
				
			||||||
        msg: <Self as Component>::Message,
 | 
					    match avatar {
 | 
				
			||||||
    ) -> Result<bool> {
 | 
					 | 
				
			||||||
        match msg {
 | 
					 | 
				
			||||||
            Msg::UserAvatarResponse(response) => match response {
 | 
					 | 
				
			||||||
                Ok(user) => self.avatar = user.user.avatar.map(AvatarData::new),
 | 
					 | 
				
			||||||
                Err(e) => {
 | 
					 | 
				
			||||||
                    self.avatar = None;
 | 
					 | 
				
			||||||
                    bail!("Error getting user avatar: {}", e);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            Msg::Update(Response::Update((username, avatar))) => {
 | 
					 | 
				
			||||||
                if username == ctx.props().username {
 | 
					 | 
				
			||||||
                    self.avatar = avatar;
 | 
					 | 
				
			||||||
                    return Ok(true);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                return Ok(false);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        Ok(true)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn mut_common(&mut self) -> &mut CommonComponentParts<Self> {
 | 
					 | 
				
			||||||
        &mut self.common
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl ShowAvatar {
 | 
					 | 
				
			||||||
    fn get_user_avatar(&mut self, ctx: &Context<Self>) {
 | 
					 | 
				
			||||||
        self.common.call_graphql::<GetUserAvatar, _>(
 | 
					 | 
				
			||||||
            ctx,
 | 
					 | 
				
			||||||
            get_user_avatar::Variables {
 | 
					 | 
				
			||||||
                id: ctx.props().username.clone(),
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            Msg::UserAvatarResponse,
 | 
					 | 
				
			||||||
            "Error trying to fetch user avatar",
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Component for ShowAvatar {
 | 
					 | 
				
			||||||
    type Message = Msg;
 | 
					 | 
				
			||||||
    type Properties = Props;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn create(ctx: &Context<Self>) -> Self {
 | 
					 | 
				
			||||||
        let mut avatar = Self {
 | 
					 | 
				
			||||||
            common: CommonComponentParts::<Self>::create(),
 | 
					 | 
				
			||||||
            avatar: None,
 | 
					 | 
				
			||||||
            _producer: AvatarEventBus::bridge(ctx.link().callback(Msg::Update)),
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        avatar.get_user_avatar(ctx);
 | 
					 | 
				
			||||||
        avatar
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
 | 
					 | 
				
			||||||
        CommonComponentParts::<Self>::update(self, ctx, msg)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn view(&self, ctx: &Context<Self>) -> Html {
 | 
					 | 
				
			||||||
        match &self.avatar {
 | 
					 | 
				
			||||||
        Some(avatar) => html! {
 | 
					        Some(avatar) => html! {
 | 
				
			||||||
            <img
 | 
					            <img
 | 
				
			||||||
                    class="avatar"
 | 
					                    class="avatar"
 | 
				
			||||||
                        src={format!("data:image/jpeg;base64, {}", avatar.0)}
 | 
					                    src={format!("data:image/jpeg;base64, {}", avatar)}
 | 
				
			||||||
                        style={format!("max-height:{}px;max-width:{}px;height:auto;width:auto;", ctx.props().height,ctx.props().width)}
 | 
					                    style={format!("max-height:{}px;max-width:{}px;height:auto;width:auto;", props.height, props.width)}
 | 
				
			||||||
                    alt="Avatar" />
 | 
					                    alt="Avatar" />
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        None => html! {
 | 
					        None => html! {
 | 
				
			||||||
            <svg xmlns="http://www.w3.org/2000/svg"
 | 
					            <svg xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
                      width={ctx.props().width.to_string()}
 | 
					                    width={props.width.to_string()}
 | 
				
			||||||
                      height={ctx.props().height.to_string()}
 | 
					                    height={props.height.to_string()}
 | 
				
			||||||
                    fill="currentColor"
 | 
					                    fill="currentColor"
 | 
				
			||||||
                    class="bi bi-person-circle"
 | 
					                    class="bi bi-person-circle"
 | 
				
			||||||
                    viewBox="0 0 16 16">
 | 
					                    viewBox="0 0 16 16">
 | 
				
			||||||
@ -130,4 +35,3 @@ impl Component for ShowAvatar {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										150
									
								
								app/src/components/avatar_cache.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								app/src/components/avatar_cache.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,150 @@
 | 
				
			|||||||
 | 
					use crate::infra::api::HostService;
 | 
				
			||||||
 | 
					use anyhow::Result;
 | 
				
			||||||
 | 
					use gloo_console::error;
 | 
				
			||||||
 | 
					use graphql_client::GraphQLQuery;
 | 
				
			||||||
 | 
					use std::{collections::HashMap, rc::Rc};
 | 
				
			||||||
 | 
					use yew::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(GraphQLQuery)]
 | 
				
			||||||
 | 
					#[graphql(
 | 
				
			||||||
 | 
					    schema_path = "../schema.graphql",
 | 
				
			||||||
 | 
					    query_path = "queries/get_user_avatar.graphql",
 | 
				
			||||||
 | 
					    response_derives = "Debug",
 | 
				
			||||||
 | 
					    custom_scalars_module = "crate::infra::graphql"
 | 
				
			||||||
 | 
					)]
 | 
				
			||||||
 | 
					pub struct GetUserAvatar;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(GraphQLQuery)]
 | 
				
			||||||
 | 
					#[graphql(
 | 
				
			||||||
 | 
					    schema_path = "../schema.graphql",
 | 
				
			||||||
 | 
					    query_path = "queries/list_users.graphql",
 | 
				
			||||||
 | 
					    response_derives = "Debug,Clone,PartialEq,Eq,Hash",
 | 
				
			||||||
 | 
					    variables_derives = "Clone",
 | 
				
			||||||
 | 
					    custom_scalars_module = "crate::infra::graphql"
 | 
				
			||||||
 | 
					)]
 | 
				
			||||||
 | 
					pub struct ListUserNames;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq, Clone)]
 | 
				
			||||||
 | 
					pub enum CacheAction {
 | 
				
			||||||
 | 
					    Clear,
 | 
				
			||||||
 | 
					    AddAvatar((String, Option<String>)),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq, Eq, Clone)]
 | 
				
			||||||
 | 
					pub struct AvatarCache {
 | 
				
			||||||
 | 
					    pub avatars: HashMap<String, Option<String>>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Reducible for AvatarCache {
 | 
				
			||||||
 | 
					    type Action = CacheAction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn reduce(self: Rc<Self>, action: Self::Action) -> Rc<Self> {
 | 
				
			||||||
 | 
					        match action {
 | 
				
			||||||
 | 
					            CacheAction::AddAvatar((username, avatar)) => {
 | 
				
			||||||
 | 
					                let mut avatars = self.avatars.clone();
 | 
				
			||||||
 | 
					                avatars.insert(username, avatar);
 | 
				
			||||||
 | 
					                AvatarCache { avatars }.into()
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            CacheAction::Clear => AvatarCache {
 | 
				
			||||||
 | 
					                avatars: HashMap::new(),
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            .into(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub type AvatarCacheContext = UseReducerHandle<AvatarCache>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq, Clone)]
 | 
				
			||||||
 | 
					pub enum CacheMode {
 | 
				
			||||||
 | 
					    AllUsers,
 | 
				
			||||||
 | 
					    SingleUser(String),
 | 
				
			||||||
 | 
					    None,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Properties, Debug, PartialEq)]
 | 
				
			||||||
 | 
					pub struct AvatarCacheProviderProps {
 | 
				
			||||||
 | 
					    #[prop_or_default]
 | 
				
			||||||
 | 
					    pub children: Children,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub mode: CacheMode,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[function_component(AvatarCacheProvider)]
 | 
				
			||||||
 | 
					pub fn avatar_cache_provider(props: &AvatarCacheProviderProps) -> Html {
 | 
				
			||||||
 | 
					    let cache = use_reducer(|| AvatarCache {
 | 
				
			||||||
 | 
					        avatars: HashMap::new(),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        let cache = cache.clone();
 | 
				
			||||||
 | 
					        let mode = props.mode.clone();
 | 
				
			||||||
 | 
					        use_effect_with_deps(
 | 
				
			||||||
 | 
					            move |mode| {
 | 
				
			||||||
 | 
					                match mode {
 | 
				
			||||||
 | 
					                    CacheMode::None => {
 | 
				
			||||||
 | 
					                        cache.dispatch(CacheAction::Clear)
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    CacheMode::AllUsers => {
 | 
				
			||||||
 | 
					                        let cache = cache.clone();
 | 
				
			||||||
 | 
					                        wasm_bindgen_futures::spawn_local(async move {
 | 
				
			||||||
 | 
					                            let result = fetch_all_avatars(cache).await;
 | 
				
			||||||
 | 
					                            if let Err(e) = result {
 | 
				
			||||||
 | 
					                                error!(&format!("Could not fetch all avatars: {e:#}"))
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        });
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    CacheMode::SingleUser(username) => {
 | 
				
			||||||
 | 
					                        let cache = cache.clone();
 | 
				
			||||||
 | 
					                        let username = username.clone();
 | 
				
			||||||
 | 
					                        wasm_bindgen_futures::spawn_local(async move {
 | 
				
			||||||
 | 
					                            let result = HostService::graphql_query::<GetUserAvatar>(
 | 
				
			||||||
 | 
					                                get_user_avatar::Variables { id: username },
 | 
				
			||||||
 | 
					                                "Error trying to fetch user avatar",
 | 
				
			||||||
 | 
					                            )
 | 
				
			||||||
 | 
					                            .await;
 | 
				
			||||||
 | 
					                            if let Ok(response) = result {
 | 
				
			||||||
 | 
					                                cache.dispatch(CacheAction::AddAvatar((
 | 
				
			||||||
 | 
					                                    response.user.id,
 | 
				
			||||||
 | 
					                                    response.user.avatar,
 | 
				
			||||||
 | 
					                                )))
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        });
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                move || cache.dispatch(CacheAction::Clear)
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            mode,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    html! {
 | 
				
			||||||
 | 
					        <ContextProvider<AvatarCacheContext> context={cache}>
 | 
				
			||||||
 | 
					            {props.children.clone()}
 | 
				
			||||||
 | 
					        </ContextProvider<AvatarCacheContext>>
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async fn fetch_all_avatars(cache: UseReducerHandle<AvatarCache>) -> Result<()> {
 | 
				
			||||||
 | 
					    let response = HostService::graphql_query::<ListUserNames>(
 | 
				
			||||||
 | 
					        list_user_names::Variables { filters: None },
 | 
				
			||||||
 | 
					        "Error trying to fetch user list",
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    .await?;
 | 
				
			||||||
 | 
					    for user in &response.users {
 | 
				
			||||||
 | 
					        let result = HostService::graphql_query::<GetUserAvatar>(
 | 
				
			||||||
 | 
					            get_user_avatar::Variables {
 | 
				
			||||||
 | 
					                id: user.id.clone(),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "Error trying to fetch user avatar",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .await;
 | 
				
			||||||
 | 
					        if let Ok(response) = result {
 | 
				
			||||||
 | 
					            cache.dispatch(CacheAction::AddAvatar((
 | 
				
			||||||
 | 
					                response.user.id,
 | 
				
			||||||
 | 
					                response.user.avatar,
 | 
				
			||||||
 | 
					            )));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return Ok(());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,55 +0,0 @@
 | 
				
			|||||||
use serde::{Deserialize, Serialize};
 | 
					 | 
				
			||||||
use std::collections::HashSet;
 | 
					 | 
				
			||||||
use yew_agent::{Agent, AgentLink, Context, HandlerId};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use super::avatar::AvatarData;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Serialize, Deserialize, Debug)]
 | 
					 | 
				
			||||||
pub enum Request {
 | 
					 | 
				
			||||||
    Update((String, Option<AvatarData>)),
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Serialize, Deserialize, Debug)]
 | 
					 | 
				
			||||||
pub enum Response {
 | 
					 | 
				
			||||||
    Update((String, Option<AvatarData>)),
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub struct AvatarEventBus {
 | 
					 | 
				
			||||||
    link: AgentLink<AvatarEventBus>,
 | 
					 | 
				
			||||||
    subscribers: HashSet<HandlerId>,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Agent for AvatarEventBus {
 | 
					 | 
				
			||||||
    type Reach = Context<Self>;
 | 
					 | 
				
			||||||
    type Message = ();
 | 
					 | 
				
			||||||
    type Input = Request;
 | 
					 | 
				
			||||||
    type Output = Response;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn create(link: AgentLink<Self>) -> Self {
 | 
					 | 
				
			||||||
        Self {
 | 
					 | 
				
			||||||
            link,
 | 
					 | 
				
			||||||
            subscribers: HashSet::new(),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn update(&mut self, _msg: Self::Message) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn handle_input(&mut self, msg: Self::Input, _id: HandlerId) {
 | 
					 | 
				
			||||||
        match msg {
 | 
					 | 
				
			||||||
            Request::Update((username, avatar)) => {
 | 
					 | 
				
			||||||
                for sub in self.subscribers.iter() {
 | 
					 | 
				
			||||||
                    self.link
 | 
					 | 
				
			||||||
                        .respond(*sub, Response::Update((username.clone(), avatar.clone())));
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn connected(&mut self, id: HandlerId) {
 | 
					 | 
				
			||||||
        self.subscribers.insert(id);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn disconnected(&mut self, id: HandlerId) {
 | 
					 | 
				
			||||||
        self.subscribers.remove(&id);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -2,7 +2,7 @@ pub mod add_group_member;
 | 
				
			|||||||
pub mod add_user_to_group;
 | 
					pub mod add_user_to_group;
 | 
				
			||||||
pub mod app;
 | 
					pub mod app;
 | 
				
			||||||
pub mod avatar;
 | 
					pub mod avatar;
 | 
				
			||||||
pub mod avatar_event_bus;
 | 
					pub mod avatar_cache;
 | 
				
			||||||
pub mod change_password;
 | 
					pub mod change_password;
 | 
				
			||||||
pub mod create_group;
 | 
					pub mod create_group;
 | 
				
			||||||
pub mod create_user;
 | 
					pub mod create_user;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,7 @@
 | 
				
			|||||||
use std::str::FromStr;
 | 
					use std::str::FromStr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    components::avatar::AvatarData,
 | 
					    components::avatar_cache::*,
 | 
				
			||||||
    components::avatar_event_bus::{AvatarEventBus, Request},
 | 
					 | 
				
			||||||
    components::user_details::User,
 | 
					    components::user_details::User,
 | 
				
			||||||
    infra::common_component::{CommonComponent, CommonComponentParts},
 | 
					    infra::common_component::{CommonComponent, CommonComponentParts},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -15,7 +14,7 @@ use graphql_client::GraphQLQuery;
 | 
				
			|||||||
use validator_derive::Validate;
 | 
					use validator_derive::Validate;
 | 
				
			||||||
use web_sys::{FileList, HtmlInputElement, InputEvent};
 | 
					use web_sys::{FileList, HtmlInputElement, InputEvent};
 | 
				
			||||||
use yew::prelude::*;
 | 
					use yew::prelude::*;
 | 
				
			||||||
use yew_agent::{Dispatched, Dispatcher};
 | 
					use yew::context::ContextHandle;
 | 
				
			||||||
use yew_form_derive::Model;
 | 
					use yew_form_derive::Model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Default)]
 | 
					#[derive(Default)]
 | 
				
			||||||
@ -75,7 +74,8 @@ pub struct UserDetailsForm {
 | 
				
			|||||||
    /// True if we just successfully updated the user, to display a success message.
 | 
					    /// True if we just successfully updated the user, to display a success message.
 | 
				
			||||||
    just_updated: bool,
 | 
					    just_updated: bool,
 | 
				
			||||||
    user: User,
 | 
					    user: User,
 | 
				
			||||||
    avatar_event_bus: Dispatcher<AvatarEventBus>,
 | 
					    avatar_cache: AvatarCacheContext,
 | 
				
			||||||
 | 
					    _context_handle: ContextHandle<AvatarCacheContext>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub enum Msg {
 | 
					pub enum Msg {
 | 
				
			||||||
@ -160,6 +160,10 @@ impl Component for UserDetailsForm {
 | 
				
			|||||||
            first_name: ctx.props().user.first_name.clone(),
 | 
					            first_name: ctx.props().user.first_name.clone(),
 | 
				
			||||||
            last_name: ctx.props().user.last_name.clone(),
 | 
					            last_name: ctx.props().user.last_name.clone(),
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					        let (avatar_cache, _context_handle) = ctx
 | 
				
			||||||
 | 
					            .link()
 | 
				
			||||||
 | 
					            .context(Callback::noop())
 | 
				
			||||||
 | 
					            .expect("No Message Context Provided");
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            common: CommonComponentParts::<Self>::create(),
 | 
					            common: CommonComponentParts::<Self>::create(),
 | 
				
			||||||
            form: yew_form::Form::new(model),
 | 
					            form: yew_form::Form::new(model),
 | 
				
			||||||
@ -167,7 +171,8 @@ impl Component for UserDetailsForm {
 | 
				
			|||||||
            just_updated: false,
 | 
					            just_updated: false,
 | 
				
			||||||
            reader: None,
 | 
					            reader: None,
 | 
				
			||||||
            user: ctx.props().user.clone(),
 | 
					            user: ctx.props().user.clone(),
 | 
				
			||||||
            avatar_event_bus: AvatarEventBus::dispatcher(),
 | 
					            avatar_cache,
 | 
				
			||||||
 | 
					            _context_handle,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -407,13 +412,7 @@ impl UserDetailsForm {
 | 
				
			|||||||
            self.user.avatar = Some(avatar);
 | 
					            self.user.avatar = Some(avatar);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        self.just_updated = true;
 | 
					        self.just_updated = true;
 | 
				
			||||||
        self.avatar_event_bus.send(Request::Update((
 | 
					        self.avatar_cache.dispatch(CacheAction::AddAvatar((self.user.id.clone(), self.user.avatar.clone())));
 | 
				
			||||||
            self.user.id.clone(),
 | 
					 | 
				
			||||||
            self.user
 | 
					 | 
				
			||||||
                .avatar
 | 
					 | 
				
			||||||
                .as_ref()
 | 
					 | 
				
			||||||
                .map(|data| AvatarData::new(data.clone())),
 | 
					 | 
				
			||||||
        )));
 | 
					 | 
				
			||||||
        Ok(true)
 | 
					        Ok(true)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user