Start wasm

This commit is contained in:
Adrian Wozniak 2020-03-30 08:16:26 +02:00
parent 488425ce75
commit 2583bd1b9e
17 changed files with 445 additions and 280 deletions

379
Cargo.lock generated
View File

@ -106,7 +106,7 @@ dependencies = [
"lazy_static",
"log 0.4.8",
"mime",
"percent-encoding",
"percent-encoding 2.1.0",
"pin-project",
"rand 0.7.3",
"regex 1.3.6",
@ -280,7 +280,7 @@ dependencies = [
"serde_json",
"serde_urlencoded",
"time",
"url",
"url 2.1.1",
]
[[package]]
@ -329,18 +329,6 @@ dependencies = [
"memchr 2.3.3",
]
[[package]]
name = "anyhow"
version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "013a6e0a2cbe3d20f9c60b65458f7a7f7a5e636c5d0f45a5a6aee5d4b1f01785"
[[package]]
name = "anymap"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344"
[[package]]
name = "arc-swap"
version = "0.4.5"
@ -391,7 +379,7 @@ dependencies = [
"futures-core",
"log 0.4.8",
"mime",
"percent-encoding",
"percent-encoding 2.1.0",
"rand 0.7.3",
"serde",
"serde_json",
@ -420,12 +408,6 @@ 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.11.0"
@ -443,28 +425,12 @@ dependencies = [
"num-traits",
]
[[package]]
name = "bincode"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf"
dependencies = [
"byteorder",
"serde",
]
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "boolinator"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9"
[[package]]
name = "brotli-sys"
version = "0.3.2"
@ -524,12 +490,6 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-match"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8100e46ff92eb85bf6dc2930c73f2a4f7176393c84a9446b3d501e1b354e7b34"
[[package]]
name = "chrono"
version = "0.4.11"
@ -551,6 +511,26 @@ dependencies = [
"bitflags",
]
[[package]]
name = "console_error_panic_hook"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211"
dependencies = [
"cfg-if",
"wasm-bindgen",
]
[[package]]
name = "cookie"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5"
dependencies = [
"time",
"url 1.7.2",
]
[[package]]
name = "copyless"
version = "0.1.4"
@ -587,6 +567,15 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "dbg"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4677188513e0e9d7adced5997cf9a1e7a3c996c994f90093325c5332c1a8b221"
dependencies = [
"version_check 0.1.5",
]
[[package]]
name = "derive_more"
version = "0.99.3"
@ -633,12 +622,6 @@ dependencies = [
"syn",
]
[[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"
@ -657,6 +640,12 @@ version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
[[package]]
name = "enclose"
version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1056f553da426e9c025a662efa48b52e62e0a3a7648aa2d15aeaaf7f0d329357"
[[package]]
name = "encoding_rs"
version = "0.8.22"
@ -863,6 +852,15 @@ dependencies = [
"byteorder",
]
[[package]]
name = "getopts"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
dependencies = [
"unicode-width",
]
[[package]]
name = "getrandom"
version = "0.1.14"
@ -874,6 +872,17 @@ dependencies = [
"wasi",
]
[[package]]
name = "gloo-timers"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f"
dependencies = [
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "h2"
version = "0.2.2"
@ -948,6 +957,17 @@ dependencies = [
"quick-error",
]
[[package]]
name = "idna"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
dependencies = [
"matches",
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "idna"
version = "0.2.0"
@ -1012,7 +1032,15 @@ version = "0.1.0"
name = "jirs-client"
version = "0.1.0"
dependencies = [
"yew",
"chrono",
"jirs-data",
"js-sys",
"seed",
"serde",
"serde_json",
"uuid 0.8.1",
"wasm-bindgen",
"web-sys",
]
[[package]]
@ -1048,17 +1076,26 @@ dependencies = [
"num-bigint",
"num-integer",
"num-traits",
"percent-encoding",
"percent-encoding 2.1.0",
"pq-sys",
"quickcheck",
"r2d2",
"serde",
"serde_json",
"time",
"url",
"url 2.1.1",
"uuid 0.8.1",
]
[[package]]
name = "js-sys"
version = "0.3.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
@ -1294,6 +1331,12 @@ dependencies = [
"winapi 0.3.8",
]
[[package]]
name = "percent-encoding"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
[[package]]
name = "percent-encoding"
version = "2.1.0"
@ -1368,6 +1411,18 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "pulldown-cmark"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c205cc82214f3594e2d50686730314f817c67ffa80fe800cf0db78c3c2b9d9e"
dependencies = [
"bitflags",
"getopts",
"memchr 2.3.3",
"unicase",
]
[[package]]
name = "quick-error"
version = "1.2.3"
@ -1552,15 +1607,6 @@ 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"
@ -1583,20 +1629,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "semver"
version = "0.9.0"
name = "seed"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
checksum = "cd5d8fd7f12f565f639caf4b6d74a3853d5d7234d0543ec3beae81311492623e"
dependencies = [
"semver-parser",
"console_error_panic_hook",
"cookie",
"dbg",
"enclose",
"futures",
"gloo-timers",
"indexmap",
"js-sys",
"pulldown-cmark",
"serde",
"serde_json",
"version_check 0.9.1",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[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"
@ -1637,7 +1691,7 @@ dependencies = [
"dtoa",
"itoa",
"serde",
"url",
"url 2.1.1",
]
[[package]]
@ -1680,57 +1734,6 @@ dependencies = [
"winapi 0.3.8",
]
[[package]]
name = "stdweb"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
dependencies = [
"discard",
"rustc_version",
"serde",
"serde_json",
"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 = "syn"
version = "1.0.17"
@ -1763,26 +1766,6 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "thiserror"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3711fd1c4e75b3eff12ba5c40dba762b6b65c5476e8174c1a664772060c49bf"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae2b85ba4c9aa32dd3343bd80eb8d22e9b54b7688c17ea3907f236885353b233"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "thread-id"
version = "2.0.0"
@ -1876,14 +1859,14 @@ dependencies = [
"enum-as-inner",
"failure",
"futures",
"idna",
"idna 0.2.0",
"lazy_static",
"log 0.4.8",
"rand 0.7.3",
"smallvec",
"socket2",
"tokio",
"url",
"url 2.1.1",
]
[[package]]
@ -1905,6 +1888,15 @@ dependencies = [
"trust-dns-proto",
]
[[package]]
name = "unicase"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
dependencies = [
"version_check 0.9.1",
]
[[package]]
name = "unicode-bidi"
version = "0.3.4"
@ -1929,21 +1921,38 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
[[package]]
name = "unicode-width"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
[[package]]
name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
[[package]]
name = "url"
version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
dependencies = [
"idna 0.1.5",
"matches",
"percent-encoding 1.0.1",
]
[[package]]
name = "url"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
dependencies = [
"idna",
"idna 0.2.0",
"matches",
"percent-encoding",
"percent-encoding 2.1.0",
]
[[package]]
@ -1976,6 +1985,18 @@ version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
[[package]]
name = "version_check"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
[[package]]
name = "version_check"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
@ -1989,6 +2010,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f"
dependencies = [
"cfg-if",
"serde",
"serde_json",
"wasm-bindgen-macro",
]
@ -2007,6 +2030,18 @@ dependencies = [
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7add542ea1ac7fdaa9dc25e031a6af33b7d63376292bd24140c637d00d1c312a"
dependencies = [
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.60"
@ -2036,6 +2071,16 @@ version = "0.2.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639"
[[package]]
name = "web-sys"
version = "0.3.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "widestring"
version = "0.4.0"
@ -2103,43 +2148,3 @@ dependencies = [
"winapi 0.2.8",
"winapi-build",
]
[[package]]
name = "yew"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20c1d343cdf3d625752fd4d9fef73e1b6b2b8a08b00c832b0fc4a47f3b10fbef"
dependencies = [
"anyhow",
"anymap",
"bincode",
"cfg-if",
"cfg-match",
"http",
"indexmap",
"log 0.4.8",
"proc-macro-hack",
"proc-macro-nested",
"ryu",
"serde",
"serde_json",
"slab",
"stdweb",
"thiserror",
"wasm-bindgen",
"yew-macro",
]
[[package]]
name = "yew-macro"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb25d91f16265dd1643497ac3252be6c21c169d9cf3babcae32325c74200499f"
dependencies = [
"boolinator",
"lazy_static",
"proc-macro-hack",
"proc-macro2",
"quote",
"syn",
]

View File

@ -10,4 +10,12 @@ name = "jirs_client"
path = "./src/lib.rs"
[dependencies]
yew = { version = "*", features = ["std_web"] }
jirs-data = { path = "../jirs-data" }
seed = { version = "*" }
serde = "*"
serde_json = "*"
chrono = { version = "*", features = [ "serde" ] }
uuid = { version = "*", features = [ "serde" ] }
wasm-bindgen = "*"
web-sys = "*"
js-sys = "*"

View File

View File

@ -1 +1,4 @@
import("../pkg/index");
import("../pkg/index.js").then(module => {
console.log(module)
// module.main();
});

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JIRS</title>
<link href="/styles.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/todomvc-common@1.0.5/base.css"/ >
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/todomvc-app-css@2.1.2/index.css" />
</head>
<body>
<main id="app"></main>
</body>
</html>

View File

@ -1,47 +1,45 @@
use yew::{html, Callback, ClickEvent, Component, ComponentLink, Html, ShouldRender};
use seed::{prelude::*, *};
struct App {
clicked: bool,
onclick: Callback<ClickEvent>,
}
mod model;
type Model = i32;
enum Msg {
Click,
Increment,
ChangeGuidePage(i32),
ChangePage(i32),
}
impl Component for App {
type Message = Msg;
type Properties = ();
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
App {
clicked: false,
onclick: link.callback(|_| Msg::Click),
}
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::Click => {
self.clicked = true;
true // Indicate that the Component should re-render
}
}
}
fn view(&self) -> Html {
let button_text = if self.clicked {
"Clicked!"
} else {
"Click me!"
};
html! {
<button onclick=&self.onclick>{ button_text }</button>
}
fn update(msg: Msg, model: &mut Model, _: &mut impl Orders<Msg>) {
match msg {
Msg::Increment => *model += 1,
}
}
fn main() {
yew::start_app::<App>();
fn view(model: &Model) -> Node<Msg> {
div![
"This is a counter: ",
class!["counter"],
button![model.to_string(), ev(Ev::Click, |_| Msg::Increment),],
]
}
fn routes(url: Url) -> Option<Msg> {
if url.path.is_empty() {
return Some(Msg::ChangePage(0));
}
match url.path[0].as_ref() {
"guide" => match url.path.get(1).as_ref() {
Some(page) => Some(Msg::ChangeGuidePage(page.parse::<usize>().unwrap())),
None => Some(Msg::ChangePage(0)),
},
"changelog" => Some(Msg::ChangePage(1)),
_ => Some(Msg::ChangePage(0)),
}
}
#[wasm_bindgen(start)]
pub fn render() {
App::builder(update, view).routes(routes).build_and_start();
}

51
jirs-client/src/model.rs Normal file
View File

@ -0,0 +1,51 @@
use std::collections::hash_map::HashMap;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use jirs_data::*;
type ProjectId = i32;
#[derive(Serialize, Deserialize)]
pub struct CreateCommentForm {
fields: CreateCommentPayload,
}
#[derive(Serialize, Deserialize)]
pub struct CreateIssueForm {
fields: CreateIssuePayload,
}
#[derive(Serialize, Deserialize)]
pub struct UpdateProjectForm {
id: ProjectId,
fields: UpdateProjectPayload,
}
#[derive(Serialize, Deserialize)]
pub struct Model {
access_token: Option<Uuid>,
user: Option<User>,
project: Option<Project>,
project_form: Option<UpdateProjectForm>,
issue_form: Option<CreateIssueForm>,
comment_form: Option<CreateCommentForm>,
issues: Vec<Issue>,
comments_by_project_id: HashMap<ProjectId, Vec<Comment>>,
}
impl Default for Model {
fn default() -> Self {
Self {
access_token: None,
project: None,
user: None,
issue_form: None,
project_form: None,
comment_form: None,
issues: vec![],
comments_by_project_id: Default::default(),
}
}
}

View File

@ -30,6 +30,8 @@ module.exports = {
args: "--log-level warn",
extraArgs: "--no-typescript",
}),
new HtmlWebpackPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "js", "template.ejs"),
}),
]
};

View File

@ -1,70 +1,103 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from "react-redux";
import { ProjectCategory, ProjectCategoryCopy } from 'shared/constants/projects';
import toast from 'shared/utils/toast';
import useApi from 'shared/hooks/api';
import api from 'shared/utils/api';
import { Breadcrumbs, Form } from 'shared/components';
import { updateProjectFormFieldChanged, updateProjectFormRequest, updateProjectFormSuccess, } from 'actions/forms';
import { ActionButton, FormCont, FormElement, FormHeading } from './Styles';
const ProjectSettings = ({ project, fetchProject }) => {
const [ { isUpdating }, updateProject ] = useApi.put(`/project/${ project.id }`);
return (
<Form
initialValues={Form.initialValues(project, get => ({
name: get('name'),
url: get('url'),
category: get('category'),
description: get('description'),
}))}
validations={{
name: [Form.is.required(), Form.is.maxLength(100)],
url: Form.is.url(),
category: Form.is.required(),
}}
onSubmit={async (values, form) => {
try {
await updateProject(values);
await fetchProject();
toast.success('Changes have been saved successfully.');
} catch (error) {
Form.handleAPIError(error, form);
class ProjectSettings extends React.Component {
state = {
isUpdating: false, form: {
name: '',
url: '',
category: '',
description: '',
}
}}
>
<FormCont>
<FormElement>
<Breadcrumbs items={['Projects', project.name, 'Project Details']} />
<FormHeading>Project Details</FormHeading>
};
<Form.Field.Input name="name" label="Name" />
<Form.Field.Input name="url" label="URL" />
<Form.Field.TextEditor
name="description"
label="Description"
tip="Describe the project in as much detail as you'd like."
/>
<Form.Field.Select name="category" label="Project Category" options={categoryOptions} />
componentDidMount() {
this.props.updateProjectFormFieldChanged(this.props.project);
}
<ActionButton type="submit" variant="primary" isWorking={isUpdating}>
Save changes
</ActionButton>
</FormElement>
</FormCont>
</Form>
);
};
onSubmit = async () => {
this.setState({ isUpdating: true });
try {
await api.put(`/project/${ this.props.project.id }`, this.state.form);
await this.props.fetchProject();
toast.success('Changes have been saved successfully.');
} catch (error) {
}
this.setState({ isUpdating: false });
};
onChange = (field, value) => this.props.updateProject({ [field]: value });
render() {
let { updateProject: project } = this.props;
console.log(project);
if (!project.id) return <></>;
return (
<Form
initialValues={ project }
validations={ {
name: [ Form.is.required(), Form.is.maxLength(100) ],
url: Form.is.url(),
category: Form.is.required(),
} }
onSubmit={ this.onSubmit }
>
<FormCont>
<FormElement>
<Breadcrumbs items={ [ 'Projects', project.name, 'Project Details' ] }/>
<FormHeading>Project Details</FormHeading>
<Form.Field.Input name="name" label="Name" onChange={ this.onChange }/>
<Form.Field.Input name="url" label="URL" onChange={ this.onChange }/>
<Form.Field.TextEditor
name="description"
label="Description"
tip="Describe the project in as much detail as you'd like."
onChange={ this.onChange }
/>
<Form.Field.Select
name="category"
label="Project Category"
options={ categoryOptions }
onChange={ this.onChange }
/>
<ActionButton type="submit" variant="primary" isWorking={ this.state.isUpdating }>
Save changes
</ActionButton>
</FormElement>
</FormCont>
</Form>
);
}
}
const categoryOptions = Object.values(ProjectCategory).map(category => ({
value: category,
label: ProjectCategoryCopy[category],
value: category,
label: ProjectCategoryCopy[category],
}));
ProjectSettings.propTypes = {
project: PropTypes.object.isRequired,
fetchProject: PropTypes.func.isRequired,
project: PropTypes.object.isRequired,
fetchProject: PropTypes.func.isRequired,
};
export default ProjectSettings;
const mapStateToProps = ({ forms: { updateProject } }) => ({ updateProject });
const mapDispatchToProps = ({
updateProjectFormFieldChanged,
updateProjectFormRequest,
updateProjectFormSuccess,
});
export default connect(mapStateToProps, mapDispatchToProps)(ProjectSettings);

View File

@ -7,3 +7,6 @@ export const passwordChanged = createAction(ActionType.SignInPasswordChanged, ev
export const signInSubmit = createAction(ActionType.SignInRequest, event => {
event.preventDefault();
});
export const updateProjectFormFieldChanged = createAction(ActionType.UpdateProjectFormFieldChanged);
export const updateProjectFormRequest = createAction(ActionType.UpdateProjectFormRequest);
export const updateProjectFormSuccess = createAction(ActionType.UpdateProjectFormSuccess);

View File

View File

@ -0,0 +1,4 @@
import { request } from './index';
export const updateProject = form =>
request({ path: `/project/${ form.get('id') }`, form });

View File

@ -7,6 +7,14 @@ interface SignInFormState {
password: string,
}
interface UpdateProjectState {
id?: number,
name: string,
url: string,
category: string,
description: string,
}
const initialSignIn = (): SignInFormState => ({ email: '', password: '' });
const signInForm = (state: SignInFormState = initialSignIn(), { type, payload }: JirsAction) => {
@ -22,4 +30,23 @@ const signInForm = (state: SignInFormState = initialSignIn(), { type, payload }:
}
};
export default combineReducers({ signInForm })
const initialUpdateProject = (): UpdateProjectState => ({
id: null,
name: '',
url: '',
category: '',
description: '',
});
const updateProject = (state = initialUpdateProject(), { type, payload }: JirsAction) => {
switch (type) {
case ActionType.UpdateProjectFormFieldChanged:
return { ...state, ...payload };
case ActionType.UpdateProjectFormSuccess:
return initialUpdateProject();
default:
return state;
}
};
export default combineReducers({ signInForm, updateProject })

View File

@ -13,10 +13,15 @@ export interface User {
export enum ActionType {
CurrentUser = 'CurrentUser',
FetchCurrentUser = 'FetchCurrentUser',
//
SignInEmailChanged = 'SignInEmailChanged',
SignInPasswordChanged = 'SignInPasswordChanged',
SignInRequest = 'SignInRequest',
SignInSuccess = 'SignInSuccess',
//
UpdateProjectFormFieldChanged = 'UpdateProjectFormFieldChanged',
UpdateProjectFormRequest = 'UpdateProjectFormRequest',
UpdateProjectFormSuccess = 'UpdateProjectFormSuccess',
}
export interface JirsAction extends Action<ActionType> {

View File

@ -0,0 +1,10 @@
import { call, select } from 'redux-saga/effects';
import * as projectsApi from 'api/projects';
export const updateProject = function * () {
const state = yield select(({ forms: { updateProject } }) => updateProject);
const form = new FormData;
for (const key in state) form.append(key, state[key]);
yield call(projectsApi.updateProject, form);
};

View File

@ -2,9 +2,11 @@ import { takeEvery } from 'redux-saga/effects';
import { ActionType } from "../reducers/types";
import * as usersSaga from './users';
import * as formsSaga from './forms';
const main = function * () {
yield takeEvery(ActionType.FetchCurrentUser, usersSaga.fetchCurrentUser);
yield takeEvery(ActionType.UpdateProjectFormRequest, formsSaga.updateProject);
};
export default main

View File