Add upload image
This commit is contained in:
parent
c20cc9ebc5
commit
5b871a3332
562
Cargo.lock
generated
562
Cargo.lock
generated
@ -71,6 +71,26 @@ dependencies = [
|
||||
"futures 0.3.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-files"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "301482841d3d74483a446ead63cb7d362e187d2c8b603f13d91995621ea53c46"
|
||||
dependencies = [
|
||||
"actix-http",
|
||||
"actix-service",
|
||||
"actix-web",
|
||||
"bitflags",
|
||||
"bytes",
|
||||
"derive_more",
|
||||
"futures 0.3.4",
|
||||
"log 0.4.8",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"percent-encoding 2.1.0",
|
||||
"v_htmlescape",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-http"
|
||||
version = "1.0.1"
|
||||
@ -115,7 +135,7 @@ dependencies = [
|
||||
"serde_urlencoded",
|
||||
"sha1",
|
||||
"slab",
|
||||
"time",
|
||||
"time 0.1.42",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -143,7 +163,7 @@ dependencies = [
|
||||
"httparse",
|
||||
"log 0.4.8",
|
||||
"mime",
|
||||
"time",
|
||||
"time 0.1.42",
|
||||
"twoway",
|
||||
]
|
||||
|
||||
@ -298,7 +318,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"time",
|
||||
"time 0.1.42",
|
||||
"url 2.1.1",
|
||||
]
|
||||
|
||||
@ -378,6 +398,18 @@ version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d663a8e9a99154b5fb793032533f6328da35e23aac63d5c152279aa8ba356825"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
|
||||
|
||||
[[package]]
|
||||
name = "ascii_utils"
|
||||
version = "0.9.3"
|
||||
@ -463,6 +495,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base-x"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b20b618342cf9891c292c4f5ac2cde7287cc5c87e87e9c769d617793607dec1"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.9.3"
|
||||
@ -488,6 +526,12 @@ version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d5ca2cd0adc3f48f9e9ea5a6bbdf9ccc0bfade884847e484d452414c7ccffb3"
|
||||
|
||||
[[package]]
|
||||
name = "bigdecimal"
|
||||
version = "0.1.0"
|
||||
@ -515,6 +559,17 @@ version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "blake2b_simd"
|
||||
version = "0.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.7.3"
|
||||
@ -616,7 +671,7 @@ dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"time",
|
||||
"time 0.1.42",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -670,13 +725,19 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5"
|
||||
dependencies = [
|
||||
"time",
|
||||
"time 0.1.42",
|
||||
"url 1.7.2",
|
||||
]
|
||||
|
||||
@ -732,6 +793,16 @@ dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-mac"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dbg"
|
||||
version = "1.0.4"
|
||||
@ -771,7 +842,7 @@ dependencies = [
|
||||
"pq-sys",
|
||||
"r2d2",
|
||||
"serde_json",
|
||||
"time",
|
||||
"time 0.1.42",
|
||||
"uuid 0.6.5",
|
||||
"uuid 0.8.1",
|
||||
]
|
||||
@ -796,6 +867,34 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "discard"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
|
||||
|
||||
[[package]]
|
||||
name = "dotenv"
|
||||
version = "0.15.0"
|
||||
@ -825,7 +924,7 @@ dependencies = [
|
||||
"encoding",
|
||||
"lazy_static",
|
||||
"rand 0.4.6",
|
||||
"time",
|
||||
"time 0.1.42",
|
||||
"version_check 0.1.5",
|
||||
]
|
||||
|
||||
@ -1261,6 +1360,22 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695"
|
||||
dependencies = [
|
||||
"crypto-mac",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hostname"
|
||||
version = "0.1.5"
|
||||
@ -1293,6 +1408,16 @@ dependencies = [
|
||||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.3.4"
|
||||
@ -1308,6 +1433,43 @@ dependencies = [
|
||||
"quick-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.13.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96816e1d921eca64d208a85aab4f7798455a8e34229ee5a88c935bdee1b78b14"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"httparse",
|
||||
"itoa",
|
||||
"log 0.4.8",
|
||||
"net2",
|
||||
"pin-project",
|
||||
"time 0.1.42",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-tls"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3adcd308402b9553630734e9c36b77a7e48b3821251ca2493e8cd596763aafaa"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"hyper",
|
||||
"native-tls",
|
||||
"tokio",
|
||||
"tokio-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.1.5"
|
||||
@ -1425,6 +1587,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"actix",
|
||||
"actix-cors",
|
||||
"actix-files",
|
||||
"actix-multipart",
|
||||
"actix-rt",
|
||||
"actix-service",
|
||||
@ -1453,9 +1616,11 @@ dependencies = [
|
||||
"pretty_env_logger",
|
||||
"quickcheck",
|
||||
"r2d2",
|
||||
"rusoto_core",
|
||||
"rusoto_s3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"time",
|
||||
"time 0.1.42",
|
||||
"toml",
|
||||
"url 2.1.1",
|
||||
"uuid 0.8.1",
|
||||
@ -1545,7 +1710,7 @@ dependencies = [
|
||||
"email",
|
||||
"lettre",
|
||||
"mime",
|
||||
"time",
|
||||
"time 0.1.42",
|
||||
"uuid 0.7.4",
|
||||
]
|
||||
|
||||
@ -1621,6 +1786,12 @@ version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
||||
|
||||
[[package]]
|
||||
name = "md5"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "0.1.11"
|
||||
@ -1642,6 +1813,16 @@ version = "0.3.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
||||
|
||||
[[package]]
|
||||
name = "mime_guess"
|
||||
version = "2.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212"
|
||||
dependencies = [
|
||||
"mime",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.3.6"
|
||||
@ -1664,7 +1845,7 @@ dependencies = [
|
||||
"kernel32-sys",
|
||||
"libc",
|
||||
"log 0.4.8",
|
||||
"miow",
|
||||
"miow 0.2.1",
|
||||
"net2",
|
||||
"slab",
|
||||
"winapi 0.2.8",
|
||||
@ -1682,6 +1863,18 @@ dependencies = [
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio-named-pipes"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3"
|
||||
dependencies = [
|
||||
"log 0.4.8",
|
||||
"mio",
|
||||
"miow 0.3.3",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio-uds"
|
||||
version = "0.6.7"
|
||||
@ -1705,6 +1898,16 @@ dependencies = [
|
||||
"ws2_32-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226"
|
||||
dependencies = [
|
||||
"socket2",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.4"
|
||||
@ -2238,6 +2441,17 @@ version = "0.1.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"redox_syscall",
|
||||
"rust-argon2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "0.1.80"
|
||||
@ -2294,12 +2508,120 @@ dependencies = [
|
||||
"quick-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusoto_core"
|
||||
version = "0.43.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a8d624cb48fcaca612329e4dd544380aa329ef338e83d3a90f5b7897e631971"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64 0.12.0",
|
||||
"bytes",
|
||||
"futures 0.3.4",
|
||||
"hmac",
|
||||
"http",
|
||||
"hyper",
|
||||
"hyper-tls",
|
||||
"lazy_static",
|
||||
"log 0.4.8",
|
||||
"md5",
|
||||
"percent-encoding 2.1.0",
|
||||
"pin-project",
|
||||
"rusoto_credential",
|
||||
"rusoto_signature",
|
||||
"rustc_version",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"tokio",
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusoto_credential"
|
||||
version = "0.43.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba3e7cdf483d7198d9bca7414746d3ba656239e89e467b715d0571912f0b492f"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
"dirs",
|
||||
"futures 0.3.4",
|
||||
"hyper",
|
||||
"pin-project",
|
||||
"regex 1.3.6",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"shlex",
|
||||
"tokio",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusoto_s3"
|
||||
version = "0.43.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b6bc3221ae5a2c036d5757eee68a2ffb6b7f87b8a83adbf4271c8133fdee01c"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"futures 0.3.4",
|
||||
"rusoto_core",
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusoto_signature"
|
||||
version = "0.43.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62940a2bd479900a1bf8935b8f254d3e19368ac3ac4570eb4bd48eb46551a1b7"
|
||||
dependencies = [
|
||||
"base64 0.12.0",
|
||||
"bytes",
|
||||
"futures 0.3.4",
|
||||
"hex",
|
||||
"hmac",
|
||||
"http",
|
||||
"hyper",
|
||||
"log 0.4.8",
|
||||
"md5",
|
||||
"percent-encoding 2.1.0",
|
||||
"pin-project",
|
||||
"rusoto_credential",
|
||||
"rustc_version",
|
||||
"serde",
|
||||
"sha2",
|
||||
"time 0.2.15",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-argon2"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017"
|
||||
dependencies = [
|
||||
"base64 0.11.0",
|
||||
"blake2b_simd",
|
||||
"constant_time_eq",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.3"
|
||||
@ -2398,6 +2720,21 @@ dependencies = [
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.105"
|
||||
@ -2459,6 +2796,24 @@ version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"digest",
|
||||
"fake-simd",
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.2.0"
|
||||
@ -2493,12 +2848,73 @@ dependencies = [
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "standback"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47e4b8c631c998468961a9ea159f064c5c8499b95b5e4a34b77849d45949d540"
|
||||
|
||||
[[package]]
|
||||
name = "stdweb"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
|
||||
dependencies = [
|
||||
"discard",
|
||||
"rustc_version",
|
||||
"stdweb-derive",
|
||||
"stdweb-internal-macros",
|
||||
"stdweb-internal-runtime",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stdweb-derive"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stdweb-internal-macros"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
|
||||
dependencies = [
|
||||
"base-x",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"sha1",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stdweb-internal-runtime"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.17"
|
||||
@ -2602,6 +3018,44 @@ dependencies = [
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1330829d2e6c06771eeae476be12ff1aa9eb5e29ca718a431ab27168efde6c1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"standback",
|
||||
"stdweb",
|
||||
"time-macros",
|
||||
"version_check 0.9.1",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ae9b6e9f095bc105e183e3cd493d72579be3181ad4004fceb01adbe9eecab2d"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"time-macros-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-macros-impl"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"standback",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "0.2.13"
|
||||
@ -2616,13 +3070,36 @@ dependencies = [
|
||||
"libc",
|
||||
"memchr 2.3.3",
|
||||
"mio",
|
||||
"mio-named-pipes",
|
||||
"mio-uds",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"slab",
|
||||
"tokio-macros",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-tls"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bde02a3a5291395f59b06ec6945a3077602fac2b07eeeaf0dee2122f3619828"
|
||||
dependencies = [
|
||||
"native-tls",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.2.0"
|
||||
@ -2646,6 +3123,12 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860"
|
||||
|
||||
[[package]]
|
||||
name = "trust-dns-proto"
|
||||
version = "0.18.0-alpha.2"
|
||||
@ -2685,6 +3168,12 @@ dependencies = [
|
||||
"trust-dns-proto",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "try-lock"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382"
|
||||
|
||||
[[package]]
|
||||
name = "twoway"
|
||||
version = "0.2.1"
|
||||
@ -2827,6 +3316,37 @@ dependencies = [
|
||||
"sha1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "v_escape"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "660b101c07b5d0863deb9e7fb3138777e858d6d2a79f9e6049a27d1cc77c6da6"
|
||||
dependencies = [
|
||||
"v_escape_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "v_escape_derive"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae"
|
||||
dependencies = [
|
||||
"nom",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "v_htmlescape"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e33e939c0d8cf047514fb6ba7d5aac78bc56677a6938b2ee67000b91f2e97e41"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"v_escape",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.8"
|
||||
@ -2862,6 +3382,16 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
|
||||
dependencies = [
|
||||
"log 0.4.8",
|
||||
"try-lock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
@ -3046,3 +3576,15 @@ dependencies = [
|
||||
"winapi 0.2.8",
|
||||
"winapi-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xml-rs"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a"
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3cbac2ed2ba24cc90f5e06485ac8c7c1e5449fe8911aef4d8877218af021a5b8"
|
||||
|
@ -50,6 +50,11 @@ features = [
|
||||
"BinaryType",
|
||||
"Blob",
|
||||
"AddEventListenerOptions",
|
||||
"File",
|
||||
"FileList",
|
||||
"FormData",
|
||||
"FileReader",
|
||||
"FileReaderSync",
|
||||
# events
|
||||
"EventTarget",
|
||||
"ErrorEvent",
|
||||
|
14
jirs-client/js/css/styledImageInput.css
Normal file
14
jirs-client/js/css/styledImageInput.css
Normal file
@ -0,0 +1,14 @@
|
||||
.styledImageInput {
|
||||
}
|
||||
|
||||
.styledImageInput > .label > .mask {
|
||||
display: block;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
margin: 0 auto;
|
||||
border-radius: 60px;
|
||||
}
|
||||
|
||||
.styledImageInput > .input {
|
||||
display: none;
|
||||
}
|
@ -13,6 +13,7 @@
|
||||
@import "./css/styledSelectChild.css";
|
||||
@import "./css/styledButton.css";
|
||||
@import "./css/styledInput.css";
|
||||
@import "./css/styledImageInput.css";
|
||||
@import "./css/styledModal.css";
|
||||
@import "./css/styledTextArea.css";
|
||||
@import "./css/styledForm.css";
|
||||
|
@ -1,6 +1,7 @@
|
||||
use std::sync::RwLock;
|
||||
|
||||
use seed::{prelude::*, *};
|
||||
use web_sys::File;
|
||||
|
||||
use jirs_data::*;
|
||||
|
||||
@ -128,11 +129,13 @@ impl std::fmt::Display for FieldId {
|
||||
UsersFieldId::Username => f.write_str("users-username"),
|
||||
UsersFieldId::Email => f.write_str("users-email"),
|
||||
UsersFieldId::UserRole => f.write_str("users-userRole"),
|
||||
UsersFieldId::Avatar => f.write_str("users-avatar"),
|
||||
},
|
||||
FieldId::Profile(sub) => match sub {
|
||||
UsersFieldId::Username => f.write_str("profile-username"),
|
||||
UsersFieldId::Email => f.write_str("profile-email"),
|
||||
UsersFieldId::UserRole => f.write_str("profile-userRole"),
|
||||
UsersFieldId::Avatar => f.write_str("profile-avatar"),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -169,7 +172,7 @@ pub enum PageChanged {
|
||||
Profile(ProfilePageChange),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Msg {
|
||||
NoOp,
|
||||
GlobalKeyDown {
|
||||
@ -179,6 +182,11 @@ pub enum Msg {
|
||||
alt: bool,
|
||||
},
|
||||
PageChanged(PageChanged),
|
||||
ChangePage(model::Page),
|
||||
|
||||
StyledSelectChanged(FieldId, StyledSelectChange),
|
||||
InternalFailure(String),
|
||||
ToggleAboutTooltip,
|
||||
|
||||
// Auth Token
|
||||
AuthTokenStored,
|
||||
@ -195,12 +203,6 @@ pub enum Msg {
|
||||
// sign up
|
||||
SignUpRequest,
|
||||
|
||||
StyledSelectChanged(FieldId, StyledSelectChange),
|
||||
|
||||
ChangePage(model::Page),
|
||||
InternalFailure(String),
|
||||
ToggleAboutTooltip,
|
||||
|
||||
// project
|
||||
ProjectAvatarFilterChanged(UserId, AvatarFilterActive),
|
||||
ProjectToggleOnlyMy,
|
||||
@ -219,6 +221,7 @@ pub enum Msg {
|
||||
// inputs
|
||||
StrInputChanged(FieldId, String),
|
||||
U32InputChanged(FieldId, u32),
|
||||
FileInputChanged(FieldId, Vec<File>),
|
||||
|
||||
// issues
|
||||
AddIssue,
|
||||
@ -228,6 +231,9 @@ pub enum Msg {
|
||||
SaveComment,
|
||||
DeleteComment(CommentId),
|
||||
|
||||
// profile
|
||||
AvatarUpdateFetched(seed::fetch::FetchObject<String>),
|
||||
|
||||
// modals
|
||||
ModalOpened(Box<ModalType>),
|
||||
ModalDropped,
|
||||
@ -237,9 +243,10 @@ pub enum Msg {
|
||||
}
|
||||
|
||||
fn update(msg: Msg, model: &mut model::Model, orders: &mut impl Orders<Msg>) {
|
||||
if msg == Msg::NoOp {
|
||||
return;
|
||||
}
|
||||
match msg {
|
||||
Msg::NoOp => return,
|
||||
_ => (),
|
||||
};
|
||||
if cfg!(debug_assertions) {
|
||||
log!(msg);
|
||||
}
|
||||
|
@ -8,10 +8,10 @@ use crate::shared::styled_field::StyledField;
|
||||
use crate::shared::styled_input::{StyledInput, StyledInputState};
|
||||
use crate::shared::styled_modal::StyledModal;
|
||||
use crate::shared::styled_select::{StyledSelect, StyledSelectState};
|
||||
use crate::shared::styled_select_child::*;
|
||||
use crate::shared::tracking_widget::{fibonacci_values, tracking_widget};
|
||||
use crate::shared::{find_issue, ToChild, ToNode};
|
||||
use crate::{EditIssueModalSection, FieldId, Msg};
|
||||
// use crate::shared::styled_select_child::*;
|
||||
use crate::shared::tracking_widget::{fibonacci_values, tracking_widget};
|
||||
|
||||
pub fn value_for_time_tracking(v: &Option<i32>, time_tracking_type: &TimeTracking) -> String {
|
||||
match (time_tracking_type, v.as_ref()) {
|
||||
|
@ -8,6 +8,7 @@ use jirs_data::*;
|
||||
use crate::modal::time_tracking::value_for_time_tracking;
|
||||
use crate::shared::styled_checkbox::StyledCheckboxState;
|
||||
use crate::shared::styled_editor::Mode;
|
||||
use crate::shared::styled_image_input::StyledImageInputState;
|
||||
use crate::shared::styled_input::StyledInputState;
|
||||
use crate::shared::styled_select::StyledSelectState;
|
||||
use crate::{EditIssueModalSection, FieldId, ProjectFieldId, HOST_URL};
|
||||
@ -364,6 +365,7 @@ impl Default for UsersPage {
|
||||
pub struct ProfilePage {
|
||||
pub name: StyledInputState,
|
||||
pub email: StyledInputState,
|
||||
pub avatar: StyledImageInputState,
|
||||
}
|
||||
|
||||
impl ProfilePage {
|
||||
@ -377,6 +379,10 @@ impl ProfilePage {
|
||||
FieldId::Profile(UsersFieldId::Email),
|
||||
user.email.as_str(),
|
||||
),
|
||||
avatar: StyledImageInputState::new(
|
||||
FieldId::Profile(UsersFieldId::Avatar),
|
||||
user.avatar_url.as_ref().cloned(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use seed::{prelude::*, *};
|
||||
use web_sys::FormData;
|
||||
|
||||
use jirs_data::*;
|
||||
|
||||
@ -6,11 +7,12 @@ use crate::api::send_ws_msg;
|
||||
use crate::model::{Model, Page, PageContent, ProfilePage};
|
||||
use crate::shared::styled_field::StyledField;
|
||||
use crate::shared::styled_form::StyledForm;
|
||||
use crate::shared::styled_image_input::StyledImageInput;
|
||||
use crate::shared::styled_input::StyledInput;
|
||||
use crate::shared::{inner_layout, ToNode};
|
||||
use crate::{FieldId, Msg};
|
||||
use crate::{FieldId, Msg, HOST_URL};
|
||||
|
||||
pub fn update(msg: Msg, model: &mut crate::model::Model, _orders: &mut impl Orders<Msg>) {
|
||||
pub fn update(msg: Msg, model: &mut crate::model::Model, orders: &mut impl Orders<Msg>) {
|
||||
let user = match model.user {
|
||||
Some(ref user) => user,
|
||||
_ => return,
|
||||
@ -31,6 +33,27 @@ pub fn update(msg: Msg, model: &mut crate::model::Model, _orders: &mut impl Orde
|
||||
|
||||
project_page.name.update(&msg);
|
||||
project_page.email.update(&msg);
|
||||
project_page.avatar.update(&msg);
|
||||
|
||||
match msg {
|
||||
Msg::FileInputChanged(FieldId::Profile(UsersFieldId::Avatar), ..) => {
|
||||
let file = match project_page.avatar.file.as_ref() {
|
||||
Some(f) => f,
|
||||
_ => return,
|
||||
};
|
||||
let token = match crate::shared::read_auth_token() {
|
||||
Ok(uuid) => uuid,
|
||||
_ => return,
|
||||
};
|
||||
let fd = FormData::new().unwrap();
|
||||
fd.set_with_str("token", format!("{}", token).as_str())
|
||||
.unwrap();
|
||||
fd.set_with_blob("avatar", file).unwrap();
|
||||
orders.perform_cmd(update_avatar(fd));
|
||||
orders.skip();
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn view(model: &Model) -> Node<Msg> {
|
||||
@ -39,6 +62,12 @@ pub fn view(model: &Model) -> Node<Msg> {
|
||||
_ => return empty![],
|
||||
};
|
||||
|
||||
let avatar = StyledImageInput::build(FieldId::Profile(UsersFieldId::Avatar))
|
||||
.add_class("avatar")
|
||||
.state(&page.avatar)
|
||||
.build()
|
||||
.into_node();
|
||||
|
||||
let username = StyledInput::build(FieldId::Profile(UsersFieldId::Username))
|
||||
.state(&page.name)
|
||||
.valid(true)
|
||||
@ -65,9 +94,20 @@ pub fn view(model: &Model) -> Node<Msg> {
|
||||
|
||||
let content = StyledForm::build()
|
||||
.heading("Profile")
|
||||
.add_field(avatar)
|
||||
.add_field(username_field)
|
||||
.add_field(email_field)
|
||||
.build()
|
||||
.into_node();
|
||||
inner_layout(model, "profile", vec![content], empty![])
|
||||
}
|
||||
|
||||
async fn update_avatar(data: FormData) -> Result<Msg, Msg> {
|
||||
let host_url = unsafe { HOST_URL.clone() };
|
||||
let path = format!("{}/avatar/", host_url);
|
||||
Request::new(path)
|
||||
.method(Method::Post)
|
||||
.body(data.into())
|
||||
.fetch_string(Msg::AvatarUpdateFetched)
|
||||
.await
|
||||
}
|
||||
|
@ -14,9 +14,9 @@ pub mod styled_checkbox;
|
||||
pub mod styled_confirm_modal;
|
||||
pub mod styled_editor;
|
||||
pub mod styled_field;
|
||||
pub mod styled_file_input;
|
||||
pub mod styled_form;
|
||||
pub mod styled_icon;
|
||||
pub mod styled_image_input;
|
||||
pub mod styled_input;
|
||||
pub mod styled_link;
|
||||
pub mod styled_modal;
|
||||
|
127
jirs-client/src/shared/styled_image_input.rs
Normal file
127
jirs-client/src/shared/styled_image_input.rs
Normal file
@ -0,0 +1,127 @@
|
||||
use seed::{prelude::*, *};
|
||||
use web_sys::File;
|
||||
|
||||
use crate::shared::ToNode;
|
||||
use crate::{FieldId, Msg};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct StyledImageInputState {
|
||||
field_id: FieldId,
|
||||
pub file: Option<File>,
|
||||
pub url: Option<String>,
|
||||
}
|
||||
|
||||
impl StyledImageInputState {
|
||||
pub fn new(field_id: FieldId, url: Option<String>) -> Self {
|
||||
Self {
|
||||
field_id,
|
||||
file: None,
|
||||
url,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, msg: &Msg) {
|
||||
match msg {
|
||||
Msg::FileInputChanged(field_id, files) if field_id == &self.field_id => {
|
||||
self.file = files.get(0).cloned();
|
||||
}
|
||||
_ => return,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StyledImageInput {
|
||||
id: FieldId,
|
||||
class_list: Vec<String>,
|
||||
url: Option<String>,
|
||||
}
|
||||
|
||||
impl StyledImageInput {
|
||||
pub fn build(field_id: FieldId) -> StyledInputInputBuilder {
|
||||
StyledInputInputBuilder {
|
||||
id: field_id,
|
||||
class_list: vec![],
|
||||
url: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToNode for StyledImageInput {
|
||||
fn into_node(self) -> Node<Msg> {
|
||||
render(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StyledInputInputBuilder {
|
||||
id: FieldId,
|
||||
class_list: Vec<String>,
|
||||
url: Option<String>,
|
||||
}
|
||||
|
||||
impl StyledInputInputBuilder {
|
||||
pub fn add_class<S>(mut self, name: S) -> Self
|
||||
where
|
||||
S: Into<String>,
|
||||
{
|
||||
self.class_list.push(name.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn state(mut self, state: &StyledImageInputState) -> Self {
|
||||
self.url = state.url.as_ref().cloned();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> StyledImageInput {
|
||||
StyledImageInput {
|
||||
id: self.id,
|
||||
class_list: self.class_list,
|
||||
url: self.url,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render(values: StyledImageInput) -> Node<Msg> {
|
||||
let StyledImageInput {
|
||||
id,
|
||||
class_list,
|
||||
url,
|
||||
} = values;
|
||||
|
||||
let field_id = id.clone();
|
||||
let on_change = ev(Ev::Change, move |ev| {
|
||||
let target = ev.target().unwrap();
|
||||
let input = seed::to_input(&target);
|
||||
let v = input
|
||||
.files()
|
||||
.map(|list| {
|
||||
let mut v = vec![];
|
||||
for i in 0..list.length() {
|
||||
v.push(list.get(i).unwrap());
|
||||
}
|
||||
v
|
||||
})
|
||||
.unwrap_or_default();
|
||||
Msg::FileInputChanged(field_id, v)
|
||||
});
|
||||
let input_id = id.to_string();
|
||||
|
||||
div![
|
||||
class!["styledImageInput"],
|
||||
attrs![At::Class => class_list.join(" ")],
|
||||
label![
|
||||
class!["label"],
|
||||
attrs![At::For => input_id],
|
||||
img![
|
||||
class!["mask"],
|
||||
attrs![At::Src => url.unwrap_or_default()],
|
||||
" "
|
||||
]
|
||||
],
|
||||
input![
|
||||
class!["input"],
|
||||
attrs![At::Type => "file", At::Id => input_id],
|
||||
on_change
|
||||
]
|
||||
]
|
||||
}
|
@ -22,10 +22,13 @@ pub fn update(msg: Msg, model: &mut model::Model, orders: &mut impl Orders<Msg>)
|
||||
return;
|
||||
}
|
||||
|
||||
if msg == Msg::ChangePage(Page::SignIn) {
|
||||
model.page_content = PageContent::SignIn(Box::new(SignInPage::default()));
|
||||
return;
|
||||
}
|
||||
match msg {
|
||||
Msg::ChangePage(Page::SignIn) => {
|
||||
model.page_content = PageContent::SignIn(Box::new(SignInPage::default()));
|
||||
return;
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
let page = match &mut model.page_content {
|
||||
PageContent::SignIn(page) => page,
|
||||
|
@ -19,10 +19,13 @@ pub fn update(msg: Msg, model: &mut model::Model, _orders: &mut impl Orders<Msg>
|
||||
return;
|
||||
}
|
||||
|
||||
if msg == Msg::ChangePage(Page::SignUp) {
|
||||
model.page_content = PageContent::SignUp(Box::new(SignUpPage::default()));
|
||||
return;
|
||||
}
|
||||
match msg {
|
||||
Msg::ChangePage(Page::SignUp) => {
|
||||
model.page_content = PageContent::SignUp(Box::new(SignUpPage::default()));
|
||||
return;
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
let page = match &mut model.page_content {
|
||||
PageContent::SignUp(page) => page,
|
||||
|
@ -673,6 +673,7 @@ pub enum UsersFieldId {
|
||||
Username,
|
||||
Email,
|
||||
UserRole,
|
||||
Avatar,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialOrd, PartialEq, Hash)]
|
||||
|
@ -21,6 +21,7 @@ actix-service = { version = "*" }
|
||||
actix-rt = "1"
|
||||
actix-web-actors = "*"
|
||||
actix-multipart = { version = "*" }
|
||||
actix-files = { version = "0.2.1" }
|
||||
|
||||
dotenv = { version = "*" }
|
||||
byteorder = "1.0"
|
||||
@ -29,7 +30,7 @@ libc = { version = "0.2.0" }
|
||||
pq-sys = { version = ">=0.3.0, <0.5.0" }
|
||||
quickcheck = { version = "0.4" }
|
||||
serde_json = { version = ">=0.8.0, <2.0" }
|
||||
toml = "0.5"
|
||||
toml = "0.5.6"
|
||||
bincode = "1.2.1"
|
||||
time = { version = "0.1" }
|
||||
url = { version = "2.1.0" }
|
||||
@ -49,6 +50,10 @@ futures = { version = "*" }
|
||||
lettre = { version = "*" }
|
||||
lettre_email = { version = "*" }
|
||||
|
||||
# Amazon S3
|
||||
rusoto_s3 = "0.43.0"
|
||||
rusoto_core = "0.43.0"
|
||||
|
||||
[dependencies.diesel]
|
||||
version = "1.4.4"
|
||||
features = [ "unstable", "postgres", "numeric", "extras", "uuidv07" ]
|
||||
|
@ -7,6 +7,7 @@ extern crate log;
|
||||
|
||||
use actix::Actor;
|
||||
use actix_cors::Cors;
|
||||
use actix_files as fs;
|
||||
use actix_web::{App, HttpServer};
|
||||
|
||||
use crate::ws::WsServer;
|
||||
@ -40,7 +41,8 @@ async fn main() -> Result<(), String> {
|
||||
let ws_server = WsServer::default().start();
|
||||
|
||||
HttpServer::new(move || {
|
||||
App::new()
|
||||
let web_config = web::Configuration::read();
|
||||
let mut app = App::new()
|
||||
.wrap(actix_web::middleware::Logger::default())
|
||||
.wrap(Cors::default())
|
||||
.data(ws_server.clone())
|
||||
@ -48,6 +50,14 @@ async fn main() -> Result<(), String> {
|
||||
.data(mail_addr.clone())
|
||||
.data(crate::db::build_pool())
|
||||
.service(crate::ws::index)
|
||||
.service(actix_web::web::scope("/avatar").service(crate::web::avatar::upload));
|
||||
if let Some(file_system) = web_config.filesystem.as_ref() {
|
||||
app = app.service(fs::Files::new(
|
||||
file_system.client_path.as_str(),
|
||||
file_system.store_path.as_str(),
|
||||
));
|
||||
}
|
||||
app
|
||||
})
|
||||
.workers(web_config.concurrency)
|
||||
.bind(web_config.addr())
|
||||
|
@ -1,28 +1,67 @@
|
||||
use actix_multipart::Multipart;
|
||||
use actix_web::{get, post, web, Error, HttpResponse, Responder};
|
||||
use futures::{StreamExt, TryStreamExt};
|
||||
use std::io::Write;
|
||||
|
||||
use actix::Addr;
|
||||
use actix_multipart::{Field, Multipart};
|
||||
use actix_web::http::header::ContentDisposition;
|
||||
use actix_web::web::Data;
|
||||
use actix_web::{get, post, web, Error, HttpResponse, Responder};
|
||||
use futures::{StreamExt, TryStreamExt};
|
||||
|
||||
use crate::db::DbExecutor;
|
||||
|
||||
#[post("/")]
|
||||
async fn upload(mut payload: Multipart) -> Result<HttpResponse, Error> {
|
||||
while let Ok(Some(mut field)) = payload.try_next().await {
|
||||
let content_type = field.content_disposition().unwrap();
|
||||
let filename = content_type.get_filename().unwrap();
|
||||
let filepath = format!("./tmp/{}", filename);
|
||||
// File::create is blocking operation, use threadpool
|
||||
let mut f = web::block(|| std::fs::File::create(filepath))
|
||||
.await
|
||||
.unwrap();
|
||||
// Field in turn is stream of *Bytes* object
|
||||
while let Some(chunk) = field.next().await {
|
||||
let data = chunk.unwrap();
|
||||
// filesystem operations are blocking, we have to use threadpool
|
||||
f = web::block(move || f.write_all(&data).map(|_| f)).await?;
|
||||
pub async fn upload(
|
||||
mut payload: Multipart,
|
||||
db: Data<Addr<DbExecutor>>,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
while let Ok(Some(field)) = payload.try_next().await {
|
||||
let disposition: ContentDisposition = match field.content_disposition() {
|
||||
Some(d) => d,
|
||||
_ => continue,
|
||||
};
|
||||
if !disposition.is_form_data() {
|
||||
return Ok(HttpResponse::BadRequest().finish());
|
||||
}
|
||||
let _name = disposition.get_name().as_ref().cloned().unwrap_or_default();
|
||||
match disposition.get_name() {
|
||||
Some("token") => handle_token(field, disposition, db.clone()).await?,
|
||||
Some("avatar") => handle_image(field, disposition, db.clone()).await?,
|
||||
_ => continue,
|
||||
};
|
||||
}
|
||||
Ok(HttpResponse::Ok().json(""))
|
||||
}
|
||||
|
||||
async fn handle_token(
|
||||
mut field: Field,
|
||||
_disposition: ContentDisposition,
|
||||
_db: Data<Addr<DbExecutor>>,
|
||||
) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_image(
|
||||
mut field: Field,
|
||||
disposition: ContentDisposition,
|
||||
_db: Data<Addr<DbExecutor>>,
|
||||
) -> Result<(), Error> {
|
||||
let web_config = crate::web::Configuration::read();
|
||||
|
||||
let filename = disposition.get_filename().unwrap();
|
||||
let filepath = format!("./tmp/{}", filename);
|
||||
// File::create is blocking operation, use threadpool
|
||||
let mut f = web::block(|| std::fs::File::create(filepath))
|
||||
.await
|
||||
.unwrap();
|
||||
// Field in turn is stream of *Bytes* object
|
||||
while let Some(chunk) = field.next().await {
|
||||
let data = chunk.unwrap();
|
||||
// filesystem operations are blocking, we have to use thread pool
|
||||
f = web::block(move || f.write_all(&data).map(|_| f)).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[get("/{id}")]
|
||||
async fn download(_id: web::Path<i32>) -> impl Responder {
|
||||
HttpResponse::Ok().json("")
|
||||
|
@ -40,12 +40,35 @@ pub enum Protocol {
|
||||
Https,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct FileSystemStorage {
|
||||
pub store_path: String,
|
||||
pub client_path: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct AmazonS3Storage {
|
||||
pub access_key_id: String,
|
||||
pub secret_access_key: String,
|
||||
pub bucket: String,
|
||||
pub region: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub enum Storage {
|
||||
FileSystem,
|
||||
AmazonS3,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Configuration {
|
||||
pub concurrency: usize,
|
||||
pub port: String,
|
||||
pub bind: String,
|
||||
pub ssl: bool,
|
||||
pub storage: Storage,
|
||||
pub filesystem: Option<FileSystemStorage>,
|
||||
pub s3: Option<AmazonS3Storage>,
|
||||
}
|
||||
|
||||
impl Default for Configuration {
|
||||
@ -55,6 +78,12 @@ impl Default for Configuration {
|
||||
port: "5000".to_string(),
|
||||
bind: "0.0.0.0".to_string(),
|
||||
ssl: false,
|
||||
storage: Storage::FileSystem,
|
||||
filesystem: Some(FileSystemStorage {
|
||||
store_path: "./tmp".to_string(),
|
||||
client_path: "/img".to_string(),
|
||||
}),
|
||||
s3: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
0
tmp/.gitkeep
Normal file
0
tmp/.gitkeep
Normal file
Loading…
Reference in New Issue
Block a user