diff --git a/index.html b/index.html index 0f92434..5beb708 100644 --- a/index.html +++ b/index.html @@ -236,7 +236,7 @@ }; init("/{base_path}/assets/dioxus/{app_name}_bg.wasm").then( - async (wasm) => { + async (wasm) => { if (wasm.__wbindgen_start == undefined) { wasm.main(); } @@ -244,26 +244,6 @@ ); - {script_include} diff --git a/public/styles/main.scss b/public/styles/main.scss index e6a1ac1..7ce20da 100644 --- a/public/styles/main.scss +++ b/public/styles/main.scss @@ -237,6 +237,7 @@ $fw-bold: 700; .bg--state-primary-active { background: var(--state-primary-active) !important; + &:hover { background-color: var(--fill-400) !important; } @@ -580,6 +581,7 @@ $fw-bold: 700; background: var(--fill-50); } +.form__inputs--initiative .TinyMDE, .form__inputs--initiative .input-wrapper { background: var(--fill-00); } @@ -771,6 +773,7 @@ $fw-bold: 700; border: none; color: var(--fill-00); background: var(--state-primary-active); + &:hover { background-color: var(--fill-400); } @@ -780,6 +783,7 @@ $fw-bold: 700; border: none; color: var(--text-loud); background: var(--fill-100); + &:hover { background-color: var(--fill-200); } @@ -1266,13 +1270,13 @@ $fw-bold: 700; background: var(--fill-00); border: none; box-shadow: 0px 0.5px 0px 0px rgba(26, 26, 26, .08), 0px 1px 3px 0px rgba(26, 26, 26, .08); + &:focus-within { outline: 3px solid var(--state-primary-active); } } .markdown__wrapper--editor .TinyMDE { - background: transparent; color: var(--text-primary); } @@ -1470,6 +1474,7 @@ $fw-bold: 700; .dropdown__item { text-align: left; border-bottom: 2px solid #4BAA54; + &:hover { background: var(--fill-200); } @@ -1530,6 +1535,10 @@ $fw-bold: 700; height: var(--element-size-small); } +.TinyMDE { + min-height: var(--element-size-medium); +} + .tab--small { padding: 0 16px; } @@ -1582,21 +1591,25 @@ textarea::placeholder { color: var(--text-secondary); } +.TinyMDE, .input-wrapper { width: 100%; min-width: 220px; padding: 0 20px; border-radius: 12px; - display: flex; - gap: 12px; - align-items: center; background: var(--fill-00); border: none; box-shadow: 0px 0.5px var(--Blur-blur-0, 0px) 0px var(--Colors-alpha-dark-50, rgba(26, 26, 26, 0.08)), 0px 1px var(--Blur-blur-2, 3px) 0px rgba(26, 26, 26, 0.08); + &:focus-within { border: 3px solid var(--state-primary-active); } } +.input-wrapper { + display: flex; + gap: 12px; + align-items: center; +} .button--primary, .button--secondary, @@ -1749,6 +1762,7 @@ textarea::placeholder { gap: 4px; width: 100%; border-radius: 12px; + &:focus-within { outline: 3px solid var(--state-primary-active); } @@ -1921,7 +1935,7 @@ textarea::placeholder { height: fit-content; } -.checkbox-card > .checkbox-card__header { +.checkbox-card>.checkbox-card__header { display: flex; width: 100%; gap: 8px; @@ -2662,7 +2676,8 @@ textarea::placeholder { right: 16px; } -.wallet, .transfers { +.wallet, +.transfers { max-height: 100vh; width: 100%; display: flex; @@ -3032,7 +3047,7 @@ small.summary__item__value { width: 100%; } -.widthdraw__data > * { +.widthdraw__data>* { width: 100%; } @@ -3570,7 +3585,7 @@ small.summary__item__value { width: auto; min-width: 150px; height: 1.62em; - vertical-align:bottom; + vertical-align: bottom; overflow: hidden; text-align: start; } @@ -3590,19 +3605,25 @@ small.summary__item__value { .animated-text span:nth-child(1) { animation-delay: 0s; } + .animated-text span:nth-child(2) { animation-delay: 2s; } + .animated-text span:nth-child(3) { animation-delay: 4s; } @keyframes roll { - 0%, 33.33% { + + 0%, + 33.33% { opacity: 0; transform: translateY(100%); } - 5%, 28.33% { + + 5%, + 28.33% { opacity: 1; transform: translateY(0); } @@ -3616,9 +3637,11 @@ small.summary__item__value { 0% { background-color: var(--fill-100); } + 50% { background-color: var(--fill-50); } + 100% { background-color: var(--fill-100); } diff --git a/src/components/atoms/attach.rs b/src/components/atoms/attach.rs index 7118aee..486a7f2 100644 --- a/src/components/atoms/attach.rs +++ b/src/components/atoms/attach.rs @@ -142,10 +142,14 @@ pub fn Attach(props: AttachProps) -> Element { variant: IconButtonVariant::Round, size: ElementSize::Big, class: "button--avatar bg--transparent", - body: rsx!( - Icon { icon : Close, height : 28, width : 28, fill : - "var(--state-destructive-active)" } - ), + body: rsx! { + Icon { + icon: Close, + height: 28, + width: 28, + fill: "var(--state-destructive-active)" + } + }, on_click: move |_| { error.set(None) } } } diff --git a/src/components/atoms/bar.rs b/src/components/atoms/bar.rs index 524a1af..38c06dc 100644 --- a/src/components/atoms/bar.rs +++ b/src/components/atoms/bar.rs @@ -26,13 +26,20 @@ pub fn Bar(props: BarProps) -> Element { rsx!( section { div { class: "bar {variant}", - span { class: "bar__content bar__content--left", style: format!("width: {}%", props.left_value), + span { + class: "bar__content bar__content--left", + style: format!("width: {}%", props.left_value), p { class: "votes-counter__title", {props.left_helper} } } if let Some(value) = props.center_value { - span { class: "bar__content__threshold", style: format!("left: {}%", value) } + span { + class: "bar__content__threshold", + style: format!("left: {}%", value) + } } - span { class: "bar__content bar__content--right", style: format!("width: {}%", props.right_value), + span { + class: "bar__content bar__content--right", + style: format!("width: {}%", props.right_value), p { class: "votes-counter__title", {props.right_helper} } } } diff --git a/src/components/atoms/card.rs b/src/components/atoms/card.rs index 0bb8137..04a5f08 100644 --- a/src/components/atoms/card.rs +++ b/src/components/atoms/card.rs @@ -15,10 +15,14 @@ pub fn Card(props: CardProps) -> Element { div { class: "card__container", div { class: "card__head", IconButton { - body: rsx!( - Avatar { name : "{props.community.name}", size : 48, uri : props.community.icon, - variant : Variant::SemiRound } - ), + body: rsx! { + Avatar { + name: "{props.community.name}", + size: 48, + uri: props.community.icon, + variant: Variant::SemiRound + } + }, on_click: move |_| {} } h3 { class: "card__title", "{props.community.name}" } @@ -38,10 +42,15 @@ pub fn Card(props: CardProps) -> Element { div { class: "card__cta", IconButton { class: "button--avatar", - body: rsx!( - Icon { icon : ArrowRight, height : 16, width : 16, stroke_width : 2, stroke : - "var(--text-primary)" } - ), + body: rsx! { + Icon { + icon: ArrowRight, + height: 16, + width: 16, + stroke_width: 2, + stroke: "var(--text-primary)" + } + }, on_click: move |_| {} } } diff --git a/src/components/atoms/card_skeleton.rs b/src/components/atoms/card_skeleton.rs index ef4c70d..aad1c3c 100644 --- a/src/components/atoms/card_skeleton.rs +++ b/src/components/atoms/card_skeleton.rs @@ -4,8 +4,7 @@ use dioxus::prelude::*; pub fn CardSkeleton() -> Element { rsx!( section { class: "card card--skeleton", - div { class: "card__container", - } + div { class: "card__container" } } ) } \ No newline at end of file diff --git a/src/components/atoms/input.rs b/src/components/atoms/input.rs index ca705ed..d0434a0 100644 --- a/src/components/atoms/input.rs +++ b/src/components/atoms/input.rs @@ -108,10 +108,15 @@ pub fn Input(props: InputProps) -> Element { IconButton { class: "button--avatar bg--transparent", size: props.size, - body: rsx!( - Icon { icon : Search, height : 26, width : 26, stroke_width : 1.5, fill : - "var(--text-secondary)" } - ), + body: rsx! { + Icon { + icon: Search, + height: 26, + width: 26, + stroke_width: 1.5, + fill: "var(--text-secondary)" + } + }, on_click: move |_| { is_active.toggle(); } diff --git a/src/components/atoms/input_tags.rs b/src/components/atoms/input_tags.rs index 2f97402..9b11a26 100644 --- a/src/components/atoms/input_tags.rs +++ b/src/components/atoms/input_tags.rs @@ -127,7 +127,9 @@ pub fn InputTags(props: InputTagsProps) -> Element { } IconButton { class: "button--drop bg--transparent", - body: rsx!(Icon { icon : Close, height : 20, width : 20, fill : "var(--fill-400)" }), + body: rsx! { + Icon { icon: Close, height: 20, width: 20, fill: "var(--fill-400)" } + }, on_click: move |_| { new_value.set(tags()[tags().len() - 1].clone()); } diff --git a/src/components/atoms/markdown.rs b/src/components/atoms/markdown.rs index ddcfcf0..a0a500a 100644 --- a/src/components/atoms/markdown.rs +++ b/src/components/atoms/markdown.rs @@ -1,12 +1,14 @@ +use crate::components::atoms::button::Variant; +use crate::components::atoms::dropdown::ElementSize; +use crate::components::atoms::Button; use dioxus::prelude::*; use dioxus_std::i18n::use_i18; use dioxus_std::translate; use wasm_bindgen::prelude::*; use wasm_bindgen::JsValue; +use web_sys::js_sys; use web_sys::js_sys::Function; -use crate::components::atoms::button::Variant; -use crate::components::atoms::dropdown::ElementSize; -use crate::components::atoms::Button; +use web_sys::HtmlElement; #[derive(PartialEq, Props, Clone)] pub struct MarkdownEvent { pub value: String, @@ -18,53 +20,99 @@ pub struct MarkdownProps { content: String, on_input: EventHandler, } -#[wasm_bindgen] +#[wasm_bindgen(inline_js = r#" + export function initMarkdownEditor(editorElement, toolbarElement, onChangeCallback) { + let tinyEditor = new TinyMDE.Editor({ element: editorElement }); + let commandBar = new TinyMDE.CommandBar({ + element: toolbarElement, + editor: tinyEditor, + }); + + tinyEditor.addEventListener('change', function () { + let content = tinyEditor.getContent(); + onChangeCallback(content); + }); + + return tinyEditor; + } +"#)] extern "C" { - #[wasm_bindgen(js_namespace = globalThis, js_name = initMarkdownEditor)] - fn init_markdown_editor(); - #[wasm_bindgen(js_namespace = window, js_name = initMarkdownEditor)] - fn add_change_listener(callback: &Function); - #[wasm_bindgen(js_namespace = window, js_name = setContentMarkdownEditor)] - fn set_content_markdown_editor(content: String); + #[wasm_bindgen(js_name = initMarkdownEditor)] + fn init_markdown_editor( + editor: HtmlElement, + toolbar: HtmlElement, + callback: &Function, + ) -> JsValue; +} + +fn call_method_reflect(obj: &JsValue, method_name: &str, args: &[JsValue]) -> Result { + let method = js_sys::Reflect::get(obj, &method_name.into())?; + let func: js_sys::Function = method.dyn_into()?; + func.apply(obj, &js_sys::Array::from_iter(args)) } + pub fn Markdown(props: MarkdownProps) -> Element { let i18 = use_i18(); let mut is_editor_loaded = use_signal(|| false); - let mut content = use_signal(|| { + let content = use_signal(|| { if props.content.len() > 0 { - props.content + props.content.clone() } else { translate!(i18, "utils.markdown.value") } }); let mut is_markdown_visible = use_signal(|| true); - let cont = &*content.read(); - let parser = pulldown_cmark::Parser::new(cont); + let mut toolbar_ref = use_signal::>>(|| None); + let mut editor_ref = use_signal::>>(|| None); + let cont = props.content; + let parser = pulldown_cmark::Parser::new(&cont); let mut html_buf = String::new(); pulldown_cmark::html::push_html(&mut html_buf, parser); use_effect(move || { if !is_editor_loaded() { - init_markdown_editor(); - set_content_markdown_editor(content()); - let closure = Closure::wrap( - Box::new(move |new_content: JsValue| { + if let (Some(toolbar_ref), Some(editor_ref)) = (toolbar_ref(), editor_ref()) { + let closure = Closure::wrap(Box::new(move |new_content: JsValue| { if let Some(text) = new_content.as_string() { - content.set(text.clone()); - props.on_input.call(MarkdownEvent { value: text }) + props.on_input.call(MarkdownEvent { value: text }); } - }) as Box, - ); - let function = closure.as_ref().unchecked_ref::(); - add_change_listener(function); - closure.forget(); - is_editor_loaded.set(true) + }) as Box); + let function = closure.as_ref().unchecked_ref::(); + let tiny_editor = init_markdown_editor(*editor_ref.clone(), *toolbar_ref.clone(), function); + let content_value = JsValue::from(content()); + if let Err(e) = call_method_reflect(&tiny_editor, "setContent", &[content_value]) { + log::warn!("Failed to set content {:?}", e); + }; + + closure.forget(); + is_editor_loaded.set(true); + } } }); + + rsx!( div { class: "markdown", - div { class: "markdown__wrapper", class: if !is_markdown_visible() { "hide" } else { "markdown__wrapper--editor" }, - div { id: "toolbar" } - div { id: "editor" } + div { + class: "markdown__wrapper", + class: if !is_markdown_visible() { "hide" } else { "markdown__wrapper--editor" }, + div { + onmounted: move |event| { + event + .data + .downcast::() + .and_then(|element| element.clone().dyn_into::().ok()) + .map(|html_element| toolbar_ref.set(Some(Box::new(html_element.clone())))); + }, + } + div { + onmounted: move |event| { + event + .data + .downcast::() + .and_then(|element| element.clone().dyn_into::().ok()) + .map(|html_element| editor_ref.set(Some(Box::new(html_element.clone())))); + }, + } } div { class: "markdown__wrapper", diff --git a/src/components/atoms/search_input.rs b/src/components/atoms/search_input.rs index 86d516d..40c617a 100644 --- a/src/components/atoms/search_input.rs +++ b/src/components/atoms/search_input.rs @@ -45,10 +45,15 @@ pub fn SearchInput(props: SearchInputProps) -> Element { IconButton { class: "button--avatar bg--transparent", size: props.size, - body: rsx!( - Icon { icon : Search, height : 26, width : 26, stroke_width : 1.5, fill : - "var(--text-secondary)" } - ), + body: rsx! { + Icon { + icon: Search, + height: 26, + width: 26, + stroke_width: 1.5, + fill: "var(--text-secondary)" + } + }, on_click: move |_| { is_active.toggle(); } diff --git a/src/components/molecules/action_request_list.rs b/src/components/molecules/action_request_list.rs index 2aa7eb2..12d8e5b 100644 --- a/src/components/molecules/action_request_list.rs +++ b/src/components/molecules/action_request_list.rs @@ -15,7 +15,10 @@ pub fn ActionRequestList(props: ActionRequestListProps) -> Element { let i18 = use_i18(); let render_add_members = |action: &AddMembersAction| { rsx!( - ActionRequest { name: translate!(i18, "initiative.steps.actions.add_members.title"), details: action.members.len().to_string() } + ActionRequest { + name: translate!(i18, "initiative.steps.actions.add_members.title"), + details: action.members.len().to_string() + } ul { class: "requests", for member in action.members.iter() { li { @@ -42,7 +45,10 @@ pub fn ActionRequestList(props: ActionRequestListProps) -> Element { }; let render_voting_open_gov = |action: &VotingOpenGovAction| { rsx!( - ActionRequest { name: translate!(i18, "initiative.steps.actions.voting_open_gov.title"), details: action.proposals.len().to_string() } + ActionRequest { + name: translate!(i18, "initiative.steps.actions.voting_open_gov.title"), + details: action.proposals.len().to_string() + } ul { class: "requests", for proposal in action.proposals.iter() { li { diff --git a/src/components/molecules/actions/members.rs b/src/components/molecules/actions/members.rs index 8bc1a6d..da5c98e 100644 --- a/src/components/molecules/actions/members.rs +++ b/src/components/molecules/actions/members.rs @@ -91,10 +91,14 @@ pub fn MembersAction(props: VotingProps) -> Element { variant: Variant::Round, size: ElementSize::Small, class: "button--avatar", - body: rsx!( - Icon { icon : AddPlus, height : 24, width : 24, fill : - "var(--state-primary-active)" } - ), + body: rsx! { + Icon { + icon: AddPlus, + height: 24, + width: 24, + fill: "var(--state-primary-active)" + } + }, on_click: move |_| { if let ActionItem::AddMembers(ref mut meta) = initiative.get_action(props.index) { diff --git a/src/components/molecules/actions/transfer.rs b/src/components/molecules/actions/transfer.rs index fc13370..d90b51e 100644 --- a/src/components/molecules/actions/transfer.rs +++ b/src/components/molecules/actions/transfer.rs @@ -107,10 +107,14 @@ pub fn TransferAction(props: VotingProps) -> Element { variant: Variant::Round, size: ElementSize::Small, class: "button--avatar", - body: rsx!( - Icon { icon : AddPlus, height : 24, width : 24, fill : - "var(--state-primary-active)" } - ), + body: rsx! { + Icon { + icon: AddPlus, + height: 24, + width: 24, + fill: "var(--state-primary-active)" + } + }, on_click: move |_| { if let ActionItem::CommunityTransfer(ref mut meta) = initiative .get_action(props.index) diff --git a/src/components/molecules/actions/treasury.rs b/src/components/molecules/actions/treasury.rs index 021d0c6..77dc14e 100644 --- a/src/components/molecules/actions/treasury.rs +++ b/src/components/molecules/actions/treasury.rs @@ -132,10 +132,14 @@ pub fn TreasuryAction(props: VotingProps) -> Element { variant: Variant::Round, size: ElementSize::Small, class: "button--avatar", - body: rsx!( - Icon { icon : AddPlus, height : 24, width : 24, fill : - "var(--state-primary-active)" } - ), + body: rsx! { + Icon { + icon: AddPlus, + height: 24, + width: 24, + fill: "var(--state-primary-active)" + } + }, on_click: move |_| { if let ActionItem::KusamaTreasury(ref mut meta) = initiative .get_action(props.index) diff --git a/src/components/molecules/actions/voting.rs b/src/components/molecules/actions/voting.rs index adae434..00b3cf5 100644 --- a/src/components/molecules/actions/voting.rs +++ b/src/components/molecules/actions/voting.rs @@ -202,10 +202,14 @@ pub fn VotingAction(props: VotingProps) -> Element { variant: Variant::Round, size: ElementSize::Small, class: "button--avatar", - body: rsx!( - Icon { icon : AddPlus, height : 24, width : 24, fill : - "var(--state-primary-active)" } - ), + body: rsx! { + Icon { + icon: AddPlus, + height: 24, + width: 24, + fill: "var(--state-primary-active)" + } + }, on_click: move |_| { if let ActionItem::VotingOpenGov(ref mut meta) = initiative .get_action(props.index) diff --git a/src/components/molecules/header.rs b/src/components/molecules/header.rs index f070adf..7a66dab 100644 --- a/src/components/molecules/header.rs +++ b/src/components/molecules/header.rs @@ -184,9 +184,9 @@ pub fn Header() -> Element { Button { text: translate!(i18, "header.cta.connect"), status: None, - right_icon: rsx!( - Icon { icon : Polkadot, height : 20, width : 20, fill : "var(--text-primary)" } - ), + right_icon: rsx! { + Icon { icon: Polkadot, height: 20, width: 20, fill: "var(--text-primary)" } + }, on_click: move |_| { spawn( async move { @@ -237,7 +237,9 @@ pub fn Header() -> Element { variant: Variant::Round, size: ElementSize::Big, class: "button--avatar button--comming-soon bg--fill-600", - body: rsx!(Icon { icon : ArrowUpDown, height : 32, width : 32, fill : "var(--fill-00)" }), + body: rsx! { + Icon { icon: ArrowUpDown, height: 32, width: 32, fill: "var(--fill-00)" } + }, on_click: move |_| {} } } @@ -260,35 +262,45 @@ pub fn Header() -> Element { variant: Variant::Round, size: ElementSize::Big, class: "button--avatar bg--fill-50 button--comming-soon", - body: rsx!(Icon { icon : Votes, height : 32, width : 32, fill : "var(--fill-600)" }), + body: rsx! { + Icon { icon: Votes, height: 32, width: 32, fill: "var(--fill-600)" } + }, on_click: move |_| {} } IconButton { variant: Variant::Round, size: ElementSize::Big, class: "button--avatar bg--fill-50 button--comming-soon", - body: rsx!(Icon { icon : Messages, height : 32, width : 32, fill : "var(--fill-600)" }), + body: rsx! { + Icon { icon: Messages, height: 32, width: 32, fill: "var(--fill-600)" } + }, on_click: move |_| {} } IconButton { variant: Variant::Round, size: ElementSize::Big, class: "button--avatar bg--fill-50 button--comming-soon", - body: rsx!(Icon { icon : Profile, height : 32, width : 32, fill : "var(--fill-600)" }), + body: rsx! { + Icon { icon: Profile, height: 32, width: 32, fill: "var(--fill-600)" } + }, on_click: move |_| {} } IconButton { variant: Variant::Round, size: ElementSize::Big, class: "button--avatar bg--fill-50 button--comming-soon", - body: rsx!(Icon { icon : Settings, height : 32, width : 32, fill : "var(--fill-600)" }), + body: rsx! { + Icon { icon: Settings, height: 32, width: 32, fill: "var(--fill-600)" } + }, on_click: move |_| {} } IconButton { variant: Variant::Round, size: ElementSize::Big, class: "button--avatar bg--fill-50 mobile", - body: rsx!(Icon { icon : Hamburguer, height : 32, width : 32, fill : "var(--fill-600)" }), + body: rsx! { + Icon { icon: Hamburguer, height: 32, width: 32, fill: "var(--fill-600)" } + }, on_click: move |_| { is_active.toggle(); } @@ -307,7 +319,9 @@ pub fn Header() -> Element { variant: Variant::Round, size: ElementSize::Big, class: "button--avatar bg--transparent", - body: rsx!(Icon { icon : Close, height : 32, width : 32, fill : "var(--fill-600)" }), + body: rsx! { + Icon { icon: Close, height: 32, width: 32, fill: "var(--fill-600)" } + }, on_click: move |_| { is_active.toggle(); } @@ -320,7 +334,9 @@ pub fn Header() -> Element { variant: Variant::Round, size: ElementSize::Big, class: "button--avatar bg--fill-50 button--comming-soon", - body: rsx!(Icon { icon : Votes, height : 32, width : 32, fill : "var(--fill-600)" }), + body: rsx! { + Icon { icon: Votes, height: 32, width: 32, fill: "var(--fill-600)" } + }, on_click: move |_| {} } } @@ -330,7 +346,9 @@ pub fn Header() -> Element { variant: Variant::Round, size: ElementSize::Big, class: "button--avatar bg--fill-50 button--comming-soon", - body: rsx!(Icon { icon : Messages, height : 32, width : 32, fill : "var(--fill-600)" }), + body: rsx! { + Icon { icon: Messages, height: 32, width: 32, fill: "var(--fill-600)" } + }, on_click: move |_| {} } } @@ -340,7 +358,9 @@ pub fn Header() -> Element { variant: Variant::Round, size: ElementSize::Big, class: "button--avatar bg--fill-50 button--comming-soon", - body: rsx!(Icon { icon : Profile, height : 32, width : 32, fill : "var(--fill-600)" }), + body: rsx! { + Icon { icon: Profile, height: 32, width: 32, fill: "var(--fill-600)" } + }, on_click: move |_| {} } } @@ -350,7 +370,9 @@ pub fn Header() -> Element { variant: Variant::Round, size: ElementSize::Big, class: "button--avatar bg--fill-50 button--comming-soon", - body: rsx!(Icon { icon : Settings, height : 32, width : 32, fill : "var(--fill-600)" }), + body: rsx! { + Icon { icon: Settings, height: 32, width: 32, fill: "var(--fill-600)" } + }, on_click: move |_| {} } } diff --git a/src/components/molecules/initiative/info.rs b/src/components/molecules/initiative/info.rs index 8b42210..5ddb601 100644 --- a/src/components/molecules/initiative/info.rs +++ b/src/components/molecules/initiative/info.rs @@ -1,12 +1,12 @@ -use dioxus::prelude::*; -use dioxus_std::{i18n::use_i18, translate}; use crate::{ components::atoms::{ - dropdown::ElementSize, input_tags::InputTagsEvent, markdown::MarkdownEvent, - Input, InputTags, Markdown, + dropdown::ElementSize, input_tags::InputTagsEvent, markdown::MarkdownEvent, Input, + InputTags, Markdown, }, hooks::{use_initiative::use_initiative, use_onboard::use_onboard}, }; +use dioxus::prelude::*; +use dioxus_std::{i18n::use_i18, translate}; #[component] pub fn InitiativeInfo(error: bool) -> Element { let i18 = use_i18(); diff --git a/src/components/molecules/onboarding/invite.rs b/src/components/molecules/onboarding/invite.rs index e564460..a84fb8d 100644 --- a/src/components/molecules/onboarding/invite.rs +++ b/src/components/molecules/onboarding/invite.rs @@ -96,10 +96,14 @@ pub fn OnboardingInvite() -> Element { variant: Variant::Round, size: ElementSize::Medium, class: "button--avatar", - body: rsx!( - Icon { icon : AddPlus, height : 24, width : 24, fill : - "var(--state-primary-active)" } - ), + body: rsx! { + Icon { + icon: AddPlus, + height: 24, + width: 24, + fill: "var(--state-primary-active)" + } + }, on_click: move |_| { onboard .push_invitation(InvitationItem { diff --git a/src/components/molecules/onboarding/management.rs b/src/components/molecules/onboarding/management.rs index a6ad98c..3999a26 100644 --- a/src/components/molecules/onboarding/management.rs +++ b/src/components/molecules/onboarding/management.rs @@ -21,12 +21,15 @@ pub fn OnboardingManagement() -> Element { id: "a".to_string(), name: String::from("management"), checked: matches!(onboard.get_management().value, ManagementOptions::Membership), - body: rsx!( - ManagementMethod { title : translate!(i18, - "onboard.management.form.membership.title"), description : translate!(i18, - "onboard.management.form.membership.description"), icon : rsx!(Icon { icon : - TeamFill, height : 20, width : 20, fill : "var(--fill-600)" }), } - ), + body: rsx! { + ManagementMethod { + title: translate!(i18, "onboard.management.form.membership.title"), + description: translate!(i18, "onboard.management.form.membership.description"), + icon: rsx! { + Icon { icon: TeamFill, height: 20, width: 20, fill: "var(--fill-600)" } + } + } + }, on_change: move |_| { onboard .management_mut() @@ -38,12 +41,15 @@ pub fn OnboardingManagement() -> Element { name: String::from("management"), checked: false, soon: true, - body: rsx!( - ManagementMethod { title : translate!(i18, "onboard.management.form.rank.title"), - description : translate!(i18, "onboard.management.form.rank.description"), icon : - rsx!(Icon { icon : MedalFill, height : 20, width : 20, fill : "var(--fill-600)" - }), } - ), + body: rsx! { + ManagementMethod { + title: translate!(i18, "onboard.management.form.rank.title"), + description: translate!(i18, "onboard.management.form.rank.description"), + icon: rsx! { + Icon { icon: MedalFill, height: 20, width: 20, fill: "var(--fill-600)" } + } + } + }, on_change: move |_| {} } CheckboxCard { @@ -51,12 +57,15 @@ pub fn OnboardingManagement() -> Element { name: String::from("management"), checked: false, soon: true, - body: rsx!( - ManagementMethod { title : translate!(i18, - "onboard.management.form.native_token.title"), description : translate!(i18, - "onboard.management.form.native_token.description"), icon : rsx!(Icon { icon : - KeyFill, height : 20, width : 20, fill : "var(--fill-600)" }), } - ), + body: rsx! { + ManagementMethod { + title: translate!(i18, "onboard.management.form.native_token.title"), + description: translate!(i18, "onboard.management.form.native_token.description"), + icon: rsx! { + Icon { icon: KeyFill, height: 20, width: 20, fill: "var(--fill-600)" } + } + } + }, on_change: move |_| {} } CheckboxCard { @@ -64,12 +73,15 @@ pub fn OnboardingManagement() -> Element { name: String::from("management"), checked: false, soon: true, - body: rsx!( - ManagementMethod { title : translate!(i18, - "onboard.management.form.own_token.title"), description : translate!(i18, - "onboard.management.form.own_token.description"), icon : rsx!(Icon { icon : - ShieldKeyholeFill, height : 20, width : 20, fill : "var(--fill-600)" }), } - ), + body: rsx! { + ManagementMethod { + title: translate!(i18, "onboard.management.form.own_token.title"), + description: translate!(i18, "onboard.management.form.own_token.description"), + icon: rsx! { + Icon { icon: ShieldKeyholeFill, height: 20, width: 20, fill: "var(--fill-600)" } + } + } + }, on_change: move |_| {} } } diff --git a/src/components/molecules/paginator.rs b/src/components/molecules/paginator.rs index c33da8f..1bd3194 100644 --- a/src/components/molecules/paginator.rs +++ b/src/components/molecules/paginator.rs @@ -35,7 +35,9 @@ pub fn Paginator(props: PaginatorProps) -> Element { class: "button--avatar button--paginator", disabled: current_page() <= 1, size: ElementSize::Small, - body: rsx!(Icon { icon : ArrowLeft, height : 24, width : 24, fill : "var(--white)" }), + body: rsx! { + Icon { icon: ArrowLeft, height: 24, width: 24, fill: "var(--white)" } + }, on_click: move |_| { let current = current_page(); current_page.set(current - 1); @@ -50,7 +52,9 @@ pub fn Paginator(props: PaginatorProps) -> Element { class: "button--avatar button--paginator", size: ElementSize::Small, disabled: current_page() >= props.to, - body: rsx!(Icon { icon : ArrowRight, height : 24, width : 24, fill : "var(--white)" }), + body: rsx! { + Icon { icon: ArrowRight, height: 24, width: 24, fill: "var(--white)" } + }, on_click: move |_| { let current = current_page(); current_page.set(current + 1); diff --git a/src/components/molecules/sidebar.rs b/src/components/molecules/sidebar.rs index 56feb0c..2716f4f 100644 --- a/src/components/molecules/sidebar.rs +++ b/src/components/molecules/sidebar.rs @@ -25,10 +25,15 @@ pub fn Sidebar() -> Element { section { class: "sidebar", class: if is_active() { "sidebar--active" }, IconButton { class: "button--hamburguer", - body: rsx!( - Icon { icon : Hamburguer, height : 30, width : 30, stroke_width : 2, stroke : - "var(--text-1)" } - ), + body: rsx! { + Icon { + icon: Hamburguer, + height: 30, + width: 30, + stroke_width: 2, + stroke: "var(--text-1)" + } + }, on_click: move |_| { is_active.toggle(); } @@ -95,10 +100,9 @@ pub fn Sidebar() -> Element { class: "button--icon bg--state-primary-active", size: ElementSize::Big, variant: icon_button::Variant::Round, - body: rsx!( - Icon { icon : Home, height : 32, width : 32, stroke_width : 1, fill : - "var(--fill-00)" } - ), + body: rsx! { + Icon { icon: Home, height: 32, width: 32, stroke_width: 1, fill: "var(--fill-00)" } + }, on_click: move |_| { nav.push(vec![], "/"); } @@ -110,10 +114,15 @@ pub fn Sidebar() -> Element { class: "button--icon bg--state-primary-active", size: ElementSize::Big, variant: icon_button::Variant::Round, - body: rsx!( - Icon { icon : Compass, height : 32, width : 32, stroke_width : 1.5, fill : - "var(--fill-00)" } - ), + body: rsx! { + Icon { + icon: Compass, + height: 32, + width: 32, + stroke_width: 1.5, + fill: "var(--fill-00)" + } + }, on_click: move |_| { tooltip.hide(); nav.push(vec![], "/explore"); diff --git a/src/pages/account.rs b/src/pages/account.rs index 8a979a5..c852d95 100644 --- a/src/pages/account.rs +++ b/src/pages/account.rs @@ -152,7 +152,7 @@ pub fn Account() -> Element { ], "/deposit"); Ok::<(), String>(()) }.unwrap_or_else(move |_: String| { - + }) ); }, @@ -168,7 +168,7 @@ pub fn Account() -> Element { nav.push(vec![Box::new(is_chain_available(i18, timestamp, notification))], "/withdraw"); Ok::<(), String>(()) }.unwrap_or_else(move |_: String| { - + }) ); }, @@ -203,7 +203,7 @@ pub fn Account() -> Element { } } } - + } div { class: "account__container", h3 { class: "account__balance__title", @@ -218,7 +218,7 @@ pub fn Account() -> Element { th { {translate!(i18, "account.tabs.wallet.assets.cost")} } th { {translate!(i18, "account.tabs.wallet.assets.total")} } } - + match *tab_value.read() { AccountTabs::Kreivo => rsx!( tr { @@ -231,14 +231,14 @@ pub fn Account() -> Element { { format!("${} USD", if ksm_usd() == 0.0 || kreivo_balance() <= 0.001 { "-".to_string() } else { format!("{:.2}", ksm_usd() * kreivo_balance()) } )} } } - + tr { class: "list__asset--comming-soon", td { class: "list__name", "USDT" } td { "-" } td { "-" } td { "-" } } - + tr { class: "list__asset--comming-soon", td { class: "list__name", "dUSD" } td { "-" } @@ -268,28 +268,28 @@ pub fn Account() -> Element { th { {translate!(i18, "account.tabs.transfers.table.quantity")} } th { {translate!(i18, "account.tabs.transfers.table.account")} } } - + tr { td { class: "list__name", "KSM" } td { "2024-08-20 20:16:34" } td { "10" } td { "5E4S9C..." } } - + tr { td { class: "list__name", "KSM" } td { "2024-08-20 20:16:34" } td { "10" } td { "5E4S9C..." } } - + tr { td { class: "list__name", "KSM" } td { "2024-08-20 20:16:34" } td { "10" } td { "5E4S9C..." } } - + tr { td { class: "list__name", "KSM" } td { "2024-08-20 20:16:34" } diff --git a/src/pages/dashboard.rs b/src/pages/dashboard.rs index 10a5db1..0464b6f 100644 --- a/src/pages/dashboard.rs +++ b/src/pages/dashboard.rs @@ -112,10 +112,15 @@ pub fn Dashboard() -> Element { IconButton { class: "button--avatar desktop", size: ElementSize::Medium, - body: rsx!( - Icon { icon : AddPlus, height : 26, width : 26, stroke_width : 1.5, fill : - "var(--fill-00)" } - ), + body: rsx! { + Icon { + icon: AddPlus, + height: 26, + width: 26, + stroke_width: 1.5, + fill: "var(--fill-00)" + } + }, on_click: move |_| { tooltip.hide(); nav.push( @@ -130,187 +135,191 @@ pub fn Dashboard() -> Element { } } div { class: "dashboard__communities", - { if (communities.is_loading)() { - rsx! { - CardSkeleton {} - CardSkeleton {} - CardSkeleton {} - } - - } else { - rsx! { - for community in communities - .get_communities_by_filters( - Some(()), - filter_name().as_deref(), - filter_paginator(), - ) - { - section { class: "card", - div { class: "card__container", - div { class: "card__head", - IconButton { - body: rsx!( - Avatar { name : "{community.name}", size : 48, uri : community.icon, variant : - AvatarVariant::SemiRound } - ), - on_click: move |_| {} - } - h3 { class: "card__title", "{community.name}" } - } - p { class: "card__description", "{community.description}" } - if community.has_membership { - div { class: "card__favorite", - Icon { icon: Star, height: 24, width: 24, fill: "var(--state-primary-active)" } - } - } else { + { if (communities.is_loading)() { + rsx! { + CardSkeleton {} + CardSkeleton {} + CardSkeleton {} + } + + } else { + rsx! { + for community in communities + .get_communities_by_filters( + Some(()), + filter_name().as_deref(), + filter_paginator(), + ) + { + section { class: "card", + div { class: "card__container", + div { class: "card__head", + IconButton { + body: rsx!( + Avatar { name : "{community.name}", size : 48, uri : community.icon, variant : + AvatarVariant::SemiRound } + ), + on_click: move |_| {} + } + h3 { class: "card__title", "{community.name}" } + } + p { class: "card__description", "{community.description}" } + if community.has_membership { div { class: "card__favorite", - IconButton { - class: "button--drop bg--transparent", - body: rsx!( - Icon { icon : Star, height : 24, width : 24, fill : if community.favorite { - "var(--state-primary-active)" } else { "var(--state-base-background)" } } - ), - on_click: move |_| { - if let Err(e) = communities.handle_favorite(community.id) { - let message = match e { - CommunitiesError::NotFound => "Failed to update favorite", - CommunitiesError::FailedUpdatingFavorites => "Failed to update favorite", - CommunitiesError::NotFoundFavorite => "Failed to update favorite", - }; - notification.handle_error(&message); + Icon { icon: Star, height: 24, width: 24, fill: "var(--state-primary-active)" } + } + } else { + div { class: "card__favorite", + IconButton { + class: "button--drop bg--transparent", + body: rsx!( + Icon { icon : Star, height : 24, width : 24, fill : if community.favorite { + "var(--state-primary-active)" } else { "var(--state-base-background)" } } + ), + on_click: move |_| { + if let Err(e) = communities.handle_favorite(community.id) { + let message = match e { + CommunitiesError::NotFound => "Failed to update favorite", + CommunitiesError::FailedUpdatingFavorites => "Failed to update favorite", + CommunitiesError::NotFoundFavorite => "Failed to update favorite", + }; + notification.handle_error(&message); + } } } } + } + div { class: "card__metrics", + span { class: "card__metric", + Icon { + icon: UserAdd, + height: 16, + width: 16, + stroke_width: 2, + stroke: "var(--text-primary)" + } + small { "{community.memberships} Free Memberships" } + } + span { class: "card__metric", + Icon { + icon: UserGroup, + height: 16, + width: 16, + stroke_width: 1, + fill: "var(--text-primary)" + } + small { "{community.members} Members" } + } + } + div { class: "card__tags", + for tag in community.tags { + { rsx!(Badge { class : + "badge--lavanda-dark", text : tag }) } + } + } + } + div { class: "card__cta", + IconButton { + class: "button--avatar buttom--comming-soon", + body: rsx!( + Icon { icon : ArrowRight, height : 32, width : 32, stroke_width : 2, fill : + "var(--fill-00)" } + ), + on_click: move |_| { + let path = format!("/dao/{}/initiatives", community.id); + nav.push(vec![], &path); } - } - div { class: "card__metrics", - span { class: "card__metric", - Icon { - icon: UserAdd, - height: 16, - width: 16, - stroke_width: 2, - stroke: "var(--text-primary)" - } - small { "{community.memberships} Free Memberships" } - } - span { class: "card__metric", - Icon { - icon: UserGroup, - height: 16, - width: 16, - stroke_width: 1, - fill: "var(--text-primary)" - } - small { "{community.members} Members" } - } - } - div { class: "card__tags", - for tag in community.tags { - { rsx!(Badge { class : - "badge--lavanda-dark", text : tag }) } - } - } - } - div { class: "card__cta", - IconButton { - class: "button--avatar buttom--comming-soon", - body: rsx!( - Icon { icon : ArrowRight, height : 32, width : 32, stroke_width : 2, fill : - "var(--fill-00)" } - ), - on_click: move |_| { - let path = format!("/dao/{}/initiatives", community.id); - nav.push(vec![], &path); - } - } - } - } - } - section { class: "card card--reverse", - div { class: "card__container", - div { class: "card__head", - h3 { class: "card__title", - { translate!(i18, - "dashboard.cta_cards.explore.title") } - } - } - p { class: "card__description", - { - translate!(i18, "dashboard.cta_cards.explore.description") } - } - } - div { class: "card__cta", - IconButton { - class: "button--avatar", - body: rsx!(Icon { icon : Compass, height : 32, width : 32, fill : "var(--fill-00)" }), - on_click: move |_| { - nav.push(vec![], "/explore"); - } - } - } - } - section { class: "card card--reverse", - div { class: "card__container", - div { class: "card__head", - h3 { class: "card__title", - {translate!(i18, "dashboard.cta_cards.create.title_part_one")}, - span { - DynamicText { words }, - }, - {translate!(i18, "dashboard.cta_cards.create.title_part_two")} - }, - } - p { class: "card__description", - { translate!(i18, - "dashboard.cta_cards.create.description") } - } - div { class: "card__head", - a { class: "card__learn", - { translate!(i18, "dashboard.cta_cards.create.cta") } - } - Icon { - icon: ArrowRight, - height: 20, - width: 20, - stroke_width: 1, - fill: "var(--text-tertiary)" - } - } - } - div { class: "card__cta", - IconButton { - class: "button--avatar", - size: ElementSize::Big, - body: rsx!( - Icon { icon : AddPlus, height : 32, width : 32, stroke_width : 1.5, fill : - "var(--fill-00)" } - ), - on_click: move |_| { - tooltip.hide(); - nav.push( - vec![ - Box::new(is_chain_available(i18, timestamp, notification)), - Box::new(is_dao_owner(i18, accounts, notification)), - ], - "/onboarding", - ); - } - } - } - } + } + } + } + } + section { class: "card card--reverse", + div { class: "card__container", + div { class: "card__head", + h3 { class: "card__title", + { translate!(i18, + "dashboard.cta_cards.explore.title") } + } + } + p { class: "card__description", + { + translate!(i18, "dashboard.cta_cards.explore.description") } + } + } + div { class: "card__cta", + IconButton { + class: "button--avatar", + body: rsx!(Icon { icon : Compass, height : 32, width : 32, fill : "var(--fill-00)" }), + on_click: move |_| { + nav.push(vec![], "/explore"); + } + } + } + } + section { class: "card card--reverse", + div { class: "card__container", + div { class: "card__head", + h3 { class: "card__title", + {translate!(i18, "dashboard.cta_cards.create.title_part_one")}, + span { + DynamicText { words }, + }, + {translate!(i18, "dashboard.cta_cards.create.title_part_two")} + }, + } + p { class: "card__description", + { translate!(i18, + "dashboard.cta_cards.create.description") } + } + div { class: "card__head", + a { class: "card__learn", + { translate!(i18, "dashboard.cta_cards.create.cta") } + } + Icon { + icon: ArrowRight, + height: 20, + width: 20, + stroke_width: 1, + fill: "var(--text-tertiary)" + } + } + } + div { class: "card__cta", + IconButton { + class: "button--avatar", + size: ElementSize::Big, + body: rsx!( + Icon { icon : AddPlus, height : 32, width : 32, stroke_width : 1.5, fill : + "var(--fill-00)" } + ), + on_click: move |_| { + tooltip.hide(); + nav.push( + vec![ + Box::new(is_chain_available(i18, timestamp, notification)), + Box::new(is_dao_owner(i18, accounts, notification)), + ], + "/onboarding", + ); + } + } + } + } + } } - } - } - } + } + } div { class: "dashboard__footer grid-footer", Paginator { - to: ((communities.get_communities_by_filters( - Some(()), - filter_name().as_deref(), - filter_paginator(), - ).len() + SKIP - 1).saturating_div(SKIP)).max(1), + to: ((communities + .get_communities_by_filters( + Some(()), + filter_name().as_deref(), + filter_paginator(), + ) + .len() + SKIP - 1) + .saturating_div(SKIP)) + .max(1), on_change: move |event: PaginatorValue| { current_page.set(event.value()); on_handle_paginator.send(current_page()) diff --git a/src/pages/deposit.rs b/src/pages/deposit.rs index efbab8f..a712c38 100644 --- a/src/pages/deposit.rs +++ b/src/pages/deposit.rs @@ -66,20 +66,20 @@ pub fn Deposit() -> Element { for account in accounts.get().into_iter() { let address = account.address(); - items.push(rsx!(AccountButton { - title: account.name(), - description: address.clone(), - on_click: move |_| {} - })) + items.push(rsx!( + AccountButton { title: account.name(), description: address.clone(), on_click: move |_| {} } + )) } let mut community_items = vec![]; for community in communities.get_communities().into_iter() { - community_items.push(rsx!(AccountButton { - title: format!("{} ({})", community.name, community.id), - description: "".to_string(), - on_click: move |_| {} - })) + community_items.push(rsx!( + AccountButton { + title: format!("{} ({})", community.name, community.id), + description: "".to_string(), + on_click: move |_| {} + } + )) } let on_handle_account = use_coroutine(move |mut rx: UnboundedReceiver| async move { @@ -136,18 +136,24 @@ pub fn Deposit() -> Element { div { class: "summary summary--form", div { class: "row deposit__row", div { class: "summary__wrapper", - h4 { class: "summary__subtitle", {translate!(i18, "deposit.payment.subtitle")} } + h4 { class: "summary__subtitle", + {translate!(i18, "deposit.payment.subtitle")} + } div { class: "payment__methods", CheckboxCard { id: "a".to_string(), name: String::from("management"), checked: matches!(*payment_selected.read(), PaymentMethods::KUSAMA), class: "checkbox-card--payment", - body: rsx!( - PaymentMethod { title : translate!(i18, "deposit.payment.methods.kusama.title"), - fee : translate!(i18, "deposit.payment.methods.kusama.fee"), icon : rsx!(Icon { - icon : KusamaLogo, height : 20, width : 20, fill : "var(--fill-600)" }), } - ), + body: rsx! { + PaymentMethod { + title: translate!(i18, "deposit.payment.methods.kusama.title"), + fee: translate!(i18, "deposit.payment.methods.kusama.fee"), + icon: rsx! { + Icon { icon: KusamaLogo, height: 20, width: 20, fill: "var(--fill-600)" } + } + } + }, on_change: move |_| { payment_selected.set(PaymentMethods::KUSAMA); } @@ -158,12 +164,15 @@ pub fn Deposit() -> Element { checked: matches!(*payment_selected.read(), PaymentMethods::Card), soon: true, class: "checkbox-card--payment", - body: rsx!( - PaymentMethod { title : translate!(i18, "deposit.payment.methods.card.title"), - fee : translate!(i18, "deposit.payment.methods.card.fee", fee : 5), icon : - rsx!(Icon { icon : BankCardLine, height : 20, width : 20, fill : - "var(--fill-600)" }), } - ), + body: rsx! { + PaymentMethod { + title: translate!(i18, "deposit.payment.methods.card.title"), + fee: translate!(i18, "deposit.payment.methods.card.fee", fee : 5), + icon: rsx! { + Icon { icon: BankCardLine, height: 20, width: 20, fill: "var(--fill-600)" } + } + } + }, on_change: move |_| { payment_selected.set(PaymentMethods::Card); } @@ -174,12 +183,15 @@ pub fn Deposit() -> Element { checked: matches!(*payment_selected.read(), PaymentMethods::Paypal), soon: true, class: "checkbox-card--payment", - body: rsx!( - PaymentMethod { title : translate!(i18, "deposit.payment.methods.paypal.title"), - fee : translate!(i18, "deposit.payment.methods.paypal.fee", fee : 5), icon : - rsx!(Icon { icon : PaypalLogo, height : 20, width : 20, fill : "var(--fill-600)" - }), } - ), + body: rsx! { + PaymentMethod { + title: translate!(i18, "deposit.payment.methods.paypal.title"), + fee: translate!(i18, "deposit.payment.methods.paypal.fee", fee : 5), + icon: rsx! { + Icon { icon: PaypalLogo, height: 20, width: 20, fill: "var(--fill-600)" } + } + } + }, on_change: move |_| { payment_selected.set(PaymentMethods::Paypal); } @@ -190,12 +202,15 @@ pub fn Deposit() -> Element { checked: matches!(*payment_selected.read(), PaymentMethods::PSE), soon: true, class: "checkbox-card--payment", - body: rsx!( - PaymentMethod { title : translate!(i18, "deposit.payment.methods.pse.title"), - fee : translate!(i18, "deposit.payment.methods.pse.fee", fee : 3), icon : - rsx!(Icon { icon : PaypalLogo, height : 20, width : 20, fill : "var(--fill-600)" - }), } - ), + body: rsx! { + PaymentMethod { + title: translate!(i18, "deposit.payment.methods.pse.title"), + fee: translate!(i18, "deposit.payment.methods.pse.fee", fee : 3), + icon: rsx! { + Icon { icon: PaypalLogo, height: 20, width: 20, fill: "var(--fill-600)" } + } + } + }, on_change: move |_| { payment_selected.set(PaymentMethods::PSE); } @@ -206,11 +221,15 @@ pub fn Deposit() -> Element { checked: matches!(*payment_selected.read(), PaymentMethods::ETH), soon: true, class: "checkbox-card--payment", - body: rsx!( - PaymentMethod { title : translate!(i18, "deposit.payment.methods.eth.title"), - fee : translate!(i18, "deposit.payment.methods.eth.fee"), icon : rsx!(Icon { - icon : PolygonLogo, height : 20, width : 20, fill : "var(--fill-600)" }), } - ), + body: rsx! { + PaymentMethod { + title: translate!(i18, "deposit.payment.methods.eth.title"), + fee: translate!(i18, "deposit.payment.methods.eth.fee"), + icon: rsx! { + Icon { icon: PolygonLogo, height: 20, width: 20, fill: "var(--fill-600)" } + } + } + }, on_change: move |_| { payment_selected.set(PaymentMethods::ETH); } @@ -219,7 +238,9 @@ pub fn Deposit() -> Element { } if !matches!(*payment_selected.read(), PaymentMethods::None) { div { class: "summary__wrapper", - h4 { class: "summary__subtitle", {translate!(i18, "deposit.form.title")} } + h4 { class: "summary__subtitle", + {translate!(i18, "deposit.form.title")} + } div { class: "deposit__form__inputs", div { class: "account__options", Tab { @@ -296,7 +317,9 @@ pub fn Deposit() -> Element { placeholder: translate!(i18, "deposit.form.amount.placeholder"), label: translate!(i18, "deposit.form.amount.label"), error: None, - right_text: rsx!(span { class : "input--right__text", "KSM" }), + right_text: rsx! { + span { class: "input--right__text", "KSM" } + }, on_input: move |event: Event| { deposit .deposit_mut() @@ -322,10 +345,17 @@ pub fn Deposit() -> Element { body: translate!(i18, "deposit.tips.loading.description"), show: true, }); - let (destination, amount, to_community) = deposit.get_deposit().to_deposit().map_err(|e| match e { - DepositError::MalformedAddress => translate!(i18, "errors.wallet.account_address"), - DepositError::InvalidAmount => translate!(i18, "errors.form.invalid_amount"), - })?; + let (destination, amount, to_community) = deposit + .get_deposit() + .to_deposit() + .map_err(|e| match e { + DepositError::MalformedAddress => { + translate!(i18, "errors.wallet.account_address") + } + DepositError::InvalidAmount => { + translate!(i18, "errors.form.invalid_amount") + } + })?; let destination = convert_to_jsvalue(&destination) .map_err(|_| { log::warn!("Malformed dest account"); @@ -338,7 +368,10 @@ pub fn Deposit() -> Element { translate!(i18, "errors.form.deposit_failed") })?; tooltip.hide(); - notification.handle_success(&translate!(i18, "deposit.tips.created.description")); + notification + .handle_success( + &translate!(i18, "deposit.tips.created.description"), + ); nav.push(vec![], "/account"); Ok::<(), String>(()) } diff --git a/src/pages/explore.rs b/src/pages/explore.rs index 2b90756..33bca48 100644 --- a/src/pages/explore.rs +++ b/src/pages/explore.rs @@ -97,10 +97,15 @@ pub fn Explore() -> Element { IconButton { class: "button--avatar desktop", size: ElementSize::Medium, - body: rsx!( - Icon { icon : AddPlus, height : 26, width : 26, stroke_width : 1.5, fill : - "var(--fill-00)" } - ), + body: rsx! { + Icon { + icon: AddPlus, + height: 26, + width: 26, + stroke_width: 1.5, + fill: "var(--fill-00)" + } + }, on_click: move |_| { tooltip.hide(); nav.push( @@ -260,7 +265,7 @@ pub fn Explore() -> Element { } div { class: "dashboard__footer grid-footer", Paginator { - to: (communities.get_communities().len() + SKIP - 1 ).saturating_div(SKIP).max(1), + to: (communities.get_communities().len() + SKIP - 1).saturating_div(SKIP).max(1), on_change: move |event: PaginatorValue| { current_page.set(event.value()); on_handle_paginator.send(current_page()) diff --git a/src/pages/initiative.rs b/src/pages/initiative.rs index b12e190..44f0319 100644 --- a/src/pages/initiative.rs +++ b/src/pages/initiative.rs @@ -7,7 +7,7 @@ use crate::{ molecules::{InitiativeActions, InitiativeInfo}, }, hooks::{ - use_initiative::{use_initiative, InitiativeData, InitiativeInfoContent, InitiativeInitContent}, use_notification::use_notification, use_our_navigator::use_our_navigator, use_session::use_session, use_spaces_client::use_spaces_client, use_tooltip::{use_tooltip, TooltipItem} + use_initiative::{use_initiative, ActionItem, InitiativeData, InitiativeInfoContent, InitiativeInitContent, TransferItem}, use_notification::use_notification, use_our_navigator::use_our_navigator, use_session::use_session, use_spaces_client::use_spaces_client, use_tooltip::{use_tooltip, TooltipItem} }, pages::onboarding::convert_to_jsvalue, services::{ @@ -93,21 +93,45 @@ pub fn Initiative(id: u16) -> Element { StepCard { name: translate!(i18, "initiative.steps.info.label"), checked: matches!(*onboarding_step.read(), InitiativeStep::Info), - body: rsx!( - div { class : "step-card__info", span { class : "step-card__title", { - translate!(i18, "initiative.steps.info.label") } } IconButton { variant : - IconButtonVariant::Round, size : ElementSize::Big, class : - "button--drop bg--transparent", body : rsx!(Icon { class : if matches!(* - onboarding_step.read(), InitiativeStep::Info) { "rotate-180" } else { "rotate-0" - }, icon : Arrow, height : 24, width : 24, stroke_width : 2, stroke : - "var(--fill-400)" }), on_click : move | _ | { if matches!(* onboarding_step - .read(), InitiativeStep::Info) { onboarding_step.set(InitiativeStep::None); } - else { onboarding_step.set(InitiativeStep::Info); } } } } - ), - editable: rsx!( - div { class : "step-card__editable", InitiativeInfo { error : - handle_required_inputs() } } - ), + body: rsx! { + div { class: "step-card__info", + span { class: "step-card__title", + { + translate!(i18, "initiative.steps.info.label") } + } + IconButton { + variant: IconButtonVariant::Round, + size: ElementSize::Big, + class: "button--drop bg--transparent", + body: rsx! { + Icon { + class: if matches!(*onboarding_step.read(), InitiativeStep::Info) { + "rotate-180" + } else { + "rotate-0" + }, + icon: Arrow, + height: 24, + width: 24, + stroke_width: 2, + stroke: "var(--fill-400)" + } + }, + on_click: move |_| { + if matches!(*onboarding_step.read(), InitiativeStep::Info) { + onboarding_step.set(InitiativeStep::None); + } else { + onboarding_step.set(InitiativeStep::Info); + } + } + } + } + }, + editable: rsx! { + div { class: "step-card__editable", + InitiativeInfo { error: handle_required_inputs() } + } + }, on_change: move |_| { onboarding_step.set(InitiativeStep::Info); } @@ -115,18 +139,43 @@ pub fn Initiative(id: u16) -> Element { StepCard { name: translate!(i18, "initiative.steps.actions.label"), checked: matches!(*onboarding_step.read(), InitiativeStep::Actions), - body: rsx!( - div { class : "step-card__info", span { class : "step-card__title", { - translate!(i18, "initiative.steps.actions.label") } } IconButton { variant : - IconButtonVariant::Round, size : ElementSize::Big, class : - "button--drop bg--transparent", body : rsx!(Icon { class : if matches!(* - onboarding_step.read(), InitiativeStep::Actions) { "rotate-180" } else { - "rotate-0" }, icon : Arrow, height : 24, width : 24, stroke_width : 2, stroke : - "var(--fill-400)" }), on_click : move | _ | { if matches!(* onboarding_step - .read(), InitiativeStep::Actions) { onboarding_step.set(InitiativeStep::None); } - else { onboarding_step.set(InitiativeStep::Actions); } } } } - ), - editable: rsx!(div { class : "step-card__editable", InitiativeActions {} }), + body: rsx! { + div { class: "step-card__info", + span { class: "step-card__title", + { + translate!(i18, "initiative.steps.actions.label") } + } + IconButton { + variant: IconButtonVariant::Round, + size: ElementSize::Big, + class: "button--drop bg--transparent", + body: rsx! { + Icon { + class: if matches!(*onboarding_step.read(), InitiativeStep::Actions) { + "rotate-180" + } else { + "rotate-0" + }, + icon: Arrow, + height: 24, + width: 24, + stroke_width: 2, + stroke: "var(--fill-400)" + } + }, + on_click: move |_| { + if matches!(*onboarding_step.read(), InitiativeStep::Actions) { + onboarding_step.set(InitiativeStep::None); + } else { + onboarding_step.set(InitiativeStep::Actions); + } + } + } + } + }, + editable: rsx! { + div { class: "step-card__editable", InitiativeActions {} } + }, on_change: move |_| { onboarding_step.set(InitiativeStep::Actions); } @@ -211,6 +260,31 @@ pub fn Initiative(id: u16) -> Element { .map(|v| v.serialize_vote_type()) .collect::>(); log::info!("votiong_open_gov_action {:?}", votiong_open_gov_action); + let community_transfer_action = initiative + .get_actions() + .into_iter() + .filter_map(|action| { + match action { + ActionItem::CommunityTransfer(community_transfer_action) => { + Some( + community_transfer_action + .transfers + .clone() + .into_iter() + .filter_map(|transfer| { + if transfer.value > 0 { Some(transfer) } else { None } + }) + .collect::>(), + ) + } + _ => None, + } + }) + .collect::>>(); + let community_transfer_action = community_transfer_action + .into_iter() + .flat_map(|v| v.into_iter()) + .collect::>(); let community_transfer_action = initiative.filter_valid_community_transfer(); log::info!("community_transfer_action {:?}", community_transfer_action); let votiong_open_gov_action = convert_to_jsvalue( @@ -221,11 +295,12 @@ pub fn Initiative(id: u16) -> Element { translate!(i18, "errors.form.initiative_creation") })?; let community_transfer_action = convert_to_jsvalue( - &community_transfer_action, - ).map_err(|_| { - log::warn!("Malformed voting open gov"); - translate!(i18, "errors.form.initiative_creation") - })?; + &community_transfer_action, + ) + .map_err(|_| { + log::warn!("Malformed voting open gov"); + translate!(i18, "errors.form.initiative_creation") + })?; let treasury_action = convert_to_jsvalue(&treasury_action) .map_err(|_| { log::warn!("Malformed membership accounts add"); @@ -262,7 +337,7 @@ pub fn Initiative(id: u16) -> Element { membership_accounts_remove, treasury_action, votiong_open_gov_action, - community_transfer_action + community_transfer_action, ) .await .map_err(|e| { diff --git a/src/pages/initiatives.rs b/src/pages/initiatives.rs index 478b7b1..9babd24 100644 --- a/src/pages/initiatives.rs +++ b/src/pages/initiatives.rs @@ -184,10 +184,15 @@ pub fn Initiatives(id: u16) -> Element { IconButton { class: "button--avatar desktop", size: ElementSize::Medium, - body: rsx!( - Icon { icon : AddPlus, height : 26, width : 26, stroke_width : 1.5, fill : - "var(--fill-00)" } - ), + body: rsx! { + Icon { + icon: AddPlus, + height: 26, + width: 26, + stroke_width: 1.5, + fill: "var(--fill-00)" + } + }, on_click: move |_| { tooltip.hide(); let path = format!("/dao/{}/initiative", id); @@ -197,63 +202,63 @@ pub fn Initiatives(id: u16) -> Element { } } div { class: "dashboard__communities", - { if initiative_state.is_loading() { - rsx! { - CardSkeleton {} - } - } else { + { if initiative_state.is_loading() { rsx! { - for initiative in filtered_initiatives() { - section { class: "card", - div { class: "card__container", - div { class: "card__head", - h3 { class: "card__title", "{initiative.info.name}" } - } - p { class: "card__description", "" } - div { class: "card__metrics", - span { class: "card__metric", - Icon { icon: CircleCheck, height: 16, width: 16, fill: "var(--text-primary)" } - small { "{initiative.ongoing.tally.ayes} Aye" } + CardSkeleton {} + } + } else { + rsx! { + for initiative in filtered_initiatives() { + section { class: "card", + div { class: "card__container", + div { class: "card__head", + h3 { class: "card__title", "{initiative.info.name}" } } - span { class: "card__metric", - Icon { - icon: StopSign, - height: 16, - width: 16, - stroke_width: 2, - stroke: "var(--text-primary)" + p { class: "card__description", "" } + div { class: "card__metrics", + span { class: "card__metric", + Icon { icon: CircleCheck, height: 16, width: 16, fill: "var(--text-primary)" } + small { "{initiative.ongoing.tally.ayes} Aye" } + } + span { class: "card__metric", + Icon { + icon: StopSign, + height: 16, + width: 16, + stroke_width: 2, + stroke: "var(--text-primary)" + } + small { "{initiative.ongoing.tally.nays} Nay" } } - small { "{initiative.ongoing.tally.nays} Nay" } } - } - div { class: "card__tags", - for tag in initiative.clone().info.tags { - { rsx!(Badge { - class : "badge--lavanda-dark", text : tag }) } + div { class: "card__tags", + for tag in initiative.clone().info.tags { + { rsx!(Badge { + class : "badge--lavanda-dark", text : tag }) } + } } } - } - div { class: "card__cta", - IconButton { - class: "button--avatar buttom--comming-soon", - body: rsx!( - Icon { icon : ArrowRight, height : 32, width : 32, stroke_width : 2, fill : - "var(--fill-00)" } - ), - on_click: move |_| { - tooltip.hide(); - initiative_wrapper.set(Some(initiative.clone())); - let path = format!("/dao/{}/vote/{}", id, initiative.id); - nav.push(vec![], &path); + div { class: "card__cta", + IconButton { + class: "button--avatar buttom--comming-soon", + body: rsx!( + Icon { icon : ArrowRight, height : 32, width : 32, stroke_width : 2, fill : + "var(--fill-00)" } + ), + on_click: move |_| { + tooltip.hide(); + initiative_wrapper.set(Some(initiative.clone())); + let path = format!("/dao/{}/vote/{}", id, initiative.id); + nav.push(vec![], &path); + } } } } } } + } - - } - } + }, section { class: "card card--reverse", div { class: "card__container", div { class: "card__head", @@ -278,10 +283,15 @@ pub fn Initiatives(id: u16) -> Element { IconButton { class: "button--avatar", size: ElementSize::Big, - body: rsx!( - Icon { icon : AddPlus, height : 32, width : 32, stroke_width : 1.5, fill : - "var(--fill-00)" } - ), + body: rsx! { + Icon { + icon: AddPlus, + height: 32, + width: 32, + stroke_width: 1.5, + fill: "var(--fill-00)" + } + }, on_click: move |_| { tooltip.hide(); let path = format!("/dao/{}/initiative", id); diff --git a/src/pages/login.rs b/src/pages/login.rs index 847062c..b810f21 100644 --- a/src/pages/login.rs +++ b/src/pages/login.rs @@ -102,7 +102,9 @@ pub fn Login() -> Element { width: 36, fill: "var(--state-primary-active)" } - span { class: "icon-text__title", {translate!(i18, "login.opportunities.connect")} } + span { class: "icon-text__title", + {translate!(i18, "login.opportunities.connect")} + } } li { class: "icon-text", Icon { @@ -141,9 +143,9 @@ pub fn Login() -> Element { text: translate!(i18, "header.cta.connect"), status: None, variant: Variant::Secondary, - right_icon: rsx!( - Icon { icon : Polkadot, height : 20, width : 20, fill : "var(--text-primary)" } - ), + right_icon: rsx! { + Icon { icon: Polkadot, height: 20, width: 20, fill: "var(--text-primary)" } + }, on_click: move |_| { spawn( async move { diff --git a/src/pages/vote.rs b/src/pages/vote.rs index c85b3bb..4feba66 100644 --- a/src/pages/vote.rs +++ b/src/pages/vote.rs @@ -253,10 +253,10 @@ pub fn Vote(id: u16, initiativeid: u16) -> Element { text: format!("{}: ", translate!(i18, "governance.description.details.by")), size: ElementSize::Medium, variant: KeyValueVariant::Secondary, - body: rsx!( + body: rsx! { { let hex_string = hex::encode(& initiative_wrapper.ongoing.submission_deposit .who); format!("0x{}", hex_string) } - ) + } } } div { class: "steps__wrapper", @@ -278,7 +278,7 @@ pub fn Vote(id: u16, initiativeid: u16) -> Element { ActionItem::AddMembers(action) => action.members.len(), ActionItem::KusamaTreasury(action) => action.periods.len(), ActionItem::VotingOpenGov(action) => action.proposals.len(), - ActionItem::CommunityTransfer(action) => action.transfers.len() + ActionItem::CommunityTransfer(action) => action.transfers.len(), } }) .sum::() @@ -390,7 +390,9 @@ pub fn Vote(id: u16, initiativeid: u16) -> Element { variant: Variant::Secondary, on_click: move |_| { handle_vote(true) }, status: None, - left_icon: rsx!(Icon { icon : CircleCheck, height : 16, width : 16, fill : "#56C95F" }) + left_icon: rsx! { + Icon { icon: CircleCheck, height: 16, width: 16, fill: "#56C95F" } + } } Button { class: "vote-cta", @@ -399,10 +401,9 @@ pub fn Vote(id: u16, initiativeid: u16) -> Element { variant: Variant::Secondary, on_click: move |_| { handle_vote(false) }, status: None, - left_icon: rsx!( - Icon { icon : StopSign, height : 16, width : 16, stroke_width : 2, stroke : - "#f44336bd" } - ) + left_icon: rsx! { + Icon { icon: StopSign, height: 16, width: 16, stroke_width: 2, stroke: "#f44336bd" } + } } } } @@ -422,13 +423,17 @@ pub fn Vote(id: u16, initiativeid: u16) -> Element { class: "key-value--row", text: "Threshold", size: ElementSize::Medium, - body: rsx!({ format!("{:.1}%", approval_threshold()) }) + body: rsx! { + { format!("{:.1}%", approval_threshold()) } + } } KeyValue { class: "key-value--row", text: "Current approval", size: ElementSize::Medium, - body: rsx!({ format!("{:.1}%", votes_statistics().percent_aye()) }) + body: rsx! { + { format!("{:.1}%", votes_statistics().percent_aye()) } + } } } } @@ -461,16 +466,18 @@ pub fn Vote(id: u16, initiativeid: u16) -> Element { class: "key-value--row", text: "Paricipation threshold", size: ElementSize::Medium, - body: rsx!({ format!("{:.1}%", participation_threshold()) }) + body: rsx! { + { format!("{:.1}%", participation_threshold()) } + } } KeyValue { class: "key-value--row", text: "Current support", size: ElementSize::Medium, - body: rsx!( + body: rsx! { { let consumed_percent = 100.0 / members() as f64 * votes_statistics().total() as f64; format!("{:.1}%", consumed_percent) } - ) + } } } } diff --git a/src/pages/withdraw.rs b/src/pages/withdraw.rs index 20ca6d2..eadac19 100644 --- a/src/pages/withdraw.rs +++ b/src/pages/withdraw.rs @@ -62,11 +62,9 @@ pub fn Withdraw() -> Element { for account in accounts.get().into_iter() { let address = account.address(); - items.push(rsx!(AccountButton { - title: account.name(), - description: address.clone(), - on_click: move |_| {} - })) + items.push(rsx!( + AccountButton { title: account.name(), description: address.clone(), on_click: move |_| {} } + )) } let on_handle_account = use_coroutine(move |mut rx: UnboundedReceiver| async move { @@ -109,11 +107,15 @@ pub fn Withdraw() -> Element { name: String::from("management"), checked: matches!(*payment_selected.read(), PaymentMethods::KUSAMA), class: "checkbox-card--payment", - body: rsx!( - PaymentMethod { title : translate!(i18, "withdraw.payment.methods.kusama.title"), - fee : translate!(i18, "withdraw.payment.methods.kusama.fee"), icon : rsx!(Icon { - icon : KusamaLogo, height : 20, width : 20, fill : "var(--fill-600)" }), } - ), + body: rsx! { + PaymentMethod { + title: translate!(i18, "withdraw.payment.methods.kusama.title"), + fee: translate!(i18, "withdraw.payment.methods.kusama.fee"), + icon: rsx! { + Icon { icon: KusamaLogo, height: 20, width: 20, fill: "var(--fill-600)" } + } + } + }, on_change: move |_| { payment_selected.set(PaymentMethods::KUSAMA); } @@ -124,12 +126,15 @@ pub fn Withdraw() -> Element { checked: matches!(*payment_selected.read(), PaymentMethods::Card), soon: true, class: "checkbox-card--payment", - body: rsx!( - PaymentMethod { title : translate!(i18, "withdraw.payment.methods.card.title"), - fee : translate!(i18, "withdraw.payment.methods.card.fee", fee : 5), icon : - rsx!(Icon { icon : BankCardLine, height : 20, width : 20, fill : - "var(--fill-600)" }), } - ), + body: rsx! { + PaymentMethod { + title: translate!(i18, "withdraw.payment.methods.card.title"), + fee: translate!(i18, "withdraw.payment.methods.card.fee", fee : 5), + icon: rsx! { + Icon { icon: BankCardLine, height: 20, width: 20, fill: "var(--fill-600)" } + } + } + }, on_change: move |_| { payment_selected.set(PaymentMethods::Card); } @@ -140,12 +145,15 @@ pub fn Withdraw() -> Element { checked: matches!(*payment_selected.read(), PaymentMethods::Paypal), soon: true, class: "checkbox-card--payment", - body: rsx!( - PaymentMethod { title : translate!(i18, "withdraw.payment.methods.paypal.title"), - fee : translate!(i18, "withdraw.payment.methods.paypal.fee", fee : 5), icon : - rsx!(Icon { icon : PaypalLogo, height : 20, width : 20, fill : "var(--fill-600)" - }), } - ), + body: rsx! { + PaymentMethod { + title: translate!(i18, "withdraw.payment.methods.paypal.title"), + fee: translate!(i18, "withdraw.payment.methods.paypal.fee", fee : 5), + icon: rsx! { + Icon { icon: PaypalLogo, height: 20, width: 20, fill: "var(--fill-600)" } + } + } + }, on_change: move |_| { payment_selected.set(PaymentMethods::Paypal); } @@ -156,12 +164,15 @@ pub fn Withdraw() -> Element { checked: matches!(*payment_selected.read(), PaymentMethods::PSE), soon: true, class: "checkbox-card--payment", - body: rsx!( - PaymentMethod { title : translate!(i18, "withdraw.payment.methods.pse.title"), - fee : translate!(i18, "withdraw.payment.methods.pse.fee", fee : 3), icon : - rsx!(Icon { icon : PaypalLogo, height : 20, width : 20, fill : "var(--fill-600)" - }), } - ), + body: rsx! { + PaymentMethod { + title: translate!(i18, "withdraw.payment.methods.pse.title"), + fee: translate!(i18, "withdraw.payment.methods.pse.fee", fee : 3), + icon: rsx! { + Icon { icon: PaypalLogo, height: 20, width: 20, fill: "var(--fill-600)" } + } + } + }, on_change: move |_| { payment_selected.set(PaymentMethods::PSE); } @@ -172,11 +183,15 @@ pub fn Withdraw() -> Element { checked: matches!(*payment_selected.read(), PaymentMethods::ETH), soon: true, class: "checkbox-card--payment", - body: rsx!( - PaymentMethod { title : translate!(i18, "withdraw.payment.methods.eth.title"), - fee : translate!(i18, "withdraw.payment.methods.eth.fee"), icon : rsx!(Icon { - icon : PolygonLogo, height : 20, width : 20, fill : "var(--fill-600)" }), } - ), + body: rsx! { + PaymentMethod { + title: translate!(i18, "withdraw.payment.methods.eth.title"), + fee: translate!(i18, "withdraw.payment.methods.eth.fee"), + icon: rsx! { + Icon { icon: PolygonLogo, height: 20, width: 20, fill: "var(--fill-600)" } + } + } + }, on_change: move |_| { payment_selected.set(PaymentMethods::ETH); } @@ -241,7 +256,9 @@ pub fn Withdraw() -> Element { placeholder: "Amount", label: "Amount", error: None, - right_text: rsx!(span { class : "input--right__text", "KSM" }), + right_text: rsx! { + span { class: "input--right__text", "KSM" } + }, on_input: move |event: Event| { withdraw .withdraw_mut()