From b27944e8eeda1cad83da53d53f3f4de23724ef50 Mon Sep 17 00:00:00 2001 From: Daniel Olano Date: Thu, 22 Aug 2024 16:04:03 +0200 Subject: [PATCH] Format code and rsx --- build.rs | 14 +- justfile | 10 +- src/components/atoms/account.rs | 25 +- src/components/atoms/action_request.rs | 14 +- src/components/atoms/attach.rs | 148 +++--- src/components/atoms/avatar.rs | 31 +- src/components/atoms/badge.rs | 7 +- src/components/atoms/bar.rs | 40 +- src/components/atoms/button.rs | 32 +- src/components/atoms/card.rs | 67 +-- src/components/atoms/checkbox_card.rs | 26 +- src/components/atoms/combo_input.rs | 95 ++-- src/components/atoms/dropdown.rs | 56 +-- src/components/atoms/icon_button.rs | 8 +- src/components/atoms/icons/add_plus.rs | 2 - src/components/atoms/icons/arrow.rs | 2 - src/components/atoms/icons/arrow_left.rs | 2 - src/components/atoms/icons/arrow_right.rs | 2 - src/components/atoms/icons/arrow_up.rs | 2 - src/components/atoms/icons/arrow_up_down.rs | 2 - src/components/atoms/icons/chat.rs | 2 - src/components/atoms/icons/chevron_left.rs | 2 - src/components/atoms/icons/chevron_right.rs | 2 - src/components/atoms/icons/circle_check.rs | 2 - src/components/atoms/icons/circle_shape.rs | 2 - src/components/atoms/icons/close.rs | 2 - src/components/atoms/icons/compass.rs | 2 - src/components/atoms/icons/filter.rs | 2 - src/components/atoms/icons/glyph.rs | 9 +- src/components/atoms/icons/hamburguer.rs | 2 - src/components/atoms/icons/home.rs | 2 - src/components/atoms/icons/icon.rs | 8 +- src/components/atoms/icons/key_fill.rs | 2 - src/components/atoms/icons/medall_fill.rs | 2 - src/components/atoms/icons/messages.rs | 2 - src/components/atoms/icons/minus_circle.rs | 8 +- src/components/atoms/icons/mod.rs | 1 - src/components/atoms/icons/monetization.rs | 7 +- src/components/atoms/icons/plus.rs | 2 - src/components/atoms/icons/profile.rs | 2 - src/components/atoms/icons/search.rs | 2 - src/components/atoms/icons/settings.rs | 2 - .../atoms/icons/shield_keyhole_fill.rs | 2 - src/components/atoms/icons/stop_sign.rs | 2 - src/components/atoms/icons/substract_line.rs | 2 - src/components/atoms/icons/suitcase.rs | 2 - src/components/atoms/icons/team_fill.rs | 6 +- src/components/atoms/icons/upload_export.rs | 2 - src/components/atoms/icons/user.rs | 2 - src/components/atoms/icons/user_add.rs | 2 - src/components/atoms/icons/user_group.rs | 8 +- src/components/atoms/icons/virto_logo.rs | 2 - src/components/atoms/icons/votes.rs | 2 - src/components/atoms/icons/warning_sign.rs | 9 +- src/components/atoms/input.rs | 53 +-- src/components/atoms/input_tags.rs | 136 ++---- src/components/atoms/key_value.rs | 16 +- src/components/atoms/markdown.rs | 46 +- src/components/atoms/mod.rs | 1 - src/components/atoms/notification.rs | 4 - src/components/atoms/radio_button.rs | 13 +- src/components/atoms/search_input.rs | 26 +- src/components/atoms/step.rs | 23 +- src/components/atoms/step_card.rs | 12 +- src/components/atoms/subtitle.rs | 6 +- src/components/atoms/tab.rs | 8 +- src/components/atoms/textarea.rs | 9 +- src/components/atoms/title.rs | 6 +- src/components/atoms/tooltip.rs | 5 +- .../molecules/action_request_list.rs | 79 ++-- src/components/molecules/actions/members.rs | 101 ++-- src/components/molecules/actions/mod.rs | 1 - src/components/molecules/actions/treasury.rs | 153 +++---- src/components/molecules/actions/voting.rs | 254 +++------- src/components/molecules/header.rs | 339 +++++--------- .../molecules/initiative/actions.rs | 125 ++--- .../molecules/initiative/confirmation.rs | 8 +- src/components/molecules/initiative/info.rs | 50 +- src/components/molecules/initiative/mod.rs | 1 - .../molecules/initiative/settings.rs | 20 +- src/components/molecules/mod.rs | 1 - src/components/molecules/onboarding/basics.rs | 45 +- src/components/molecules/onboarding/invite.rs | 138 ++---- .../molecules/onboarding/management.rs | 59 +-- src/components/molecules/onboarding/mod.rs | 1 - src/components/molecules/sidebar.rs | 125 ++--- src/components/molecules/tabs.rs | 16 +- src/hooks/use_accounts.rs | 14 - src/hooks/use_attach.rs | 9 - src/hooks/use_communities.rs | 12 - src/hooks/use_connect_wallet.rs | 39 +- src/hooks/use_initiative.rs | 122 ++--- src/hooks/use_language.rs | 21 +- src/hooks/use_notification.rs | 14 - src/hooks/use_onboard.rs | 38 +- src/hooks/use_our_navigator.rs | 15 +- src/hooks/use_paginator.rs | 14 +- src/hooks/use_session.rs | 38 +- src/hooks/use_spaces_client.rs | 5 - src/hooks/use_startup.rs | 50 +- src/hooks/use_theme.rs | 21 +- src/hooks/use_timestamp.rs | 8 - src/hooks/use_tooltip.rs | 11 +- src/hooks/use_vote.rs | 9 - src/layouts/authenticated.rs | 16 +- src/layouts/onboard.rs | 2 - src/lib.rs | 6 - src/main.rs | 30 +- src/middlewares/is_chain_available.rs | 9 +- src/middlewares/is_dao_owner.rs | 3 - src/pages/dashboard.rs | 220 +++------ src/pages/explore.rs | 186 +++----- src/pages/initiative.rs | 426 ++++++++--------- src/pages/initiatives.rs | 201 +++----- src/pages/not_found.rs | 1 - src/pages/onboarding.rs | 269 +++++------ src/pages/route.rs | 39 +- src/pages/vote.rs | 433 +++++++----------- src/services/bot/client.rs | 47 +- src/services/bot/types.rs | 5 - src/services/kreivo/balances.rs | 16 +- src/services/kreivo/communities.rs | 15 +- src/services/kreivo/community_memberships.rs | 118 ++--- src/services/kreivo/community_referenda.rs | 66 +-- src/services/kreivo/community_track.rs | 66 +-- src/services/kreivo/identity.rs | 51 +-- src/services/kreivo/preimage.rs | 36 +- src/services/kreivo/system.rs | 14 +- src/services/kreivo/timestamp.rs | 14 +- src/services/kusama/system.rs | 14 +- src/services/kusama/timestamp.rs | 14 +- 131 files changed, 1773 insertions(+), 3557 deletions(-) diff --git a/build.rs b/build.rs index ddda75b..8a76c60 100644 --- a/build.rs +++ b/build.rs @@ -1,15 +1,10 @@ use std::{fs, path::PathBuf}; - const STYLES_IN: &str = "public/styles"; const STYLES_OUT: &str = "public/css-out"; - fn main() { println!("cargo:rerun-if-changed=src/styles"); - let files = fs::read_dir(STYLES_IN).expect("It should read a dir"); - _ = fs::create_dir(STYLES_OUT); - for file in files { let file = file.expect("It should read a file"); let path = file.path(); @@ -19,12 +14,11 @@ fn main() { .expect("It should parse a file name") .strip_suffix(".scss") .expect("It should remove a suffix .scss"); - let out_path = PathBuf::from(STYLES_OUT).join(format!("{}.css", raw_name)); - - let scss_options = grass::Options::default().style(grass::OutputStyle::Compressed); - let css = - grass::from_path(path, &scss_options).expect("It should convert a .scss block to css"); + let scss_options = grass::Options::default() + .style(grass::OutputStyle::Compressed); + let css = grass::from_path(path, &scss_options) + .expect("It should convert a .scss block to css"); fs::write(out_path, css).expect("It should write the output of a css"); } } diff --git a/justfile b/justfile index 96d0887..3cfcff9 100644 --- a/justfile +++ b/justfile @@ -1,3 +1,11 @@ -tag: +build: + dx build --release + +tag: check build #!/usr/bin/env nu git tag (open Cargo.toml | get package.version) + +check: + dx fmt --check --all-code + dx check + cargo clippy -- -D warnings diff --git a/src/components/atoms/account.rs b/src/components/atoms/account.rs index 8db7bad..86a1c54 100644 --- a/src/components/atoms/account.rs +++ b/src/components/atoms/account.rs @@ -1,30 +1,17 @@ use dioxus::prelude::*; - #[derive(PartialEq, Props, Clone)] pub struct AccountProps { title: String, description: String, on_click: EventHandler<()>, } - pub fn AccountButton(props: AccountProps) -> Element { rsx!( - button { - class: "account", - onclick: move |_| { - props.on_click.call(()) - }, - div { - class: "account__wrapper", - h3 { - class: "account__title", - {props.title} - } - p { - class: "account__description", - {props.description} - } - } - } + button { class: "account", onclick: move |_| { props.on_click.call(()) }, + div { class: "account__wrapper", + h3 { class: "account__title", { props.title } } + p { class: "account__description", { props.description } } + } + } ) } diff --git a/src/components/atoms/action_request.rs b/src/components/atoms/action_request.rs index 7a472cc..f256b00 100644 --- a/src/components/atoms/action_request.rs +++ b/src/components/atoms/action_request.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::dropdown::ElementSize; - #[derive(PartialEq, Props, Clone)] pub struct RequestProps { name: String, @@ -9,24 +7,20 @@ pub struct RequestProps { #[props(default = ElementSize::Medium)] size: ElementSize, } - pub fn ActionRequest(props: RequestProps) -> Element { let size = match props.size { ElementSize::Big => "action-request--big", ElementSize::Medium => "action-request--medium", ElementSize::Small => "action-request--small", }; - rsx!( - div { - class: "action-request {size}", + div { class: "action-request {size}", span { class: "action-request__title", - {props.name} + { + props.name } } if let Some(details) = props.details { - span { class: "action-request__details", - {details} - } + span { class: "action-request__details", { details } } } } ) diff --git a/src/components/atoms/attach.rs b/src/components/atoms/attach.rs index 05c364e..18538b0 100644 --- a/src/components/atoms/attach.rs +++ b/src/components/atoms/attach.rs @@ -1,11 +1,9 @@ use std::ops::Deref; - use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; use futures_util::TryFutureExt; use wasm_bindgen::JsCast; use web_sys::HtmlElement; - use crate::{ components::atoms::{ button::Variant as ButtonVariant, dropdown::ElementSize, @@ -13,7 +11,6 @@ use crate::{ }, hooks::use_attach::{use_attach, AttachFile}, }; - #[derive(Clone, Debug)] pub enum AttachError { NotFound, @@ -21,87 +18,75 @@ pub enum AttachError { UnknownContent, Size, } - #[derive(Clone, Debug)] pub struct FeedAttachError { explanation: String, details: String, } - #[derive(PartialEq, Debug, Clone)] pub struct AttachEvent { pub value: Vec, } - #[derive(PartialEq, Props, Clone)] pub struct AttachProps { - // value: Vec, label: Option, supported_types: Vec, cta_text: String, on_change: EventHandler, } - const MAX_FILE_SIZE: u64 = 2 * 1024 * 1024; - pub fn Attach(props: AttachProps) -> Element { let i18 = use_i18(); let mut attach = use_attach(); let mut textarea_ref = use_signal::>>(|| None); let mut error = use_signal::>(|| None); - let supported_types = props .supported_types .iter() .map(|t| t.parse::().expect("Supported mime")) .collect::>(); - let on_handle_attach = move |_| { if let Some(input_element) = textarea_ref() { input_element.click(); } }; - let on_handle_input = move |event: Event| { let supported_types = supported_types.clone(); spawn({ async move { let files = &event.files().ok_or(AttachError::NotFound)?; let fs = files.files(); - let existing_file = fs.get(0).ok_or(AttachError::NotFound)?; let name = existing_file.clone(); - let content = files .read_file(existing_file) .await .ok_or(AttachError::NotFound)?; - let infered_type = infer::get(content.deref()).ok_or(AttachError::UncoverType)?; - - let content_type: Result = infered_type.mime_type().parse(); - let content_type = content_type.map_err(|_| AttachError::UnknownContent)?; - + let infered_type = infer::get(content.deref()) + .ok_or(AttachError::UncoverType)?; + let content_type: Result = infered_type + .mime_type() + .parse(); + let content_type = content_type + .map_err(|_| AttachError::UnknownContent)?; if !supported_types.contains(&content_type) { return Err(AttachError::UncoverType); } - let blob = match content_type.type_() { mime::IMAGE => gloo::file::Blob::new(content.deref()), - mime::VIDEO => gloo::file::Blob::new_with_options( - content.deref(), - Some(infered_type.mime_type()), - ), + mime::VIDEO => { + gloo::file::Blob::new_with_options( + content.deref(), + Some(infered_type.mime_type()), + ) + } _ => gloo::file::Blob::new(content.deref()), }; - let size = blob.size().clone(); - if size > MAX_FILE_SIZE { return Err(AttachError::Size); } - let object_url = gloo::file::ObjectUrl::from(blob); - let attach_file = AttachFile { name: existing_file.to_string(), preview_url: object_url, @@ -109,90 +94,71 @@ pub fn Attach(props: AttachProps) -> Element { content_type, size, }; - attach.set(Some(attach_file.clone())); - props.on_change.call(attach_file); - Ok::<(), AttachError>(()) } - .unwrap_or_else(move |e: AttachError| { - let message_error = match e { - AttachError::NotFound => FeedAttachError { - explanation: translate!(i18, "errors.attach.not_found.explanation"), - details: translate!(i18, "errors.attach.not_found.details"), - }, - AttachError::Size => FeedAttachError { - explanation: translate!(i18, "errors.attach.size.explanation"), - details: translate!(i18, "errors.attach.size.details"), - }, - AttachError::UncoverType | AttachError::UnknownContent => FeedAttachError { - explanation: translate!(i18, "errors.attach.mime.explanation"), - details: translate!(i18, "errors.attach.mime.details"), - }, - }; - - error.set(Some(message_error)) - }) + .unwrap_or_else(move |e: AttachError| { + let message_error = match e { + AttachError::NotFound => { + FeedAttachError { + explanation: translate!( + i18, "errors.attach.not_found.explanation" + ), + details: translate!(i18, "errors.attach.not_found.details"), + } + } + AttachError::Size => { + FeedAttachError { + explanation: translate!( + i18, "errors.attach.size.explanation" + ), + details: translate!(i18, "errors.attach.size.details"), + } + } + AttachError::UncoverType | AttachError::UnknownContent => { + FeedAttachError { + explanation: translate!( + i18, "errors.attach.mime.explanation" + ), + details: translate!(i18, "errors.attach.mime.details"), + } + } + }; + error.set(Some(message_error)) + }) }); }; - rsx!( - section { - class: "attach", + section { class: "attach", if let Some(value) = props.label { label { class: "input__label", "{value}" } } if let Some(e) = error() { - div { - class: "attach__wrapper attach__wrapper--error", + div { class: "attach__wrapper attach__wrapper--error", div { class: "attach__error__header", - h4 { class: "attach__error__title", - { translate!(i18, "errors.attach.title") } - } - div { - class: "attach__close", + h4 { class: "attach__error__title", { translate!(i18, "errors.attach.title") } } + div { class: "attach__close", IconButton { 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)" - } + Icon { icon : Close, height : 28, width : 28, fill : + "var(--state-destructive-active)" } ), - on_click: move |_| { - error.set(None) - } + on_click: move |_| { error.set(None) } } } } - p { class: "attach__error__explanation", - "{e.explanation}" - } - p { class: "attach__error__details", - "{e.details}" - } + p { class: "attach__error__explanation", "{e.explanation}" } + p { class: "attach__error__details", "{e.details}" } } } else { - div { - class: "attach__wrapper", - { - attach.get_file().ok().map(|url| { - rsx!( - img { - class: "attach__preview", - src: "{url}" - } - ) - }) - } - - div { - class: "attach__cta", + div { class: "attach__wrapper", + { attach.get_file().ok().map(| url | { rsx!(img { class : + "attach__preview", src : "{url}" }) }) }, + div { class: "attach__cta", Button { text: "{props.cta_text}", status: None, @@ -206,7 +172,9 @@ pub fn Attach(props: AttachProps) -> Element { r#type: "file", class: "attach__input", onmounted: move |event| { - event.data.downcast::() + event + .data + .downcast::() .and_then(|element| element.clone().dyn_into::().ok()) .map(|html_element| textarea_ref.set(Some(Box::new(html_element.clone())))); }, diff --git a/src/components/atoms/avatar.rs b/src/components/atoms/avatar.rs index 5ff587e..2e773a2 100644 --- a/src/components/atoms/avatar.rs +++ b/src/components/atoms/avatar.rs @@ -1,11 +1,9 @@ use dioxus::prelude::*; - #[derive(PartialEq, Clone)] pub enum Variant { Round, SemiRound, } - #[derive(PartialEq, Props, Clone)] pub struct AvatarProps { name: String, @@ -15,37 +13,18 @@ pub struct AvatarProps { #[props(default = Variant::Round)] variant: Variant, } - pub fn Avatar(props: AvatarProps) -> Element { let size_avatar = format!("--avatar-size: {}px;", props.size); let avatar_style = format!("{}", size_avatar); - let variant = match props.variant { Variant::Round => "avatar--round", Variant::SemiRound => "avatar--semi-round", }; - rsx! { - match &props.uri { - Some(uri) => rsx!( - img { - class: "avatar {variant}", - style: "{avatar_style}", - src: "{uri}" - } - ), - None => { - let initial: Vec = props.name.chars().collect(); - let initial = initial[0].to_uppercase(); - - rsx!( - div{ - class: "avatar {variant}", - style: "{avatar_style}", - span{ class: "avatar--initial", "{initial}" } - } - ) - } - } + match & props.uri { Some(uri) => rsx!(img { class : "avatar {variant}", style : + "{avatar_style}", src : "{uri}" }), None => { let initial : Vec < char > = props + .name.chars().collect(); let initial = initial[0].to_uppercase(); rsx!(div { + class : "avatar {variant}", style : "{avatar_style}", span { class : + "avatar--initial", "{initial}" } }) } } } } diff --git a/src/components/atoms/badge.rs b/src/components/atoms/badge.rs index 374ddf7..f35851d 100644 --- a/src/components/atoms/badge.rs +++ b/src/components/atoms/badge.rs @@ -1,17 +1,12 @@ use dioxus::prelude::*; - #[derive(PartialEq, Props, Clone)] pub struct BadgeProps { #[props(default = "".to_string())] class: String, text: String, } - pub fn Badge(props: BadgeProps) -> Element { rsx!( - span { - class: "badge {props.class}", - {props.text} - } + span { class: "badge {props.class}", { props.text } } ) } diff --git a/src/components/atoms/bar.rs b/src/components/atoms/bar.rs index 2b4b61a..4531695 100644 --- a/src/components/atoms/bar.rs +++ b/src/components/atoms/bar.rs @@ -1,12 +1,10 @@ use dioxus::prelude::*; - #[derive(PartialEq, Clone)] pub enum Variant { Remaign, Vote, - Participation + Participation, } - #[derive(PartialEq, Props, Clone)] pub struct BarProps { left_value: f64, @@ -19,47 +17,31 @@ pub struct BarProps { #[props(default = Variant::Remaign)] variant: Variant, } - pub fn Bar(props: BarProps) -> Element { let variant = match props.variant { Variant::Remaign => "bar--remaign", Variant::Vote => "bar--vote", Variant::Participation => "bar--participation", }; - rsx!( section { - div { - class: "bar {variant}", - span { - class: "bar__content bar__content--left", - style: format!("width: {}%", props.left_value), - p { class: "votes-counter__title", - {props.left_helper} - } + div { class: "bar {variant}", + 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), - p { class: "votes-counter__title", - {props.right_helper} - } + span { class: "bar__content bar__content--right", style: format!("width: {}%", props.right_value), + p { class: "votes-counter__title", { props.right_helper } } } } - div { - class: "bar__percent", + div { class: "bar__percent", p { class: "votes-counter__percent", - {props.left_title} - } - p { class: "votes-counter__percent", - {props.right_title} + { props + .left_title } } + p { class: "votes-counter__percent", { props.right_title } } } } ) diff --git a/src/components/atoms/button.rs b/src/components/atoms/button.rs index f36a89b..083ad29 100644 --- a/src/components/atoms/button.rs +++ b/src/components/atoms/button.rs @@ -1,14 +1,11 @@ use dioxus::prelude::*; - use super::dropdown::ElementSize; - #[derive(PartialEq, Clone)] pub enum Variant { Primary, Secondary, Tertiary, } - #[derive(PartialEq, Props, Clone)] pub struct ButtonProps { #[props(default = "".to_string())] @@ -26,35 +23,28 @@ pub struct ButtonProps { left_icon: Option, right_icon: Option, } - pub fn Button(props: ButtonProps) -> Element { let variant = match props.variant { Variant::Primary => "button--primary", Variant::Secondary => "button--secondary", Variant::Tertiary => "button--tertiary", }; - let size = match props.size { ElementSize::Big => "button--big", ElementSize::Medium => "button--medium", ElementSize::Small => "button--small", }; - - let disabled = if props.disabled { - "button--disabled" - } else { - "" - }; - - let loading = if props.status.is_some() { - "button--loading" - } else { - "" - }; - + let disabled = if props.disabled { "button--disabled" } else { "" }; + let loading = if props.status.is_some() { "button--loading" } else { "" }; match &props.status { Some(s) => { - rsx!( button { class: "button {props.class} {variant} {size} {loading}", disabled: true, "{s}" } ) + rsx!( + button { + class: "button {props.class} {variant} {size} {loading}", + disabled: true, + "{s}" + } + ) } None => { rsx!( @@ -62,9 +52,9 @@ pub fn Button(props: ButtonProps) -> Element { class: "button {props.class} {variant} {size} {disabled}", disabled: props.disabled, onclick: move |event| props.on_click.call(event), - {props.left_icon} + { props.left_icon }, "{props.text}" - {props.right_icon} + { props.right_icon } } ) } diff --git a/src/components/atoms/card.rs b/src/components/atoms/card.rs index dd72124..0bb8137 100644 --- a/src/components/atoms/card.rs +++ b/src/components/atoms/card.rs @@ -1,14 +1,14 @@ use dioxus::prelude::*; - -use crate::{components::atoms::{ - avatar::Variant, ArrowRight, Avatar, Icon, IconButton, Suitcase, UserGroup, -}, pages::dashboard::Community}; - +use crate::{ + components::atoms::{ + avatar::Variant, ArrowRight, Avatar, Icon, IconButton, Suitcase, UserGroup, + }, + pages::dashboard::Community, +}; #[derive(PartialEq, Props, Clone)] pub struct CardProps { community: Community, } - pub fn Card(props: CardProps) -> Element { rsx!( section { class: "card", @@ -16,66 +16,35 @@ pub fn Card(props: CardProps) -> Element { div { class: "card__head", IconButton { body: rsx!( - Avatar { - name: "{props.community.name}", - size: 48, - uri: props.community.icon, - variant: Variant::SemiRound - } + Avatar { name : "{props.community.name}", size : 48, uri : props.community.icon, + variant : Variant::SemiRound } ), - on_click: move |_| { } + on_click: move |_| {} } - h3 { class: "card__title", - "{props.community.name}" - } - } - p { class: "card__description", - "{props.community.description}" + h3 { class: "card__title", "{props.community.name}" } } + p { class: "card__description", "{props.community.description}" } div { class: "card__metrics", span { class: "card__metric", - Icon { - icon: UserGroup, - height: 16, - width: 16, - stroke_width: 1, - fill: "var(--white)" - } - small { - "{props.community.memberships}" - } + Icon { icon: UserGroup, height: 16, width: 16, stroke_width: 1, fill: "var(--white)" } + small { "{props.community.memberships}" } } span { class: "card__metric", - Icon { - icon: Suitcase, - height: 16, - width: 16, - stroke_width: 1, - fill: "var(--white)" - } - small { - "{props.community.members}" - } + Icon { icon: Suitcase, height: 16, width: 16, stroke_width: 1, fill: "var(--white)" } + small { "{props.community.members}" } } } } - div { class: "card__cta", IconButton { class: "button--avatar", body: rsx!( - Icon { - icon: ArrowRight, - height: 16, - width: 16, - stroke_width: 2, - stroke: "var(--text-primary)" - } + Icon { icon : ArrowRight, height : 16, width : 16, stroke_width : 2, stroke : + "var(--text-primary)" } ), - on_click: move |_| { } + on_click: move |_| {} } } } ) } - diff --git a/src/components/atoms/checkbox_card.rs b/src/components/atoms/checkbox_card.rs index 8441e23..cada997 100644 --- a/src/components/atoms/checkbox_card.rs +++ b/src/components/atoms/checkbox_card.rs @@ -1,5 +1,4 @@ use dioxus::prelude::*; - #[derive(PartialEq, Props, Clone)] pub struct CheckboxCardProps { id: String, @@ -12,25 +11,18 @@ pub struct CheckboxCardProps { soon: bool, on_change: EventHandler, } - pub fn CheckboxCard(props: CheckboxCardProps) -> Element { rsx!( label { class: "checkbox-card", class: if props.soon { "checkbox-card--comming-soon" }, - div { - class: "checkbox-card__media", - {props.icon} + div { class: "checkbox-card__media", + { props + .icon } } div { - span { - class: "checkbox-card__title", - "{props.title}" - } - p { - class: "checkbox-card__description", - "{props.description}" - } + span { class: "checkbox-card__title", "{props.title}" } + p { class: "checkbox-card__description", "{props.description}" } } input { class: "checkbox__cta", @@ -38,13 +30,9 @@ pub fn CheckboxCard(props: CheckboxCardProps) -> Element { name: props.name, disabled: props.soon, checked: props.checked, - onchange: move |_| { - props.on_change.call(()) - } - } - div { - class: "checkbox-custom", + onchange: move |_| { props.on_change.call(()) } } + div { class: "checkbox-custom" } } ) } diff --git a/src/components/atoms/combo_input.rs b/src/components/atoms/combo_input.rs index 138c1ac..6a7235e 100644 --- a/src/components/atoms/combo_input.rs +++ b/src/components/atoms/combo_input.rs @@ -1,23 +1,20 @@ use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; - -use crate::components::atoms::{dropdown::DropdownItem, input::InputType, Dropdown, Input}; - +use crate::components::atoms::{ + dropdown::DropdownItem, input::InputType, Dropdown, Input, +}; use super::dropdown::ElementSize; - #[derive(PartialEq, Clone, Debug)] pub enum ComboInputOption { Dropdown(DropdownItem), Date(String), None, } - #[derive(PartialEq, Clone, Debug)] pub struct ComboInputValue { pub option: ComboInputOption, pub input: String, } - #[derive(PartialEq, Props, Clone)] pub struct ComboInputProps { #[props(default = "".to_string())] @@ -32,69 +29,46 @@ pub struct ComboInputProps { right_text: Option, on_change: EventHandler, } - pub fn ComboInput(props: ComboInputProps) -> Element { let i18 = use_i18(); - let mut option_value = use_signal(|| props.value.option.clone()); let mut input_value = use_signal::(|| props.value.input.clone()); - let mut items = vec![]; - let dropdown_options = use_signal::>(|| { + let dropdown_options = use_signal::< + Vec, + >(|| { let Some(options) = props.options else { - return vec![DropdownItem { - key: "Wallet".to_string(), - value: translate!(i18, "onboard.invite.form.wallet.label"), - }]; + return vec![ + DropdownItem { + key: "Wallet".to_string(), + value: translate!(i18, "onboard.invite.form.wallet.label"), + }, + ]; }; - options }); - for account in dropdown_options().clone().into_iter() { - items.push(rsx!(span { - "{account.value}" - })) + items.push(rsx!( + span { "{account.value}" } + )) } - rsx!( - div { - class: "combo-input {props.class}", + div { class: "combo-input {props.class}", match option_value() { - ComboInputOption::Date(value) => rsx!( - Input { - message: value, - size: props.size.clone(), - itype: InputType::Date, - placeholder: props.placeholder.clone(), - error: None, - on_input: move |event: Event| { - option_value.set(ComboInputOption::Date(event.value().clone())); - props.on_change.call(ComboInputValue { option: ComboInputOption::Date(event.value().clone()), input: input_value().clone() }) - }, - on_keypress: move |_| {}, - on_click: move |_| {}, - } - ), - ComboInputOption::Dropdown(value) => rsx!( - Dropdown { - class: "dropdown--left".to_string(), - value: value, - placeholder: translate!(i18, "header.cta.account"), - size: props.size.clone(), - default: None, - on_change: move |event: usize| { - let to_assign = &dropdown_options()[event]; - option_value.set(ComboInputOption::Dropdown(to_assign.clone())); - props.on_change.call(ComboInputValue { option: ComboInputOption::Dropdown(to_assign.clone()), input: input_value().clone() }) - }, - body: items - } - ), - ComboInputOption::None => { - rsx!() - } - } + ComboInputOption::Date(value) => rsx!(Input { message : value, size : props.size + .clone(), itype : InputType::Date, placeholder : props.placeholder.clone(), error + : None, on_input : move | event : Event < FormData >| { option_value + .set(ComboInputOption::Date(event.value().clone())); props.on_change + .call(ComboInputValue { option : ComboInputOption::Date(event.value().clone()), + input : input_value().clone() }) }, on_keypress : move | _ | {}, on_click : move + | _ | {}, }), ComboInputOption::Dropdown(value) => rsx!(Dropdown { class : + "dropdown--left".to_string(), value : value, placeholder : translate!(i18, + "header.cta.account"), size : props.size.clone(), default : None, on_change : + move | event : usize | { let to_assign = & dropdown_options() [event]; + option_value.set(ComboInputOption::Dropdown(to_assign.clone())); props.on_change + .call(ComboInputValue { option : ComboInputOption::Dropdown(to_assign.clone()), + input : input_value().clone() }) }, body : items }), ComboInputOption::None => { + rsx!() } }, Input { message: props.value.input.clone(), size: props.size, @@ -103,10 +77,15 @@ pub fn ComboInput(props: ComboInputProps) -> Element { right_text: props.right_text, on_input: move |event: Event| { input_value.set(event.value().clone()); - props.on_change.call(ComboInputValue { option: option_value(), input: input_value().clone() }) + props + .on_change + .call(ComboInputValue { + option: option_value(), + input: input_value().clone(), + }) }, on_keypress: move |_| {}, - on_click: move |_| {}, + on_click: move |_| {} } } ) diff --git a/src/components/atoms/dropdown.rs b/src/components/atoms/dropdown.rs index 67113cb..5ea8c32 100644 --- a/src/components/atoms/dropdown.rs +++ b/src/components/atoms/dropdown.rs @@ -1,20 +1,16 @@ use dioxus::prelude::*; - use crate::components::atoms::{Arrow, Icon}; - #[derive(PartialEq, Debug, Clone, Default)] pub struct DropdownItem { pub key: String, pub value: String, } - #[derive(PartialEq, Clone)] pub enum ElementSize { Big, Medium, Small, } - #[derive(PartialEq, Props, Clone)] pub struct DropdownProps { value: Option, @@ -31,30 +27,17 @@ pub struct DropdownProps { size: ElementSize, body: Vec, } - pub fn Dropdown(props: DropdownProps) -> Element { let mut is_active = use_signal::(|| false); - let disabled = if props.disabled { - "button--disabled" - } else { - "" - }; - - let placeholder = if let None = props.value { - "dropdown__placeholder" - } else { - "" - }; - + let disabled = if props.disabled { "button--disabled" } else { "" }; + let placeholder = if let None = props.value { "dropdown__placeholder" } else { "" }; let size = match props.size { ElementSize::Big => "dropdown__container--big", ElementSize::Medium => "dropdown__container--medium", ElementSize::Small => "dropdown__container--small", }; - rsx!( - section { - class: "dropdown {props.class}", + section { class: "dropdown {props.class}", if let Some(value) = props.label { label { class: "dropdown__label", "{value}" } } @@ -67,14 +50,10 @@ pub fn Dropdown(props: DropdownProps) -> Element { is_active.toggle(); } }, - span { - class: "dropdown__content", - span { - class: "dropdown__value {placeholder}", - match props.value { - Some(v) => {v.value}.to_string(), - None => props.placeholder - } + span { class: "dropdown__content", + span { class: "dropdown__value {placeholder}", + match props.value { Some(v) => { v.value } + .to_string(), None => props.placeholder } } Icon { class: if is_active() { "rotate-180" } else { "rotate-0" }, @@ -87,24 +66,9 @@ pub fn Dropdown(props: DropdownProps) -> Element { } } if is_active() { - {rsx!( - ul { - class: "dropdown__list", - { - props.body.into_iter().enumerate().map(|(index, item)| { - rsx!( - li { - class: "dropdown__item", - onclick: move |_| { - is_active.toggle(); - props.on_change.call(index) - }, - {item} - }) - }) - } - } - )} + { rsx!(ul { class : "dropdown__list", { props.body.into_iter().enumerate().map(| + (index, item) | { rsx!(li { class : "dropdown__item", onclick : move | _ | { + is_active.toggle(); props.on_change.call(index) }, { item } }) }) } }) } } } } diff --git a/src/components/atoms/icon_button.rs b/src/components/atoms/icon_button.rs index bbb2de3..81a5581 100644 --- a/src/components/atoms/icon_button.rs +++ b/src/components/atoms/icon_button.rs @@ -1,13 +1,10 @@ use dioxus::prelude::*; - use super::dropdown::ElementSize; - #[derive(PartialEq, Clone)] pub enum Variant { Round, SemiRound, } - #[derive(PartialEq, Props, Clone)] pub struct IconButtonProps { body: Element, @@ -19,24 +16,21 @@ pub struct IconButtonProps { size: ElementSize, on_click: EventHandler, } - pub fn IconButton(props: IconButtonProps) -> Element { let variant = match props.variant { Variant::Round => "icon-button--round", Variant::SemiRound => "icon-button--semi-round", }; - let size = match props.size { ElementSize::Big => "icon-button--big", ElementSize::Medium => "icon-button--medium", ElementSize::Small => "icon-button--small", }; - rsx!( button { class: "button button--tertiary padding-reset {props.class} {variant} {size} commin-soon", onclick: move |event| props.on_click.call(event), - {props.body} + { props.body } } ) } diff --git a/src/components/atoms/icons/add_plus.rs b/src/components/atoms/icons/add_plus.rs index 117bd65..7a818d7 100644 --- a/src/components/atoms/icons/add_plus.rs +++ b/src/components/atoms/icons/add_plus.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct AddPlus; impl IconShape for AddPlus { diff --git a/src/components/atoms/icons/arrow.rs b/src/components/atoms/icons/arrow.rs index ea0c653..4aac5d5 100644 --- a/src/components/atoms/icons/arrow.rs +++ b/src/components/atoms/icons/arrow.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct Arrow; impl IconShape for Arrow { diff --git a/src/components/atoms/icons/arrow_left.rs b/src/components/atoms/icons/arrow_left.rs index cd6e60b..fd6990d 100644 --- a/src/components/atoms/icons/arrow_left.rs +++ b/src/components/atoms/icons/arrow_left.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct ArrowLeft; impl IconShape for ArrowLeft { diff --git a/src/components/atoms/icons/arrow_right.rs b/src/components/atoms/icons/arrow_right.rs index be73be9..d8e8b6a 100644 --- a/src/components/atoms/icons/arrow_right.rs +++ b/src/components/atoms/icons/arrow_right.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct ArrowRight; impl IconShape for ArrowRight { diff --git a/src/components/atoms/icons/arrow_up.rs b/src/components/atoms/icons/arrow_up.rs index aa6767f..bc594ef 100644 --- a/src/components/atoms/icons/arrow_up.rs +++ b/src/components/atoms/icons/arrow_up.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct ArrowUp; impl IconShape for ArrowUp { diff --git a/src/components/atoms/icons/arrow_up_down.rs b/src/components/atoms/icons/arrow_up_down.rs index d1be073..151161b 100644 --- a/src/components/atoms/icons/arrow_up_down.rs +++ b/src/components/atoms/icons/arrow_up_down.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct ArrowUpDown; impl IconShape for ArrowUpDown { diff --git a/src/components/atoms/icons/chat.rs b/src/components/atoms/icons/chat.rs index 779543a..f7df8fc 100644 --- a/src/components/atoms/icons/chat.rs +++ b/src/components/atoms/icons/chat.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct Chat; impl IconShape for Chat { diff --git a/src/components/atoms/icons/chevron_left.rs b/src/components/atoms/icons/chevron_left.rs index 9d69a7d..16b3a36 100644 --- a/src/components/atoms/icons/chevron_left.rs +++ b/src/components/atoms/icons/chevron_left.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct ChevronLeft; impl IconShape for ChevronLeft { diff --git a/src/components/atoms/icons/chevron_right.rs b/src/components/atoms/icons/chevron_right.rs index dc831e9..9833339 100644 --- a/src/components/atoms/icons/chevron_right.rs +++ b/src/components/atoms/icons/chevron_right.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct ChevronRight; impl IconShape for ChevronRight { diff --git a/src/components/atoms/icons/circle_check.rs b/src/components/atoms/icons/circle_check.rs index 3e356e7..b6b5630 100644 --- a/src/components/atoms/icons/circle_check.rs +++ b/src/components/atoms/icons/circle_check.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct CircleCheck; impl IconShape for CircleCheck { diff --git a/src/components/atoms/icons/circle_shape.rs b/src/components/atoms/icons/circle_shape.rs index fcec294..bb625d3 100644 --- a/src/components/atoms/icons/circle_shape.rs +++ b/src/components/atoms/icons/circle_shape.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct CircleShape; impl IconShape for CircleShape { diff --git a/src/components/atoms/icons/close.rs b/src/components/atoms/icons/close.rs index dff1b2c..619623c 100644 --- a/src/components/atoms/icons/close.rs +++ b/src/components/atoms/icons/close.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct Close; impl IconShape for Close { diff --git a/src/components/atoms/icons/compass.rs b/src/components/atoms/icons/compass.rs index e1cafa4..5e743fc 100644 --- a/src/components/atoms/icons/compass.rs +++ b/src/components/atoms/icons/compass.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct Compass; impl IconShape for Compass { diff --git a/src/components/atoms/icons/filter.rs b/src/components/atoms/icons/filter.rs index 1e35655..7c91340 100644 --- a/src/components/atoms/icons/filter.rs +++ b/src/components/atoms/icons/filter.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct Filter; impl IconShape for Filter { diff --git a/src/components/atoms/icons/glyph.rs b/src/components/atoms/icons/glyph.rs index da40772..4e5c13c 100644 --- a/src/components/atoms/icons/glyph.rs +++ b/src/components/atoms/icons/glyph.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct Glyph; impl IconShape for Glyph { @@ -11,9 +9,12 @@ impl IconShape for Glyph { fn child_elements(&self) -> Element { rsx!( g { filter: "url(#filter0_d_575_469)", - path { fill_rule: "evenodd", clip_rule: "evenodd", d: "M13.3851 0.996566C13.9392 0.380801 14.8877 0.330883 15.5034 0.885072C16.1192 1.43926 16.1691 2.38769 15.6149 3.00346L6.61494 13.0035C6.04003 13.6422 5.04703 13.6684 4.43934 13.0607L0.43934 9.06067C-0.146447 8.47489 -0.146447 7.52514 0.43934 6.93935C1.02513 6.35357 1.97487 6.35357 2.56066 6.93935L5.44271 9.8214L13.3851 0.996566Z" } + path { + fill_rule: "evenodd", + clip_rule: "evenodd", + d: "M13.3851 0.996566C13.9392 0.380801 14.8877 0.330883 15.5034 0.885072C16.1192 1.43926 16.1691 2.38769 15.6149 3.00346L6.61494 13.0035C6.04003 13.6422 5.04703 13.6684 4.43934 13.0607L0.43934 9.06067C-0.146447 8.47489 -0.146447 7.52514 0.43934 6.93935C1.02513 6.35357 1.97487 6.35357 2.56066 6.93935L5.44271 9.8214L13.3851 0.996566Z" + } } - ) } } diff --git a/src/components/atoms/icons/hamburguer.rs b/src/components/atoms/icons/hamburguer.rs index 66c41a6..7da9c9e 100644 --- a/src/components/atoms/icons/hamburguer.rs +++ b/src/components/atoms/icons/hamburguer.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct Hamburguer; impl IconShape for Hamburguer { diff --git a/src/components/atoms/icons/home.rs b/src/components/atoms/icons/home.rs index f56788c..4674599 100644 --- a/src/components/atoms/icons/home.rs +++ b/src/components/atoms/icons/home.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct Home; impl IconShape for Home { diff --git a/src/components/atoms/icons/icon.rs b/src/components/atoms/icons/icon.rs index 245e291..c0eda7e 100644 --- a/src/components/atoms/icons/icon.rs +++ b/src/components/atoms/icons/icon.rs @@ -1,10 +1,8 @@ use dioxus::prelude::*; - pub trait IconShape: PartialEq { fn view_box(&self) -> String; fn child_elements(&self) -> Element; } - #[derive(PartialEq, Clone, Props)] pub struct IconProps { #[props(default = 20)] @@ -21,16 +19,14 @@ pub struct IconProps { pub class: String, pub icon: T, } - pub fn Icon(props: IconProps) -> Element { let icon_style = format!( r#" width: 100%; max-width: {}px; "#, - props.width + props.width, ); - rsx! { svg { style: "{icon_style}", @@ -42,7 +38,7 @@ pub fn Icon(props: IconProps) -> Element { view_box: format_args!("{}", props.icon.view_box()), stroke_linecap: "round", stroke_linejoin: "round", - {props.icon.child_elements()} + { props.icon.child_elements() } } } } diff --git a/src/components/atoms/icons/key_fill.rs b/src/components/atoms/icons/key_fill.rs index a310a6a..bbb3344 100644 --- a/src/components/atoms/icons/key_fill.rs +++ b/src/components/atoms/icons/key_fill.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct KeyFill; impl IconShape for KeyFill { diff --git a/src/components/atoms/icons/medall_fill.rs b/src/components/atoms/icons/medall_fill.rs index c756e4b..432c673 100644 --- a/src/components/atoms/icons/medall_fill.rs +++ b/src/components/atoms/icons/medall_fill.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct MedalFill; impl IconShape for MedalFill { diff --git a/src/components/atoms/icons/messages.rs b/src/components/atoms/icons/messages.rs index 3c923cc..f4d64b5 100644 --- a/src/components/atoms/icons/messages.rs +++ b/src/components/atoms/icons/messages.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct Messages; impl IconShape for Messages { diff --git a/src/components/atoms/icons/minus_circle.rs b/src/components/atoms/icons/minus_circle.rs index 54f6174..11d5bc3 100644 --- a/src/components/atoms/icons/minus_circle.rs +++ b/src/components/atoms/icons/minus_circle.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct MinusCircle; impl IconShape for MinusCircle { @@ -10,7 +8,11 @@ impl IconShape for MinusCircle { } fn child_elements(&self) -> Element { rsx!( - path { fill_rule: "evenodd", clip_rule: "evenodd", d: "M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20Z" } + path { + fill_rule: "evenodd", + clip_rule: "evenodd", + d: "M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20Z" + } path { d: "M16.5 11C17.0523 11 17.5 11.4477 17.5 12C17.5 12.5523 17.0523 13 16.5 13H7.5C6.94772 13 6.5 12.5523 6.5 12C6.5 11.4477 6.94772 11 7.5 11H16.5Z" } ) } diff --git a/src/components/atoms/icons/mod.rs b/src/components/atoms/icons/mod.rs index 942ad7c..e4acd46 100644 --- a/src/components/atoms/icons/mod.rs +++ b/src/components/atoms/icons/mod.rs @@ -37,7 +37,6 @@ pub mod user_group; pub mod virto_logo; pub mod votes; pub mod warning_sign; - pub use add_plus::AddPlus; pub use arrow::Arrow; pub use arrow_left::ArrowLeft; diff --git a/src/components/atoms/icons/monetization.rs b/src/components/atoms/icons/monetization.rs index 3a8bfbc..4757435 100644 --- a/src/components/atoms/icons/monetization.rs +++ b/src/components/atoms/icons/monetization.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct Monetization; impl IconShape for Monetization { @@ -10,7 +8,10 @@ impl IconShape for Monetization { } fn child_elements(&self) -> Element { rsx!( - path { opacity: "0.3", d: "M8 2.667A5.34 5.34 0 0 0 2.665 8a5.34 5.34 0 0 0 5.333 5.333A5.34 5.34 0 0 0 13.333 8a5.34 5.34 0 0 0-5.334-5.333m.82 8.886v1.114H7.265V11.54c-1-.207-1.847-.853-1.907-1.98H6.5c.06.613.48 1.093 1.547 1.093 1.14 0 1.4-.573 1.4-.926 0-.487-.26-.94-1.56-1.247-1.447-.353-2.44-.947-2.44-2.14 0-1.007.813-1.653 1.813-1.873V3.333h1.56v1.14c1.087.26 1.627 1.087 1.66 1.98H9.34c-.026-.646-.373-1.093-1.293-1.093-.873 0-1.4.393-1.4.953 0 .487.38.814 1.56 1.114 1.18.306 2.44.813 2.44 2.28-.007 1.066-.807 1.653-1.827 1.846" } + path { + opacity: "0.3", + d: "M8 2.667A5.34 5.34 0 0 0 2.665 8a5.34 5.34 0 0 0 5.333 5.333A5.34 5.34 0 0 0 13.333 8a5.34 5.34 0 0 0-5.334-5.333m.82 8.886v1.114H7.265V11.54c-1-.207-1.847-.853-1.907-1.98H6.5c.06.613.48 1.093 1.547 1.093 1.14 0 1.4-.573 1.4-.926 0-.487-.26-.94-1.56-1.247-1.447-.353-2.44-.947-2.44-2.14 0-1.007.813-1.653 1.813-1.873V3.333h1.56v1.14c1.087.26 1.627 1.087 1.66 1.98H9.34c-.026-.646-.373-1.093-1.293-1.093-.873 0-1.4.393-1.4.953 0 .487.38.814 1.56 1.114 1.18.306 2.44.813 2.44 2.28-.007 1.066-.807 1.653-1.827 1.846" + } path { d: "M8 1.333A6.67 6.67 0 0 0 1.335 8a6.67 6.67 0 0 0 6.667 6.667A6.67 6.67 0 0 0 14.667 8a6.67 6.67 0 0 0-6.666-6.667m0 12A5.34 5.34 0 0 1 2.668 8a5.34 5.34 0 0 1 5.334-5.333A5.34 5.34 0 0 1 13.334 8a5.34 5.34 0 0 1-5.333 5.333m.207-5.906c-1.18-.3-1.56-.627-1.56-1.114 0-.56.527-.953 1.4-.953.92 0 1.267.44 1.294 1.093h1.14c-.034-.893-.58-1.713-1.66-1.98v-1.14H7.267V4.46c-1.006.213-1.813.867-1.813 1.873 0 1.194.993 1.794 2.44 2.14 1.3.307 1.56.767 1.56 1.247 0 .353-.26.927-1.4.927-1.067 0-1.487-.48-1.547-1.094H5.361c.066 1.134.906 1.774 1.906 1.98v1.134h1.56v-1.114c1.014-.193 1.814-.773 1.82-1.846-.006-1.467-1.266-1.974-2.44-2.28" } ) } diff --git a/src/components/atoms/icons/plus.rs b/src/components/atoms/icons/plus.rs index 34c5148..a1c331d 100644 --- a/src/components/atoms/icons/plus.rs +++ b/src/components/atoms/icons/plus.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct Plus; impl IconShape for Plus { diff --git a/src/components/atoms/icons/profile.rs b/src/components/atoms/icons/profile.rs index 9c13ca9..f0b7aee 100644 --- a/src/components/atoms/icons/profile.rs +++ b/src/components/atoms/icons/profile.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct Profile; impl IconShape for Profile { diff --git a/src/components/atoms/icons/search.rs b/src/components/atoms/icons/search.rs index 97f3182..97153c6 100644 --- a/src/components/atoms/icons/search.rs +++ b/src/components/atoms/icons/search.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct Search; impl IconShape for Search { diff --git a/src/components/atoms/icons/settings.rs b/src/components/atoms/icons/settings.rs index d273c25..5d863f3 100644 --- a/src/components/atoms/icons/settings.rs +++ b/src/components/atoms/icons/settings.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct Settings; impl IconShape for Settings { diff --git a/src/components/atoms/icons/shield_keyhole_fill.rs b/src/components/atoms/icons/shield_keyhole_fill.rs index 32fc09c..2dcead6 100644 --- a/src/components/atoms/icons/shield_keyhole_fill.rs +++ b/src/components/atoms/icons/shield_keyhole_fill.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct ShieldKeyholeFill; impl IconShape for ShieldKeyholeFill { diff --git a/src/components/atoms/icons/stop_sign.rs b/src/components/atoms/icons/stop_sign.rs index 63618b8..ec86b9a 100644 --- a/src/components/atoms/icons/stop_sign.rs +++ b/src/components/atoms/icons/stop_sign.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct StopSign; impl IconShape for StopSign { diff --git a/src/components/atoms/icons/substract_line.rs b/src/components/atoms/icons/substract_line.rs index 6f455a1..571fc22 100644 --- a/src/components/atoms/icons/substract_line.rs +++ b/src/components/atoms/icons/substract_line.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct SubstractLine; impl IconShape for SubstractLine { diff --git a/src/components/atoms/icons/suitcase.rs b/src/components/atoms/icons/suitcase.rs index 065a1c0..199a4f4 100644 --- a/src/components/atoms/icons/suitcase.rs +++ b/src/components/atoms/icons/suitcase.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct Suitcase; impl IconShape for Suitcase { diff --git a/src/components/atoms/icons/team_fill.rs b/src/components/atoms/icons/team_fill.rs index 381d261..4537669 100644 --- a/src/components/atoms/icons/team_fill.rs +++ b/src/components/atoms/icons/team_fill.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct TeamFill; impl IconShape for TeamFill { @@ -10,7 +8,9 @@ impl IconShape for TeamFill { } fn child_elements(&self) -> Element { rsx!( - path { d: "M10 9.16667C11.1051 9.16667 12.1649 9.60566 12.9463 10.3871C13.7277 11.1685 14.1667 12.2283 14.1667 13.3333V18.3333H5.83335V13.3333C5.83335 12.2283 6.27234 11.1685 7.05374 10.3871C7.83514 9.60566 8.89495 9.16667 10 9.16667ZM4.40669 11.6717C4.27407 12.119 4.19573 12.5806 4.17335 13.0467L4.16669 13.3333V18.3333H1.66669L1.66669 14.5833C1.66652 13.8646 1.93171 13.1712 2.41138 12.636C2.89105 12.1008 3.55144 11.7616 4.26585 11.6833L4.40752 11.6717H4.40669ZM15.5934 11.6717C16.3349 11.7169 17.0314 12.0433 17.5405 12.5844C18.0497 13.1254 18.3332 13.8404 18.3334 14.5833L18.3334 18.3333L15.8334 18.3333V13.3333C15.8334 12.7558 15.75 12.1983 15.5934 11.6717ZM4.58335 6.66667C5.13589 6.66667 5.66579 6.88616 6.05649 7.27686C6.44719 7.66756 6.66669 8.19747 6.66669 8.75C6.66669 9.30254 6.44719 9.83244 6.05649 10.2231C5.66579 10.6138 5.13589 10.8333 4.58335 10.8333C4.03082 10.8333 3.50092 10.6138 3.11021 10.2231C2.71951 9.83244 2.50002 9.30254 2.50002 8.75C2.50002 8.19747 2.71951 7.66756 3.11021 7.27686C3.50092 6.88616 4.03082 6.66667 4.58335 6.66667V6.66667ZM15.4167 6.66667C15.9692 6.66667 16.4991 6.88616 16.8898 7.27686C17.2805 7.66756 17.5 8.19747 17.5 8.75C17.5 9.30254 17.2805 9.83244 16.8898 10.2231C16.4991 10.6138 15.9692 10.8333 15.4167 10.8333C14.8642 10.8333 14.3342 10.6138 13.9435 10.2231C13.5528 9.83244 13.3334 9.30254 13.3334 8.75C13.3334 8.19747 13.5528 7.66756 13.9435 7.27686C14.3342 6.88616 14.8642 6.66667 15.4167 6.66667V6.66667ZM10 1.66667C10.8841 1.66667 11.7319 2.01786 12.357 2.64298C12.9822 3.2681 13.3334 4.11595 13.3334 5C13.3334 5.88406 12.9822 6.7319 12.357 7.35702C11.7319 7.98215 10.8841 8.33333 10 8.33333C9.11597 8.33333 8.26812 7.98215 7.643 7.35702C7.01788 6.7319 6.66669 5.88406 6.66669 5C6.66669 4.11595 7.01788 3.2681 7.643 2.64298C8.26812 2.01786 9.11597 1.66667 10 1.66667V1.66667Z" } + path { + d: "M10 9.16667C11.1051 9.16667 12.1649 9.60566 12.9463 10.3871C13.7277 11.1685 14.1667 12.2283 14.1667 13.3333V18.3333H5.83335V13.3333C5.83335 12.2283 6.27234 11.1685 7.05374 10.3871C7.83514 9.60566 8.89495 9.16667 10 9.16667ZM4.40669 11.6717C4.27407 12.119 4.19573 12.5806 4.17335 13.0467L4.16669 13.3333V18.3333H1.66669L1.66669 14.5833C1.66652 13.8646 1.93171 13.1712 2.41138 12.636C2.89105 12.1008 3.55144 11.7616 4.26585 11.6833L4.40752 11.6717H4.40669ZM15.5934 11.6717C16.3349 11.7169 17.0314 12.0433 17.5405 12.5844C18.0497 13.1254 18.3332 13.8404 18.3334 14.5833L18.3334 18.3333L15.8334 18.3333V13.3333C15.8334 12.7558 15.75 12.1983 15.5934 11.6717ZM4.58335 6.66667C5.13589 6.66667 5.66579 6.88616 6.05649 7.27686C6.44719 7.66756 6.66669 8.19747 6.66669 8.75C6.66669 9.30254 6.44719 9.83244 6.05649 10.2231C5.66579 10.6138 5.13589 10.8333 4.58335 10.8333C4.03082 10.8333 3.50092 10.6138 3.11021 10.2231C2.71951 9.83244 2.50002 9.30254 2.50002 8.75C2.50002 8.19747 2.71951 7.66756 3.11021 7.27686C3.50092 6.88616 4.03082 6.66667 4.58335 6.66667V6.66667ZM15.4167 6.66667C15.9692 6.66667 16.4991 6.88616 16.8898 7.27686C17.2805 7.66756 17.5 8.19747 17.5 8.75C17.5 9.30254 17.2805 9.83244 16.8898 10.2231C16.4991 10.6138 15.9692 10.8333 15.4167 10.8333C14.8642 10.8333 14.3342 10.6138 13.9435 10.2231C13.5528 9.83244 13.3334 9.30254 13.3334 8.75C13.3334 8.19747 13.5528 7.66756 13.9435 7.27686C14.3342 6.88616 14.8642 6.66667 15.4167 6.66667V6.66667ZM10 1.66667C10.8841 1.66667 11.7319 2.01786 12.357 2.64298C12.9822 3.2681 13.3334 4.11595 13.3334 5C13.3334 5.88406 12.9822 6.7319 12.357 7.35702C11.7319 7.98215 10.8841 8.33333 10 8.33333C9.11597 8.33333 8.26812 7.98215 7.643 7.35702C7.01788 6.7319 6.66669 5.88406 6.66669 5C6.66669 4.11595 7.01788 3.2681 7.643 2.64298C8.26812 2.01786 9.11597 1.66667 10 1.66667V1.66667Z" + } ) } } diff --git a/src/components/atoms/icons/upload_export.rs b/src/components/atoms/icons/upload_export.rs index 65a3c85..1a0896e 100644 --- a/src/components/atoms/icons/upload_export.rs +++ b/src/components/atoms/icons/upload_export.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct UploadExport; impl IconShape for UploadExport { diff --git a/src/components/atoms/icons/user.rs b/src/components/atoms/icons/user.rs index f9681ea..c9b4657 100644 --- a/src/components/atoms/icons/user.rs +++ b/src/components/atoms/icons/user.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct User; impl IconShape for User { diff --git a/src/components/atoms/icons/user_add.rs b/src/components/atoms/icons/user_add.rs index 05eec14..ce77293 100644 --- a/src/components/atoms/icons/user_add.rs +++ b/src/components/atoms/icons/user_add.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct UserAdd; impl IconShape for UserAdd { diff --git a/src/components/atoms/icons/user_group.rs b/src/components/atoms/icons/user_group.rs index 67c9254..e7df44e 100644 --- a/src/components/atoms/icons/user_group.rs +++ b/src/components/atoms/icons/user_group.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct UserGroup; impl IconShape for UserGroup { @@ -10,9 +8,9 @@ impl IconShape for UserGroup { } fn child_elements(&self) -> Element { rsx!( - path {d: "M6.00065 7.33333C7.47341 7.33333 8.66732 6.13943 8.66732 4.66667C8.66732 3.19391 7.47341 2 6.00065 2C4.52789 2 3.33398 3.19391 3.33398 4.66667C3.33398 6.13943 4.52789 7.33333 6.00065 7.33333Z"} - path {d: "M11.334 8.66675C12.4386 8.66675 13.334 7.77132 13.334 6.66675C13.334 5.56218 12.4386 4.66675 11.334 4.66675C10.2294 4.66675 9.33398 5.56218 9.33398 6.66675C9.33398 7.77132 10.2294 8.66675 11.334 8.66675Z"} - path {d: "M14.0007 13.3333C14.3688 13.3333 14.6673 13.0349 14.6673 12.6667C14.6662 11.3956 13.9423 10.2357 12.8009 9.67632C11.6595 9.11694 10.2993 9.25541 9.29398 10.0333C7.9587 8.7033 5.95446 8.307 4.21347 9.02876C2.47248 9.75053 1.33653 11.4487 1.33398 13.3333C1.33398 13.7015 1.63246 14 2.00065 14H10.0007C10.3688 14 10.6673 13.7015 10.6673 13.3333"} + path { d: "M6.00065 7.33333C7.47341 7.33333 8.66732 6.13943 8.66732 4.66667C8.66732 3.19391 7.47341 2 6.00065 2C4.52789 2 3.33398 3.19391 3.33398 4.66667C3.33398 6.13943 4.52789 7.33333 6.00065 7.33333Z" } + path { d: "M11.334 8.66675C12.4386 8.66675 13.334 7.77132 13.334 6.66675C13.334 5.56218 12.4386 4.66675 11.334 4.66675C10.2294 4.66675 9.33398 5.56218 9.33398 6.66675C9.33398 7.77132 10.2294 8.66675 11.334 8.66675Z" } + path { d: "M14.0007 13.3333C14.3688 13.3333 14.6673 13.0349 14.6673 12.6667C14.6662 11.3956 13.9423 10.2357 12.8009 9.67632C11.6595 9.11694 10.2993 9.25541 9.29398 10.0333C7.9587 8.7033 5.95446 8.307 4.21347 9.02876C2.47248 9.75053 1.33653 11.4487 1.33398 13.3333C1.33398 13.7015 1.63246 14 2.00065 14H10.0007C10.3688 14 10.6673 13.7015 10.6673 13.3333" } ) } } diff --git a/src/components/atoms/icons/virto_logo.rs b/src/components/atoms/icons/virto_logo.rs index e3d719f..ecdb6c3 100644 --- a/src/components/atoms/icons/virto_logo.rs +++ b/src/components/atoms/icons/virto_logo.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct VirtoLogo; impl IconShape for VirtoLogo { diff --git a/src/components/atoms/icons/votes.rs b/src/components/atoms/icons/votes.rs index dc827ef..c847305 100644 --- a/src/components/atoms/icons/votes.rs +++ b/src/components/atoms/icons/votes.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct Votes; impl IconShape for Votes { diff --git a/src/components/atoms/icons/warning_sign.rs b/src/components/atoms/icons/warning_sign.rs index aa18eb0..c48ff33 100644 --- a/src/components/atoms/icons/warning_sign.rs +++ b/src/components/atoms/icons/warning_sign.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::icon::IconShape; - #[derive(PartialEq, Clone)] pub struct WarningSign; impl IconShape for WarningSign { @@ -10,7 +8,12 @@ impl IconShape for WarningSign { } fn child_elements(&self) -> Element { rsx!( - path { fill_rule: "evenodd", clip_rule: "evenodd", d: "M14.2987 3.31824C13.2904 1.56059 10.7096 1.56059 9.7013 3.31824L2.34255 16.146C1.35361 17.8699 2.62409 20 4.64124 20H19.3588C21.3759 20 22.6464 17.8699 21.6575 16.146L14.2987 3.31824ZM12 6.5C11.4477 6.5 11 6.94772 11 7.5V13.5C11 14.0523 11.4477 14.5 12 14.5C12.5523 14.5 13 14.0523 13 13.5V7.5C13 6.94772 12.5523 6.5 12 6.5ZM12 15.5C11.4477 15.5 11 15.9477 11 16.5C11 17.0523 11.4477 17.5 12 17.5C12.5523 17.5 13 17.0523 13 16.5C13 15.9477 12.5523 15.5 12 15.5Z", fill: "#DC2828" } + path { + fill_rule: "evenodd", + clip_rule: "evenodd", + d: "M14.2987 3.31824C13.2904 1.56059 10.7096 1.56059 9.7013 3.31824L2.34255 16.146C1.35361 17.8699 2.62409 20 4.64124 20H19.3588C21.3759 20 22.6464 17.8699 21.6575 16.146L14.2987 3.31824ZM12 6.5C11.4477 6.5 11 6.94772 11 7.5V13.5C11 14.0523 11.4477 14.5 12 14.5C12.5523 14.5 13 14.0523 13 13.5V7.5C13 6.94772 12.5523 6.5 12 6.5ZM12 15.5C11.4477 15.5 11 15.9477 11 16.5C11 17.0523 11.4477 17.5 12 17.5C12.5523 17.5 13 17.0523 13 16.5C13 15.9477 12.5523 15.5 12 15.5Z", + fill: "#DC2828" + } ) } } diff --git a/src/components/atoms/input.rs b/src/components/atoms/input.rs index 9f14727..ea176f3 100644 --- a/src/components/atoms/input.rs +++ b/src/components/atoms/input.rs @@ -1,11 +1,8 @@ use dioxus::prelude::*; use wasm_bindgen::JsCast; use web_sys::HtmlInputElement; - use crate::components::atoms::{Icon, IconButton, Search, WarningSign}; - use super::dropdown::ElementSize; - #[derive(PartialEq, Clone)] pub enum InputType { Text, @@ -14,7 +11,6 @@ pub enum InputType { Password, Date, } - #[derive(PartialEq, Props, Clone)] pub struct InputProps { #[props(default = InputType::Text)] @@ -37,16 +33,13 @@ pub struct InputProps { on_keypress: EventHandler, on_click: EventHandler, } - pub fn Input(props: InputProps) -> Element { let mut input_ref = use_signal::>>(|| None); - let input_error_container = if let Some(_) = props.error { "input--error-container" } else { "" }; - let input_type = match props.itype { InputType::Text => "text", InputType::Search => "text", @@ -54,39 +47,35 @@ pub fn Input(props: InputProps) -> Element { InputType::Date => "date", InputType::Password => "password", }; - let size = match props.size { ElementSize::Big => "input-wrapper__container--big", ElementSize::Medium => "input-wrapper__container--medium", ElementSize::Small => "input-wrapper__container--small", }; - let is_search = if matches!(props.itype, InputType::Search) { "input__wrapper--search" } else { "" }; - let mut is_active = use_signal::(|| false); - rsx!( section { class: "input__wrapper {is_search}", - class: if is_active() {"input__wrapper--active"}, + class: if is_active() { "input__wrapper--active" }, if let Some(value) = props.label { label { class: "input__label", "{value}" } } - div { - class: "input-wrapper {size} {input_error_container}", - {props.left_text} + div { class: "input-wrapper {size} {input_error_container}", + { props.left_text }, input { r#type: "{input_type}", class: "input", onmounted: move |event| { - event.data.downcast::() - .and_then(|element| element.clone().dyn_into::().ok()) - .map(|html_element| input_ref.set(Some(Box::new(html_element.clone())))); - + event + .data + .downcast::() + .and_then(|element| element.clone().dyn_into::().ok()) + .map(|html_element| input_ref.set(Some(Box::new(html_element.clone())))); if input_type == "date" { if let Some(input_element) = input_ref() { input_element.set_type("text") @@ -106,23 +95,22 @@ pub fn Input(props: InputProps) -> Element { value: props.message, required: props.required, maxlength: i64::from(props.maxlength), - placeholder: if props.required { format!("{}*", props.placeholder) } else { format!("{}", props.placeholder) }, + placeholder: if props.required { + format!("{}*", props.placeholder) + } else { + format!("{}", props.placeholder) + }, oninput: move |event| props.on_input.call(event), onkeypress: move |event| props.on_keypress.call(event) } - {props.right_text} + { props.right_text }, if matches!(props.itype, InputType::Search) { 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)" - } + Icon { icon : Search, height : 26, width : 26, stroke_width : 1.5, fill : + "var(--text-secondary)" } ), on_click: move |_| { is_active.toggle(); @@ -132,16 +120,11 @@ pub fn Input(props: InputProps) -> Element { } if props.error.is_none() { if let Some(help) = props.help { - div { - class: "input--help", - "{help}" - } + div { class: "input--help", "{help}" } } } - if let Some(error) = props.error { - div { - class: "input--error", + div { class: "input--error", Icon { icon: WarningSign, height: 24, diff --git a/src/components/atoms/input_tags.rs b/src/components/atoms/input_tags.rs index d5b2c67..dc3dff1 100644 --- a/src/components/atoms/input_tags.rs +++ b/src/components/atoms/input_tags.rs @@ -1,15 +1,11 @@ use dioxus::prelude::*; - use crate::components::atoms::icons::Close; use crate::components::atoms::{Icon, IconButton, WarningSign}; - use super::dropdown::ElementSize; - #[derive(PartialEq, Props, Clone)] pub struct InputTagsEvent { pub tags: Vec, } - #[derive(PartialEq, Props, Clone)] pub struct InputTagsProps { message: String, @@ -27,90 +23,48 @@ pub struct InputTagsProps { on_keypress: EventHandler, on_click: EventHandler, } - pub fn InputTags(props: InputTagsProps) -> Element { let input_error_container = if let Some(_) = props.error { "input--error-container" } else { "" }; - let size = match props.size { ElementSize::Big => "input-wrapper__container--big", ElementSize::Medium => "input-wrapper__container--medium", ElementSize::Small => "input-wrapper__container--small", }; - let mut is_active = use_signal::(|| false); let mut tags = use_signal::>(|| vec![]); let mut complete_value = use_signal(|| String::new()); let mut new_value = use_signal(|| String::new()); let mut temporal_value = use_signal(|| String::new()); let mut is_editing_tag = use_signal(|| None); - rsx!( section { class: "input__wrapper", - class: if is_active() {"input__wrapper--active"}, + class: if is_active() { "input__wrapper--active" }, if let Some(value) = props.label { label { class: "input__label", "{value}" } } - div { - class: "input-wrapper {size} {input_error_container}", - { - tags().iter().enumerate().map(|(index, tag)| { - rsx!( - div { - class: "tag", - class: if let Some(i) = is_editing_tag() { if i != index { "tag--editing" } else {""} }, - button { - class: "tag__text", - onclick: move |_| { - if let Some(i) = is_editing_tag() { - if i == index { - new_value.set(temporal_value()); - is_editing_tag.set(None); - } else { - is_editing_tag.set(Some(index)); - new_value.set(tags()[index].clone()); - } - } else { - is_editing_tag.set(Some(index)); - temporal_value.set(new_value()); - new_value.set(tags()[index].clone()); - } - }, - "{tag}" - } - IconButton { - class: "button--drop bg--transparent", - body: rsx!( - Icon { - icon: Close, - height: 20, - width: 20, - fill: "var(--fill-400)" - } - ), - on_click: move |_| { - if let Some(i) = is_editing_tag() { - if i == index { - new_value.set(temporal_value()); - is_editing_tag.set(None); - } - } - tags.with_mut(|t|t.remove(index)); - complete_value.set(tags().join(",")); - } - } - } - ) - }) - } + div { class: "input-wrapper {size} {input_error_container}", + { tags().iter().enumerate().map(| + (index, tag) | { rsx!(div { class : "tag", class : if let Some(i) = + is_editing_tag() { if i != index { "tag--editing" } else { "" } }, button { class + : "tag__text", onclick : move | _ | { if let Some(i) = is_editing_tag() { if i == + index { new_value.set(temporal_value()); is_editing_tag.set(None); } else { + is_editing_tag.set(Some(index)); new_value.set(tags() [index].clone()); } } else + { is_editing_tag.set(Some(index)); temporal_value.set(new_value()); new_value + .set(tags() [index].clone()); } }, "{tag}" } IconButton { class : + "button--drop bg--transparent", body : rsx!(Icon { icon : Close, height : 20, + width : 20, fill : "var(--fill-400)" }), on_click : move | _ | { if let Some(i) = + is_editing_tag() { if i == index { new_value.set(temporal_value()); + is_editing_tag.set(None); } } tags.with_mut(| t | t.remove(index)); + complete_value.set(tags().join(",")); } } }) }) }, if new_value().trim().len() > 0 { div { class: "tag", - class: if is_editing_tag().is_some() {"tag--editing"}, + class: if is_editing_tag().is_some() { "tag--editing" }, button { class: "tag__text", onclick: move |_| { @@ -125,14 +79,7 @@ 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()); } @@ -144,27 +91,38 @@ pub fn InputTags(props: InputTagsProps) -> Element { class: "input", value: new_value, required: props.required, - placeholder: if props.required { format!("{}*", props.placeholder) } else { format!("{}", props.placeholder) }, + placeholder: if props.required { + format!("{}*", props.placeholder) + } else { + format!("{}", props.placeholder) + }, oninput: move |event| { if let Some(index) = is_editing_tag() { - tags.with_mut(|t|t[index] = event.value()); - props.on_input.call(InputTagsEvent { - tags: tags().clone() - }); + tags.with_mut(|t| t[index] = event.value()); + props + .on_input + .call(InputTagsEvent { + tags: tags().clone(), + }); return; } - if event.value().contains(',') { if tags().len() == (props.maxlength - 1) as usize { - props.on_input.call(InputTagsEvent { - tags: tags().clone() - }); + props + .on_input + .call(InputTagsEvent { + tags: tags().clone(), + }); return; } - let e: Vec = event.value().split(',').map(|s| s.to_string()).collect(); + let e: Vec = event + .value() + .split(',') + .map(|s| s.to_string()) + .collect(); let last_tag = e[1].clone(); if last_tag.len() > 0 { - tags.with_mut(|t|t.push(e[0].clone())); + tags.with_mut(|t| t.push(e[0].clone())); complete_value.set(tags().join(",")); new_value.set(last_tag.clone()); } else { @@ -173,29 +131,23 @@ pub fn InputTags(props: InputTagsProps) -> Element { } else { new_value.set(event.value().clone()); } - if event.value().len() == 0 && tags.last().is_some(){ + if event.value().len() == 0 && tags.last().is_some() { new_value.set(tags().last().unwrap().to_string()); - tags.with_mut(|t|t.pop()); + tags.with_mut(|t| t.pop()); } - let val = if temporal_value().len() > 0 { temporal_value() } else { new_value() }; - let mut t = tags().clone(); t.push(val.to_string()); - - props.on_input.call(InputTagsEvent { - tags: t - }); - }, + props.on_input.call(InputTagsEvent { tags: t }); + } } } if let Some(error) = props.error { - div { - class: "input--error", + div { class: "input--error", Icon { icon: WarningSign, height: 24, diff --git a/src/components/atoms/key_value.rs b/src/components/atoms/key_value.rs index ce0c03a..8d6a038 100644 --- a/src/components/atoms/key_value.rs +++ b/src/components/atoms/key_value.rs @@ -1,13 +1,10 @@ use dioxus::prelude::*; - use super::dropdown::ElementSize; - #[derive(PartialEq, Clone)] pub enum Variant { Primary, Secondary, } - #[derive(PartialEq, Props, Clone)] pub struct KeyValueProps { #[props(default = "".to_string())] @@ -19,27 +16,22 @@ pub struct KeyValueProps { text: String, body: Element, } - pub fn KeyValue(props: KeyValueProps) -> Element { let size = match props.size { ElementSize::Big => "key-value--big", ElementSize::Medium => "key-value--medium", ElementSize::Small => "key-value--small", }; - let variant = match props.variant { Variant::Primary => "key-value--primary", Variant::Secondary => "key-value--secondary", }; - rsx!( - span { - class: "key-value {props.class} {size} {variant}", - h4 { class: "key-value__key", - "{props.text}" - }, + span { class: "key-value {props.class} {size} {variant}", + h4 { class: "key-value__key", "{props.text}" } div { class: "key-value__value", - {props.body} + { props + .body } } } ) diff --git a/src/components/atoms/markdown.rs b/src/components/atoms/markdown.rs index a4af61f..ddcfcf0 100644 --- a/src/components/atoms/markdown.rs +++ b/src/components/atoms/markdown.rs @@ -4,16 +4,13 @@ use dioxus_std::translate; use wasm_bindgen::prelude::*; use wasm_bindgen::JsValue; use web_sys::js_sys::Function; - use crate::components::atoms::button::Variant; use crate::components::atoms::dropdown::ElementSize; use crate::components::atoms::Button; - #[derive(PartialEq, Props, Clone)] pub struct MarkdownEvent { pub value: String, } - #[derive(PartialEq, Props, Clone)] pub struct MarkdownProps { #[props(default = "".to_string())] @@ -21,24 +18,18 @@ pub struct MarkdownProps { content: String, on_input: EventHandler, } - #[wasm_bindgen] 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); } - pub fn Markdown(props: MarkdownProps) -> Element { let i18 = use_i18(); - let mut is_editor_loaded = use_signal(|| false); - let mut content = use_signal(|| { if props.content.len() > 0 { props.content @@ -47,56 +38,53 @@ pub fn Markdown(props: MarkdownProps) -> Element { } }); let mut is_markdown_visible = use_signal(|| true); - let cont = &*content.read(); 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(text) = new_content.as_string() { - content.set(text.clone()); - props.on_input.call(MarkdownEvent { value: text }) - } - }) as Box); - + 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 }) + } + }) as Box, + ); let function = closure.as_ref().unchecked_ref::(); add_change_listener(function); 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 { 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() {"markdown__wrapper--preview"} else {"hide"}, + class: if !is_markdown_visible() { "markdown__wrapper--preview" } else { "hide" }, dangerous_inner_html: "{html_buf}" } div { Button { class: "", - text: if !is_markdown_visible() {translate!(i18, "utils.markdown.cta.edit")} else {translate!(i18, "utils.markdown.cta.preview")}, + text: if !is_markdown_visible() { + translate!(i18, "utils.markdown.cta.edit") + } else { + translate!(i18, "utils.markdown.cta.preview") + }, size: ElementSize::Small, variant: Variant::Tertiary, on_click: move |_| { is_markdown_visible.toggle(); }, - status: None, + status: None } } } diff --git a/src/components/atoms/mod.rs b/src/components/atoms/mod.rs index 6a75cf8..57b70bc 100644 --- a/src/components/atoms/mod.rs +++ b/src/components/atoms/mod.rs @@ -25,7 +25,6 @@ pub mod tab; pub mod textarea; pub mod title; pub mod tooltip; - pub use account::AccountButton; pub use attach::Attach; pub use avatar::Avatar; diff --git a/src/components/atoms/notification.rs b/src/components/atoms/notification.rs index 86c8221..05086c7 100644 --- a/src/components/atoms/notification.rs +++ b/src/components/atoms/notification.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use crate::hooks::use_notification::NotificationVariant; - #[derive(PartialEq, Props, Clone)] pub struct NotificationProps { title: String, @@ -9,7 +7,6 @@ pub struct NotificationProps { variant: NotificationVariant, on_click: EventHandler, } - pub fn Notification(props: NotificationProps) -> Element { let variant = match props.variant { NotificationVariant::Warning => "notification--warning", @@ -21,7 +18,6 @@ pub fn Notification(props: NotificationProps) -> Element { class: "notification {variant}", onclick: move |event| props.on_click.call(event), h3 { class: "notification__title", "{props.title}" } - p { class: "notification__body", "{props.body}" } } ) diff --git a/src/components/atoms/radio_button.rs b/src/components/atoms/radio_button.rs index ae03f70..9036482 100644 --- a/src/components/atoms/radio_button.rs +++ b/src/components/atoms/radio_button.rs @@ -1,5 +1,4 @@ use dioxus::prelude::*; - #[derive(PartialEq, Props, Clone)] pub struct RadioButtonProps { #[props(default = "".to_string())] @@ -9,24 +8,18 @@ pub struct RadioButtonProps { checked: bool, on_change: EventHandler, } - pub fn RadioButton(props: RadioButtonProps) -> Element { rsx!( - label { - class: "radio-button {props.class}", + label { class: "radio-button {props.class}", input { class: "ration-button__cta", r#type: "radio", checked: props.checked, - onchange: move |_| { - props.on_change.call(()) - } + onchange: move |_| { props.on_change.call(()) } } div { class: "radio-button__header", div { class: "radio-custom" } - span { - {props.title} - } + span { { props.title } } } } ) diff --git a/src/components/atoms/search_input.rs b/src/components/atoms/search_input.rs index 68effac..86d516d 100644 --- a/src/components/atoms/search_input.rs +++ b/src/components/atoms/search_input.rs @@ -1,9 +1,6 @@ use dioxus::prelude::*; - use crate::components::atoms::{Icon, IconButton, Search}; - use super::dropdown::ElementSize; - #[derive(PartialEq, Props, Clone)] pub struct SearchInputProps { message: String, @@ -17,31 +14,26 @@ pub struct SearchInputProps { on_keypress: EventHandler, on_click: EventHandler, } - pub fn SearchInput(props: SearchInputProps) -> Element { let input_error_container = if let Some(_) = props.error { "input--error-container" } else { "" }; - let size = match props.size { ElementSize::Big => "input-wrapper__container--big", ElementSize::Medium => "input-wrapper__container--medium", ElementSize::Small => "input-wrapper__container--small", }; - let mut is_active = use_signal::(|| false); - rsx!( section { class: "input__wrapper input__wrapper--search", - class: if is_active() {"input__wrapper--active"}, + class: if is_active() { "input__wrapper--active" }, if let Some(value) = props.label { label { class: "input__label", "{value}" } } - div { - class: "input-wrapper {size} {input_error_container}", + div { class: "input-wrapper {size} {input_error_container}", input { r#type: "text", class: "input", @@ -54,13 +46,8 @@ pub fn SearchInput(props: SearchInputProps) -> Element { 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)" - } + Icon { icon : Search, height : 26, width : 26, stroke_width : 1.5, fill : + "var(--text-secondary)" } ), on_click: move |_| { is_active.toggle(); @@ -68,10 +55,7 @@ pub fn SearchInput(props: SearchInputProps) -> Element { } } if let Some(error) = props.error { - div { - class: "input--error", - "{error}" - } + div { class: "input--error", "{error}" } } } ) diff --git a/src/components/atoms/step.rs b/src/components/atoms/step.rs index 4a2fa78..c44f127 100644 --- a/src/components/atoms/step.rs +++ b/src/components/atoms/step.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use crate::components::atoms::{CircleShape, Glyph, Icon}; - #[derive(PartialEq, Props, Clone)] pub struct StepProps { #[props(default = false)] @@ -10,11 +8,9 @@ pub struct StepProps { is_completed: bool, #[props(default = false)] has_cube: bool, - // #[props(default = false)] name: Option, on_click: EventHandler, } - pub fn Step(props: StepProps) -> Element { rsx!( button { @@ -25,20 +21,9 @@ pub fn Step(props: StepProps) -> Element { if props.has_cube { div { class: "step__cube", if props.is_completed { - Icon { - icon: Glyph, - height: 13, - width: 16, - stroke_width: 2, - stroke: "var(--fill-400)" - } + Icon { icon: Glyph, height: 13, width: 16, stroke_width: 2, stroke: "var(--fill-400)" } } else if props.is_active { - Icon { - icon: CircleShape, - height: 12, - width: 12, - fill: "var(--fill-00)" - } + Icon { icon: CircleShape, height: 12, width: 12, fill: "var(--fill-00)" } } else { Icon { icon: CircleShape, @@ -51,9 +36,9 @@ pub fn Step(props: StepProps) -> Element { } } if let Some(name) = props.name { - span {class: "step__name", {name} } + span { class: "step__name", { name } } } - div {class: "step__line"} + div { class: "step__line" } } ) } diff --git a/src/components/atoms/step_card.rs b/src/components/atoms/step_card.rs index f1fe83c..95a2324 100644 --- a/src/components/atoms/step_card.rs +++ b/src/components/atoms/step_card.rs @@ -1,5 +1,4 @@ use dioxus::prelude::*; - #[derive(PartialEq, Props, Clone)] pub struct StepCardProps { name: String, @@ -12,11 +11,10 @@ pub struct StepCardProps { editable: Option, on_change: EventHandler, } - pub fn StepCard(props: StepCardProps) -> Element { rsx!( label { - class: "step-card {props.class}" , + class: "step-card {props.class}", class: if props.soon { "step-card--comming-soon" }, input { class: "step__cta", @@ -24,17 +22,15 @@ pub fn StepCard(props: StepCardProps) -> Element { name: props.name, disabled: props.soon, checked: props.checked, - onchange: move |_| { - props.on_change.call(()) - } + onchange: move |_| { props.on_change.call(()) } } div { class: "step-card__header", div { class: "step-custom" } - {props.body} + { props.body } } if props.checked { if let Some(editable) = props.editable { - {editable} + { editable } } } } diff --git a/src/components/atoms/subtitle.rs b/src/components/atoms/subtitle.rs index f63ffd4..ebe592c 100644 --- a/src/components/atoms/subtitle.rs +++ b/src/components/atoms/subtitle.rs @@ -1,10 +1,10 @@ use dioxus::prelude::*; - #[derive(PartialEq, Props, Clone)] pub struct ButtonProps { text: String, } - pub fn Subtitle(props: ButtonProps) -> Element { - rsx!( h3 { class: "subtitle", "{props.text}" } ) + rsx!( + h3 { class: "subtitle", "{props.text}" } + ) } diff --git a/src/components/atoms/tab.rs b/src/components/atoms/tab.rs index a0c308a..ca91e85 100644 --- a/src/components/atoms/tab.rs +++ b/src/components/atoms/tab.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use super::dropdown::ElementSize; - #[derive(PartialEq, Props, Clone)] pub struct TabProps { text: String, @@ -12,20 +10,18 @@ pub struct TabProps { on_click: EventHandler, icon: Option, } - pub fn Tab(props: TabProps) -> Element { let size = match props.size { ElementSize::Big => "tab--big", ElementSize::Medium => "tab--medium", ElementSize::Small => "tab--small", }; - rsx!( button { class: "tab {size}", - class: if props.is_active {"tab--active"}, + class: if props.is_active { "tab--active" }, onclick: move |event| props.on_click.call(event), - {props.icon} + { props.icon }, "{props.text}" } ) diff --git a/src/components/atoms/textarea.rs b/src/components/atoms/textarea.rs index c4e3d1b..e4fae8a 100644 --- a/src/components/atoms/textarea.rs +++ b/src/components/atoms/textarea.rs @@ -1,5 +1,4 @@ use dioxus::prelude::*; - #[derive(PartialEq, Props, Clone)] pub struct TextareaInputProps { value: String, @@ -9,17 +8,13 @@ pub struct TextareaInputProps { on_keypress: EventHandler, on_click: EventHandler, } - pub fn TextareaInput(props: TextareaInputProps) -> Element { let mut sent_handled = use_signal(|| false); - rsx!( - section { - class: "textarea", + section { class: "textarea", if let Some(value) = props.label { label { class: "input__label", "{value}" } } - textarea { id: "textarea", class: "textarea__wrapper input", @@ -30,7 +25,6 @@ pub fn TextareaInput(props: TextareaInputProps) -> Element { }, onkeypress: move |event| { let modifiers = event.modifiers(); - match modifiers { keyboard_types::Modifiers::SHIFT => {} _ => { @@ -39,7 +33,6 @@ pub fn TextareaInput(props: TextareaInputProps) -> Element { } } } - if modifiers.is_empty() { props.on_keypress.call(event) } diff --git a/src/components/atoms/title.rs b/src/components/atoms/title.rs index 770b884..e465872 100644 --- a/src/components/atoms/title.rs +++ b/src/components/atoms/title.rs @@ -1,10 +1,10 @@ use dioxus::prelude::*; - #[derive(PartialEq, Props, Clone)] pub struct ButtonProps { text: String, } - pub fn Title(props: ButtonProps) -> Element { - rsx!( h2 { class: "title", "{props.text}" } ) + rsx!( + h2 { class: "title", "{props.text}" } + ) } diff --git a/src/components/atoms/tooltip.rs b/src/components/atoms/tooltip.rs index b8deb77..8e19ac5 100644 --- a/src/components/atoms/tooltip.rs +++ b/src/components/atoms/tooltip.rs @@ -1,15 +1,12 @@ use dioxus::prelude::*; - #[derive(PartialEq, Props, Clone)] pub struct TooltipProps { title: String, body: String, } - pub fn Tooltip(props: TooltipProps) -> Element { rsx!( - button { - class: "tooltip", + button { class: "tooltip", h3 { class: "tooltip__title", "{props.title}" } p { class: "tooltip__body", "{props.body}" } } diff --git a/src/components/molecules/action_request_list.rs b/src/components/molecules/action_request_list.rs index 81616bd..eacbbd7 100644 --- a/src/components/molecules/action_request_list.rs +++ b/src/components/molecules/action_request_list.rs @@ -1,97 +1,82 @@ use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; - use crate::{ components::atoms::ActionRequest, - hooks::use_initiative::{ActionItem, AddMembersAction, ConvictionVote, KusamaTreasuryAction, VoteType, VotingOpenGovAction}, + hooks::use_initiative::{ + ActionItem, AddMembersAction, ConvictionVote, KusamaTreasuryAction, VoteType, + VotingOpenGovAction, + }, }; - #[derive(PartialEq, Props, Clone)] pub struct ActionRequestListProps { actions: Vec, } - pub fn ActionRequestList(props: ActionRequestListProps) -> Element { let i18 = use_i18(); - let render_add_members = |action: &AddMembersAction| { rsx!( - ActionRequest { - name: "Add Members", - details: action.members.len().to_string() - } + ActionRequest { name: "Add Members", details: action.members.len().to_string() } ul { class: "requests", for member in action.members.iter() { li { - ActionRequest { - name: format!("{}...", member.account[..10].to_string()), - } + ActionRequest { name: format!("{}...", member.account[..10].to_string()) } } } } ) }; - let render_kusama_treasury = |action: &KusamaTreasuryAction| { rsx!( - ActionRequest { - name: "Kusama Treasury Request" - } + ActionRequest { name: "Kusama Treasury Request" } ul { class: "requests", - for (index, period) in action.periods.iter().enumerate() { + for (index , period) in action.periods.iter().enumerate() { li { ActionRequest { name: format!("Periodo: #{}", index + 1), - details: format!("{} KSM", period.amount as f64 / 1_000_000_000_000.0 ) + details: format!("{} KSM", period.amount as f64 / 1_000_000_000_000.0) } } } } ) }; - let render_voting_open_gov = |action: &VotingOpenGovAction| { rsx!( - ActionRequest { - name: "Voting Open Gov", - details: action.proposals.len().to_string() - } + ActionRequest { name: "Voting Open Gov", details: action.proposals.len().to_string() } ul { class: "requests", for proposal in action.proposals.iter() { li { - match &proposal.vote { - VoteType::Standard(vote) => { - let conviction = match vote.conviction { - ConvictionVote::None => translate!(i18, "initiative.steps.actions.voting_open_gov.standard.conviction.none"), - ConvictionVote::Locked1x => translate!(i18, "initiative.steps.actions.voting_open_gov.standard.conviction.locked_1"), - ConvictionVote::Locked2x => translate!(i18, "initiative.steps.actions.voting_open_gov.standard.conviction.locked_2"), - ConvictionVote::Locked3x => translate!(i18, "initiative.steps.actions.voting_open_gov.standard.conviction.locked_3"), - ConvictionVote::Locked4x => translate!(i18, "initiative.steps.actions.voting_open_gov.standard.conviction.locked_4"), - ConvictionVote::Locked5x => translate!(i18, "initiative.steps.actions.voting_open_gov.standard.conviction.locked_5"), - ConvictionVote::Locked6x => translate!(i18, "initiative.steps.actions.voting_open_gov.standard.conviction.locked_6"), - }; - rsx!( - ActionRequest { - name: format!("{} - {}", translate!(i18, "initiative.steps.actions.voting_open_gov.standard.title"), proposal.poll_index), - details: format!("{} - {} KSM", conviction, vote.balance as f64 / 1_000_000_000_000.0 ), - } - ) - } - } + match & proposal.vote { VoteType::Standard(vote) => { let + conviction = match vote.conviction { ConvictionVote::None => translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.conviction.none"), + ConvictionVote::Locked1x => translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.conviction.locked_1"), + ConvictionVote::Locked2x => translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.conviction.locked_2"), + ConvictionVote::Locked3x => translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.conviction.locked_3"), + ConvictionVote::Locked4x => translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.conviction.locked_4"), + ConvictionVote::Locked5x => translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.conviction.locked_5"), + ConvictionVote::Locked6x => translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.conviction.locked_6"), }; + rsx!(ActionRequest { name : format!("{} - {}", translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.title"), proposal + .poll_index), details : format!("{} - {} KSM", conviction, vote.balance as + f64 / 1_000_000_000_000.0), }) } } } } } ) }; - rsx!( for request in props.actions.iter() { div { class: "requests", match request { - ActionItem::AddMembers(action) => render_add_members(&action), - ActionItem::KusamaTreasury(action) => render_kusama_treasury(&action), - ActionItem::VotingOpenGov(action) => render_voting_open_gov(&action) - } + ActionItem::AddMembers(action) => render_add_members(& action), + ActionItem::KusamaTreasury(action) => render_kusama_treasury(& action), + ActionItem::VotingOpenGov(action) => render_voting_open_gov(& action) } } } ) diff --git a/src/components/molecules/actions/members.rs b/src/components/molecules/actions/members.rs index 3e60bce..7282cbf 100644 --- a/src/components/molecules/actions/members.rs +++ b/src/components/molecules/actions/members.rs @@ -1,100 +1,57 @@ use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; - use crate::{ components::atoms::{ combo_input::{ComboInputOption, ComboInputValue}, dropdown::{DropdownItem, ElementSize}, - icon_button::Variant, - AddPlus, ComboInput, Icon, IconButton, MinusCircle, + icon_button::Variant, AddPlus, ComboInput, Icon, IconButton, MinusCircle, + }, + hooks::use_initiative::{ + use_initiative, ActionItem, AddMembersAction, MediumOptions, MemberItem, }, - hooks::use_initiative::{use_initiative, ActionItem, AddMembersAction, MediumOptions, MemberItem}, }; - #[derive(PartialEq, Props, Clone)] pub struct VotingProps { index: usize, meta: AddMembersAction, } - pub fn MembersAction(props: VotingProps) -> Element { let i18 = use_i18(); let mut initiative = use_initiative(); - rsx!( ul { class: "form__inputs form__inputs--combo", - { - props.meta.members.iter().enumerate().map(|(index_meta, member)| { - let dropdown_item = DropdownItem { key: match member.medium { - MediumOptions::Wallet => translate!(i18, "onboard.invite.form.wallet.label"), - }, value: match member.medium.clone() { - MediumOptions::Wallet => translate!(i18, "onboard.invite.form.wallet.label"), - } }; - - rsx!( - li { - ComboInput { - size: ElementSize::Small, - value: ComboInputValue { - option: ComboInputOption::Dropdown(dropdown_item), - input: member.account.clone() - }, - placeholder: match member.medium { - MediumOptions::Wallet => translate!(i18, "onboard.invite.form.wallet.placeholder"), - }, - on_change: move |event: ComboInputValue| { - let medium = match event.option { - ComboInputOption::Dropdown(value) => { - match value.key.as_str() { - "Wallet" => MediumOptions::Wallet, - _ => todo!() - } - }, - _ => todo!() - }; - if let ActionItem::AddMembers(ref mut meta) = initiative.get_action(props.index) { - meta.members[index_meta] = MemberItem { medium, account: event.input }; - initiative.update_action(props.index, ActionItem::AddMembers(meta.clone())); - } - } - } - IconButton { - variant: Variant::Round, - size: ElementSize::Small, - class: "button--avatar", - body: rsx!( - Icon { - icon: MinusCircle, - height: 24, - width: 24, - fill: "var(--state-primary-active)" - } - ), - on_click: move |_| { - if let ActionItem::AddMembers(ref mut meta) = initiative.get_action(props.index) { - meta.members.remove(index_meta); - initiative.update_action(props.index, ActionItem::AddMembers(meta.clone())); - } - } - } - } - ) - }) - } + { props.meta.members.iter() + .enumerate().map(| (index_meta, member) | { let dropdown_item = DropdownItem { + key : match member.medium { MediumOptions::Wallet => translate!(i18, + "onboard.invite.form.wallet.label"), }, value : match member.medium.clone() { + MediumOptions::Wallet => translate!(i18, "onboard.invite.form.wallet.label"), } + }; rsx!(li { ComboInput { size : ElementSize::Small, value : ComboInputValue { + option : ComboInputOption::Dropdown(dropdown_item), input : member.account + .clone() }, placeholder : match member.medium { MediumOptions::Wallet => + translate!(i18, "onboard.invite.form.wallet.placeholder"), }, on_change : move | + event : ComboInputValue | { let medium = match event.option { + ComboInputOption::Dropdown(value) => { match value.key.as_str() { "Wallet" => + MediumOptions::Wallet, _ => todo!() } }, _ => todo!() }; if let + ActionItem::AddMembers(ref mut meta) = initiative.get_action(props.index) { meta + .members[index_meta] = MemberItem { medium, account : event.input }; initiative + .update_action(props.index, ActionItem::AddMembers(meta.clone())); } } } + IconButton { variant : Variant::Round, size : ElementSize::Small, class : + "button--avatar", body : rsx!(Icon { icon : MinusCircle, height : 24, width : 24, + fill : "var(--state-primary-active)" }), on_click : move | _ | { if let + ActionItem::AddMembers(ref mut meta) = initiative.get_action(props.index) { meta + .members.remove(index_meta); initiative.update_action(props.index, + ActionItem::AddMembers(meta.clone())); } } } }) }) }, IconButton { variant: Variant::Round, size: ElementSize::Small, class: "button--avatar", body: rsx!( - Icon { - icon: AddPlus, - height: 24, - width: 24, - fill: "var(--state-primary-active)" - } + 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) { + if let ActionItem::AddMembers(ref mut meta) = initiative.get_action(props.index) + { meta.add_member(MemberItem::default()); initiative.update_action(props.index, ActionItem::AddMembers(meta.clone())); } diff --git a/src/components/molecules/actions/mod.rs b/src/components/molecules/actions/mod.rs index f653739..3706919 100644 --- a/src/components/molecules/actions/mod.rs +++ b/src/components/molecules/actions/mod.rs @@ -1,7 +1,6 @@ pub mod members; pub mod treasury; pub mod voting; - pub use members::MembersAction; pub use treasury::TreasuryAction; pub use voting::VotingAction; diff --git a/src/components/molecules/actions/treasury.rs b/src/components/molecules/actions/treasury.rs index fc18783..001f776 100644 --- a/src/components/molecules/actions/treasury.rs +++ b/src/components/molecules/actions/treasury.rs @@ -1,31 +1,24 @@ use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; - use crate::{ components::atoms::{ dropdown::{DropdownItem, ElementSize}, - icon_button::Variant, - input::InputType, - AddPlus, Icon, IconButton, Input, MinusCircle, + icon_button::Variant, input::InputType, AddPlus, Icon, IconButton, Input, + MinusCircle, + }, + hooks::use_initiative::{ + use_initiative, ActionItem, KusamaTreasury, KusamaTreasuryAction, }, - hooks::use_initiative::{use_initiative, ActionItem, KusamaTreasury, KusamaTreasuryAction}, }; - #[derive(PartialEq, Props, Clone)] pub struct VotingProps { index: usize, meta: KusamaTreasuryAction, } - const KUSAMA_PRECISION_DECIMALS: u64 = 1_000_000_000_000; - pub fn TreasuryAction(props: VotingProps) -> Element { let i18 = use_i18(); let mut initiative = use_initiative(); - - // let mut option_value = use_signal(|| props.value.option.clone()); - // let mut input_value = use_signal::(|| props.value.input.clone()); - let mut items = vec![]; let dropdown_options = vec![ DropdownItem { @@ -41,112 +34,68 @@ pub fn TreasuryAction(props: VotingProps) -> Element { value: "Split Abstain".to_string(), }, ]; - for account in dropdown_options.clone().into_iter() { - items.push(rsx!(span { - "{account.value}" - })) + items.push(rsx!( + span { "{account.value}" } + )) } - rsx!( ul { class: "form__inputs form__inputs--combo", p { class: "form__inputs__disclaimer", - {translate!(i18, "initiative.steps.actions.kusama_treasury.disclaimer.period_1")} + { translate!(i18, + "initiative.steps.actions.kusama_treasury.disclaimer.period_1") }, if props.meta.periods.len() > 1 { - {translate!(i18, "initiative.steps.actions.kusama_treasury.disclaimer.period_n")} + { translate!(i18, + "initiative.steps.actions.kusama_treasury.disclaimer.period_n") } } } - { - props.meta.periods.iter().enumerate().map(|(index_meta, period)| { - rsx!( - li { - div { - style: " - width: 100%; - display: flex; - gap: 4px; - ", - Input { - message: (period.amount / KUSAMA_PRECISION_DECIMALS).to_string(), - size: ElementSize::Small, - placeholder: translate!(i18, "initiative.steps.actions.kusama_treasury.placeholder"), - error: None, - right_text: { - rsx!( - span { class: "input--right__text", - "KSM" - } - ) - }, - on_input: move |event: Event| { - if let ActionItem::KusamaTreasury(ref mut meta) = initiative.get_action(props.index) { - // Scale amount - let amount = event.value().parse::().unwrap_or(0.0); - let scaled_amount = amount * KUSAMA_PRECISION_DECIMALS as f64; - meta.periods[index_meta].amount = scaled_amount as u64 ; - initiative.update_action(props.index, ActionItem::KusamaTreasury(meta.clone())); - } - }, - on_keypress: move |_| {}, - on_click: move |_| {}, - } - if index_meta > 0 { - Input { - message: period.date.clone(), - size: ElementSize::Small, - itype: InputType::Date, - placeholder: translate!(i18, "initiative.steps.actions.kusama_treasury.placeholder"), - error: None, - on_input: move |event: Event| { - if let ActionItem::KusamaTreasury(ref mut meta) = initiative.get_action(props.index) { - meta.periods[index_meta].date = event.value() ; - initiative.update_action(props.index, ActionItem::KusamaTreasury(meta.clone())); - } - }, - on_keypress: move |_| {}, - on_click: move |_| {}, - } - } - } - IconButton { - variant: Variant::Round, - size: ElementSize::Small, - class: "button--avatar", - body: rsx!( - Icon { - icon: MinusCircle, - height: 24, - width: 24, - fill: "var(--state-primary-active)" - } - ), - on_click: move |_| { - if let ActionItem::KusamaTreasury(ref mut meta) = initiative.get_action(props.index) { - meta.periods.remove(index_meta); - initiative.update_action(props.index, ActionItem::KusamaTreasury(meta.clone())); - } - } - } - } - ) - }) - } + { props + .meta.periods.iter().enumerate().map(| (index_meta, period) | { rsx!(li { div { + style : + " + width: 100%; + display: flex; + gap: 4px; + ", + Input { message : (period.amount / KUSAMA_PRECISION_DECIMALS).to_string(), size : + ElementSize::Small, placeholder : translate!(i18, + "initiative.steps.actions.kusama_treasury.placeholder"), error : None, right_text + : { rsx!(span { class : "input--right__text", "KSM" }) }, on_input : move | event + : Event < FormData >| { if let ActionItem::KusamaTreasury(ref mut meta) = + initiative.get_action(props.index) { let amount = event.value().parse::< f64 > () + .unwrap_or(0.0); let scaled_amount = amount * KUSAMA_PRECISION_DECIMALS as f64; + meta.periods[index_meta].amount = scaled_amount as u64; initiative + .update_action(props.index, ActionItem::KusamaTreasury(meta.clone())); } }, + on_keypress : move | _ | {}, on_click : move | _ | {}, } if index_meta > 0 { + Input { message : period.date.clone(), size : ElementSize::Small, itype : + InputType::Date, placeholder : translate!(i18, + "initiative.steps.actions.kusama_treasury.placeholder"), error : None, on_input : + move | event : Event < FormData >| { if let ActionItem::KusamaTreasury(ref mut + meta) = initiative.get_action(props.index) { meta.periods[index_meta].date = + event.value(); initiative.update_action(props.index, + ActionItem::KusamaTreasury(meta.clone())); } }, on_keypress : move | _ | {}, + on_click : move | _ | {}, } } } IconButton { variant : Variant::Round, size : + ElementSize::Small, class : "button--avatar", body : rsx!(Icon { icon : + MinusCircle, height : 24, width : 24, fill : "var(--state-primary-active)" }), + on_click : move | _ | { if let ActionItem::KusamaTreasury(ref mut meta) = + initiative.get_action(props.index) { meta.periods.remove(index_meta); initiative + .update_action(props.index, ActionItem::KusamaTreasury(meta.clone())); } } } }) + }) }, IconButton { variant: Variant::Round, size: ElementSize::Small, class: "button--avatar", body: rsx!( - Icon { - icon: AddPlus, - height: 24, - width: 24, - fill: "var(--state-primary-active)" - } + 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) { + if let ActionItem::KusamaTreasury(ref mut meta) = initiative + .get_action(props.index) + { meta.add_period(KusamaTreasury::default()); - initiative.update_action(props.index, ActionItem::KusamaTreasury(meta.clone())); + initiative + .update_action(props.index, ActionItem::KusamaTreasury(meta.clone())); } } } diff --git a/src/components/molecules/actions/voting.rs b/src/components/molecules/actions/voting.rs index dd849c8..201bbaf 100644 --- a/src/components/molecules/actions/voting.rs +++ b/src/components/molecules/actions/voting.rs @@ -1,211 +1,107 @@ use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; - use crate::{ components::atoms::{ combo_input::{ComboInputOption, ComboInputValue}, dropdown::{DropdownItem, ElementSize}, - icon_button::Variant, - AddPlus, ComboInput, Icon, IconButton, Input, MinusCircle, RadioButton, + icon_button::Variant, AddPlus, ComboInput, Icon, IconButton, Input, MinusCircle, + RadioButton, }, hooks::use_initiative::{ - use_initiative, ActionItem, ConvictionVote, StandardVote, VoteType, VotingOpenGov, - VotingOpenGovAction, + use_initiative, ActionItem, ConvictionVote, StandardVote, VoteType, + VotingOpenGov, VotingOpenGovAction, }, }; - #[derive(PartialEq, Props, Clone)] pub struct VotingProps { index: usize, meta: VotingOpenGovAction, } - const KUSAMA_PRECISION_DECIMALS: u64 = 1_000_000_000_000; - pub fn VotingAction(props: VotingProps) -> Element { let i18 = use_i18(); let mut initiative = use_initiative(); - rsx!( ul { class: "form__inputs form__inputs--combo", - { - props.meta.proposals.iter().enumerate().map(|(index_meta, proposal)| { - rsx!( - li { - div { class: "form__inputs__wrapper", - div { - Input { - message: if proposal.poll_index > 0 { proposal.poll_index.to_string() } else { String::new() }, - size: ElementSize::Small, - placeholder: "Ex: 000", - error: None, - label: translate!(i18, "initiative.steps.actions.voting_open_gov.poll_index"), - on_input: move |event: Event| { - if let ActionItem::VotingOpenGov(ref mut meta) = initiative.get_action(props.index) { - let poll_index: u64 = event.value().parse().unwrap_or(0); - meta.proposals[index_meta].poll_index = poll_index; - initiative.update_action(props.index, ActionItem::VotingOpenGov(meta.clone())); - } - }, - on_keypress: move |_| {}, - on_click: move |_| {}, - } - } - div { - match &proposal.vote { - VoteType::Standard(vote) => { - let vote_a = vote.clone(); - let mut vote_b = vote.clone(); - let mut vote_c = vote.clone(); - - rsx!( - div { - ComboInput { - size: ElementSize::Small, - value: ComboInputValue { - option: ComboInputOption::Dropdown( DropdownItem { - key: "None".to_string(), - value: "None".to_string(), - }), - input: if vote.balance > 0 { (vote.balance as f64 / KUSAMA_PRECISION_DECIMALS as f64).to_string() } else { String::new() }, - }, - placeholder: translate!(i18, "initiative.steps.actions.voting_open_gov.standard.balance"), - right_text: { - rsx!( - span { class: "input--right__text", - "KSM" - } - ) - }, - options: vec![ - DropdownItem { - key: "None".to_string(), - value: translate!(i18, "initiative.steps.actions.voting_open_gov.standard.conviction.none"), - }, - DropdownItem { - key: "Locked1x".to_string(), - value: translate!(i18, "initiative.steps.actions.voting_open_gov.standard.conviction.locked_1"), - }, - DropdownItem { - key: "Locked2x".to_string(), - value: translate!(i18, "initiative.steps.actions.voting_open_gov.standard.conviction.locked_2"), - }, - DropdownItem { - key: "Locked3x".to_string(), - value: translate!(i18, "initiative.steps.actions.voting_open_gov.standard.conviction.locked_3"), - }, - DropdownItem { - key: "Locked4x".to_string(), - value: translate!(i18, "initiative.steps.actions.voting_open_gov.standard.conviction.locked_4"), - }, - DropdownItem { - key: "Locked5x".to_string(), - value: translate!(i18, "initiative.steps.actions.voting_open_gov.standard.conviction.locked_5"), - }, - DropdownItem { - key: "Locked6x".to_string(), - value: translate!(i18, "initiative.steps.actions.voting_open_gov.standard.conviction.locked_6"), - } - ], - on_change: move |event: ComboInputValue| { - let conviction = match event.option { - ComboInputOption::Dropdown(value) => { - match value.key.as_str() { - "None" => ConvictionVote::None, - "Locked1x" => ConvictionVote::Locked1x, - "Locked2x" => ConvictionVote::Locked2x, - "Locked3x" => ConvictionVote::Locked3x, - "Locked4x" => ConvictionVote::Locked4x, - "Locked5x" => ConvictionVote::Locked5x, - "Locked6x" => ConvictionVote::Locked6x, - _ => todo!() - } - }, - _ => todo!() - }; - if let ActionItem::VotingOpenGov(ref mut meta) = initiative.get_action(props.index) { - let amount = event.input.parse::().unwrap_or(0.0); - let scaled_amount = amount * KUSAMA_PRECISION_DECIMALS as f64; - - meta.proposals[index_meta].vote = VoteType::Standard( - StandardVote { aye: vote_a.aye, conviction, balance: scaled_amount as u64 } - ); - initiative.update_action(props.index, ActionItem::VotingOpenGov(meta.clone())); - } - } - } - div { class: "form__inputs__container__cta", - RadioButton { - title: translate!(i18, "initiative.steps.actions.voting_open_gov.standard.aye"), - name: "Aye", - checked: vote.aye.clone(), - on_change: move |_| { - if let ActionItem::VotingOpenGov(ref mut meta) = initiative.get_action(props.index) { - vote_b.aye = true; - meta.proposals[index_meta].vote = VoteType::Standard(vote_b.clone()); - initiative.update_action(props.index, ActionItem::VotingOpenGov(meta.clone())); - } - } - } - RadioButton { - title: translate!(i18, "initiative.steps.actions.voting_open_gov.standard.nay"), - name: "Nay", - checked: !vote.aye.clone(), - on_change: move |_| { - if let ActionItem::VotingOpenGov(ref mut meta) = initiative.get_action(props.index) { - vote_c.aye = false; - meta.proposals[index_meta].vote = VoteType::Standard(vote_c.clone()); - initiative.update_action(props.index, ActionItem::VotingOpenGov(meta.clone())); - } - }, - } - } - } - ) - }, - } - } - } - - IconButton { - variant: Variant::Round, - size: ElementSize::Small, - class: "button--avatar", - body: rsx!( - Icon { - icon: MinusCircle, - height: 24, - width: 24, - fill: "var(--state-primary-active)" - } - ), - on_click: move |_| { - if let ActionItem::VotingOpenGov(ref mut meta) = initiative.get_action(props.index) { - meta.proposals.remove(index_meta); - initiative.update_action(props.index, ActionItem::VotingOpenGov(meta.clone())); - } - } - } - } - ) - }) - } + { props.meta.proposals.iter() + .enumerate().map(| (index_meta, proposal) | { rsx!(li { div { class : + "form__inputs__wrapper", div { Input { message : if proposal.poll_index > 0 { + proposal.poll_index.to_string() } else { String::new() }, size : + ElementSize::Small, placeholder : "Ex: 000", error : None, label : + translate!(i18, "initiative.steps.actions.voting_open_gov.poll_index"), on_input + : move | event : Event < FormData >| { if let ActionItem::VotingOpenGov(ref mut + meta) = initiative.get_action(props.index) { let poll_index : u64 = event.value() + .parse().unwrap_or(0); meta.proposals[index_meta].poll_index = poll_index; + initiative.update_action(props.index, ActionItem::VotingOpenGov(meta.clone())); } + }, on_keypress : move | _ | {}, on_click : move | _ | {}, } } div { match & + proposal.vote { VoteType::Standard(vote) => { let vote_a = vote.clone(); let mut + vote_b = vote.clone(); let mut vote_c = vote.clone(); rsx!(div { ComboInput { + size : ElementSize::Small, value : ComboInputValue { option : + ComboInputOption::Dropdown(DropdownItem { key : "None".to_string(), value : + "None".to_string(), }), input : if vote.balance > 0 { (vote.balance as f64 / + KUSAMA_PRECISION_DECIMALS as f64).to_string() } else { String::new() }, }, + placeholder : translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.balance"), right_text : { + rsx!(span { class : "input--right__text", "KSM" }) }, options : vec![DropdownItem + { key : "None".to_string(), value : translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.conviction.none"), }, + DropdownItem { key : "Locked1x".to_string(), value : translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.conviction.locked_1"), }, + DropdownItem { key : "Locked2x".to_string(), value : translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.conviction.locked_2"), }, + DropdownItem { key : "Locked3x".to_string(), value : translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.conviction.locked_3"), }, + DropdownItem { key : "Locked4x".to_string(), value : translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.conviction.locked_4"), }, + DropdownItem { key : "Locked5x".to_string(), value : translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.conviction.locked_5"), }, + DropdownItem { key : "Locked6x".to_string(), value : translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.conviction.locked_6"), }], + on_change : move | event : ComboInputValue | { let conviction = match event + .option { ComboInputOption::Dropdown(value) => { match value.key.as_str() { + "None" => ConvictionVote::None, "Locked1x" => ConvictionVote::Locked1x, + "Locked2x" => ConvictionVote::Locked2x, "Locked3x" => ConvictionVote::Locked3x, + "Locked4x" => ConvictionVote::Locked4x, "Locked5x" => ConvictionVote::Locked5x, + "Locked6x" => ConvictionVote::Locked6x, _ => todo!() } }, _ => todo!() }; if let + ActionItem::VotingOpenGov(ref mut meta) = initiative.get_action(props.index) { + let amount = event.input.parse::< f64 > ().unwrap_or(0.0); let scaled_amount = + amount * KUSAMA_PRECISION_DECIMALS as f64; meta.proposals[index_meta].vote = + VoteType::Standard(StandardVote { aye : vote_a.aye, conviction, balance : + scaled_amount as u64 }); initiative.update_action(props.index, + ActionItem::VotingOpenGov(meta.clone())); } } } div { class : + "form__inputs__container__cta", RadioButton { title : translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.aye"), name : "Aye", checked : + vote.aye.clone(), on_change : move | _ | { if let ActionItem::VotingOpenGov(ref + mut meta) = initiative.get_action(props.index) { vote_b.aye = true; meta + .proposals[index_meta].vote = VoteType::Standard(vote_b.clone()); initiative + .update_action(props.index, ActionItem::VotingOpenGov(meta.clone())); } } } + RadioButton { title : translate!(i18, + "initiative.steps.actions.voting_open_gov.standard.nay"), name : "Nay", checked : + ! vote.aye.clone(), on_change : move | _ | { if let ActionItem::VotingOpenGov(ref + mut meta) = initiative.get_action(props.index) { vote_c.aye = false; meta + .proposals[index_meta].vote = VoteType::Standard(vote_c.clone()); initiative + .update_action(props.index, ActionItem::VotingOpenGov(meta.clone())); } }, } } }) + }, } } } IconButton { variant : Variant::Round, size : ElementSize::Small, class + : "button--avatar", body : rsx!(Icon { icon : MinusCircle, height : 24, width : + 24, fill : "var(--state-primary-active)" }), on_click : move | _ | { if let + ActionItem::VotingOpenGov(ref mut meta) = initiative.get_action(props.index) { + meta.proposals.remove(index_meta); initiative.update_action(props.index, + ActionItem::VotingOpenGov(meta.clone())); } } } }) }) }, IconButton { variant: Variant::Round, size: ElementSize::Small, class: "button--avatar", body: rsx!( - Icon { - icon: AddPlus, - height: 24, - width: 24, - fill: "var(--state-primary-active)" - } + 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) { + if let ActionItem::VotingOpenGov(ref mut meta) = initiative + .get_action(props.index) + { meta.add_proposal(VotingOpenGov::default()); - initiative.update_action(props.index, ActionItem::VotingOpenGov(meta.clone())); + initiative + .update_action(props.index, ActionItem::VotingOpenGov(meta.clone())); } } } diff --git a/src/components/molecules/header.rs b/src/components/molecules/header.rs index a72b58e..03857ba 100644 --- a/src/components/molecules/header.rs +++ b/src/components/molecules/header.rs @@ -1,187 +1,165 @@ use std::str::FromStr; - use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; use futures_util::TryFutureExt; - use crate::{ components::atoms::{ dropdown::{DropdownItem, ElementSize}, - icon_button::Variant, - AccountButton, ArrowUp, ArrowUpDown, Button, Close, Dropdown, Hamburguer, Icon, IconButton, - Messages, Profile, Settings, Votes, + icon_button::Variant, AccountButton, ArrowUp, ArrowUpDown, Button, Close, + Dropdown, Hamburguer, Icon, IconButton, Messages, Profile, Settings, Votes, }, hooks::{ use_accounts::{use_accounts, IsDaoOwner}, - use_connect_wallet::use_connect_wallet, - use_notification::use_notification, + use_connect_wallet::use_connect_wallet, use_notification::use_notification, use_session::{use_session, UserSession}, }, services::kreivo::{balances::account, communities::is_admin}, }; use wasm_bindgen::prelude::*; - use pjs::PjsExtension; - #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_namespace = globalThis, js_name = setSigner)] fn set_signer(address: String); } - const APP_NAME: &str = "Virto"; - #[component] pub fn Header() -> Element { let i18 = use_i18(); let mut accounts = use_accounts(); let mut notification = use_notification(); let mut session = use_session(); - let mut ksm_balance = use_signal::<(String, String)>(|| ('0'.to_string(), "00".to_string())); - let mut usdt_balance = use_signal::<(String, String)>(|| ('0'.to_string(), "00".to_string())); + let mut ksm_balance = use_signal::< + (String, String), + >(|| ('0'.to_string(), "00".to_string())); + let mut usdt_balance = use_signal::< + (String, String), + >(|| ('0'.to_string(), "00".to_string())); let mut header_handled = consume_context::>(); - let get_account = move || { let Some(user_session) = session.get() else { return None; }; - accounts.get_one(user_session.account_id) }; - let get_balance = move || { spawn({ async move { - let pjs_account = - get_account().ok_or(translate!(i18, "errors.wallet.accounts_not_found"))?; - + let pjs_account = get_account() + .ok_or(translate!(i18, "errors.wallet.accounts_not_found"))?; let account_address = pjs_account.address(); - - let address = - sp_core::sr25519::Public::from_str(&account_address).map_err(|e| { + let address = sp_core::sr25519::Public::from_str(&account_address) + .map_err(|e| { log::warn!("Not found public address: {}", e); translate!(i18, "errors.wallet.account_address") })?; - let hex_address = hex::encode(address.0); - let Ok(account) = account(&format!("0x{}", hex_address)).await else { ksm_balance.set(('0'.to_string(), "00".to_string())); usdt_balance.set(('0'.to_string(), "00".to_string())); - if !header_handled() { header_handled.set(true); } - return Ok(()); }; - - let is_dao_owner = is_admin(&address.0).await.map_err(|_| { - log::warn!("Failed to get is admin"); - translate!(i18, "errors.wallet.account_address") - })?; - + let is_dao_owner = is_admin(&address.0) + .await + .map_err(|_| { + log::warn!("Failed to get is admin"); + translate!(i18, "errors.wallet.account_address") + })?; accounts.set_is_active_account_an_admin(IsDaoOwner(is_dao_owner)); - let unscaled_value = account.data.free as f64 / 10_f64.powf(12f64); const KSM_PRICE: f64 = 32.11; - let usdt_value = unscaled_value * KSM_PRICE; - let usdt_value = usdt_value.to_string(); let unscaled_value = unscaled_value.to_string(); - let usdt_value = usdt_value.split(".").collect::>(); let unscaled_value = unscaled_value.split(".").collect::>(); - - ksm_balance.set(( - unscaled_value[0].to_string(), - format!("{:.2}", unscaled_value.get(1).unwrap_or(&"00")), - )); - usdt_balance.set(( - usdt_value[0].to_string(), - format!("{:.2}", usdt_value.get(1).unwrap_or(&"00")), - )); + ksm_balance + .set(( + unscaled_value[0].to_string(), + format!("{:.2}", unscaled_value.get(1).unwrap_or(&"00")), + )); + usdt_balance + .set(( + usdt_value[0].to_string(), + format!("{:.2}", usdt_value.get(1).unwrap_or(&"00")), + )); if !header_handled() { header_handled.set(true); } - Ok::<(), String>(()) } - .unwrap_or_else(move |e: String| notification.handle_warning(&e)) + .unwrap_or_else(move |e: String| notification.handle_warning(&e)) }); }; - - let mut dropdown_value = use_signal::>(|| { - let account = get_account().and_then(|account| { - Some(DropdownItem { - key: account.address().clone(), - value: account.name(), - }) - }); - + let mut dropdown_value = use_signal::< + Option, + >(|| { + let account = get_account() + .and_then(|account| { + Some(DropdownItem { + key: account.address().clone(), + value: account.name(), + }) + }); account }); - let mut items = vec![]; 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 on_handle_account = move |event: u8| { header_handled.set(false); - let account = &accounts.get()[event as usize]; - - let Ok(serialized_session) = serde_json::to_string(&UserSession { - name: account.name(), - address: account.address(), - account_id: event, - }) else { + let Ok(serialized_session) = serde_json::to_string( + &UserSession { + name: account.name(), + address: account.address(), + account_id: event, + }, + ) else { return notification.handle_error(&translate!(i18, "errors.session.persist")); }; - if let Err(e) = session.persist_session_file(&serialized_session) { log::warn!("Failed to persist session {:?}", e) - }; + } if let Err(e) = session.update_account(event) { log::warn!("Failed to update account {:?}", e) - }; - + } log::info!("{:?}", account); accounts.set_account(Some(account.clone())); set_signer(account.address().clone()); - - let account = get_account().and_then(|account| { - Some(DropdownItem { - key: account.address().clone(), - value: account.name(), - }) - }); - + let account = get_account() + .and_then(|account| { + Some(DropdownItem { + key: account.address().clone(), + value: account.name(), + }) + }); dropdown_value.set(account); get_balance(); }; - use_coroutine(move |_: UnboundedReceiver<()>| async move { if session.is_logged() { match PjsExtension::connect(APP_NAME).await { Ok(mut vault) => { let Ok(_) = vault.fetch_accounts().await else { notification - .handle_error(&translate!(i18, "errors.wallet.accounts_not_found")); + .handle_error( + &translate!(i18, "errors.wallet.accounts_not_found"), + ); return; }; - let vault_accounts = vault.accounts(); accounts.set(vault_accounts); - if let Some(user_session) = session.get() { on_handle_account(user_session.account_id); } @@ -195,19 +173,16 @@ pub fn Header() -> Element { header_handled.set(true); } }); - let mut is_active = use_signal(|| false); let mut connect_handled = use_signal(|| false); - let active_class = if is_active() { "header--active" } else { "" }; - rsx!( div { class: "dashboard__header", div { class: "dashboard__header__left", - div { class: "profile"} + div { class: "profile" } div { class: "welcome", - class: if connect_handled() || session.is_logged() {"welcome--positioned"}, + class: if connect_handled() || session.is_logged() { "welcome--positioned" }, if session.is_logged() && session.get().is_some() { Dropdown { class: "header__wallet dropdown--left".to_string(), @@ -226,18 +201,13 @@ pub fn Header() -> Element { text: translate!(i18, "header.cta.connect"), status: None, right_icon: rsx!( - Icon { - icon: ArrowUp, - height: 14, - width: 14, - stroke_width: 1, - stroke: "var(--text-primary, #12352b)" - } + Icon { icon : ArrowUp, height : 14, width : 14, stroke_width : 1, stroke : + "var(--text-primary, #12352b)" } ), on_click: move |_| { use_connect_wallet(); connect_handled.toggle(); - }, + } } } else { Dropdown { @@ -263,45 +233,22 @@ pub fn Header() -> Element { variant: Variant::Round, size: ElementSize::Big, class: "button--avatar button--comming-soon", - body: rsx!( - Icon { - icon: ArrowUpDown, - height: 32, - width: 32, - fill: "var(--fill-00)" - } - ), - on_click: move |_| { } + body: rsx!(Icon { icon : ArrowUpDown, height : 32, width : 32, fill : "var(--fill-00)" }), + on_click: move |_| {} } } div { class: "balances", span { class: "balance__title", - span { class: "balance__sign", - "$" - } - span { class: "balance__value", - "{ksm_balance().0}" - } - span { class: "balance__decimals", - ".{ksm_balance().1}" - } - span { class: "balance__asset", - "KSM" - } + span { class: "balance__sign", "$" } + span { class: "balance__value", "{ksm_balance().0}" } + span { class: "balance__decimals", ".{ksm_balance().1}" } + span { class: "balance__asset", "KSM" } } span { class: "balance__subtitle", - span { class: "balance__sign", - "$" - } - span { class: "balance__value", - "{usdt_balance().0}" - } - span { class: "balance__decimals", - ".{usdt_balance().1}" - } - span { class: "balance__asset", - "USD" - } + span { class: "balance__sign", "$" } + span { class: "balance__value", "{usdt_balance().0}" } + span { class: "balance__decimals", ".{usdt_balance().1}" } + span { class: "balance__asset", "USD" } } } } @@ -310,78 +257,43 @@ 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)" - } - ), - on_click: move |_| { } + 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)" - } - ), - on_click: move |_| { } + 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)" - } - ), - on_click: move |_| { } + 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)" - } - ), - on_click: move |_| { } + 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(); } } } div { class: "header__menu mobile", - div { class: "header__scream", + div { + class: "header__scream", onclick: move |_| { is_active.toggle(); } @@ -392,14 +304,7 @@ 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(); } @@ -407,79 +312,43 @@ pub fn Header() -> Element { } ul { li { - span { - {translate!(i18, "header.menu.invitations")} - } + span { { translate!(i18, "header.menu.invitations") } } IconButton { 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)" - } - ), - on_click: move |_| { } + body: rsx!(Icon { icon : Votes, height : 32, width : 32, fill : "var(--fill-600)" }), + on_click: move |_| {} } } li { - span { - {translate!(i18, "header.menu.messages")} - } + span { { translate!(i18, "header.menu.messages") } } 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)" - } - ), - on_click: move |_| { } + body: rsx!(Icon { icon : Messages, height : 32, width : 32, fill : "var(--fill-600)" }), + on_click: move |_| {} } } li { - span { - {translate!(i18, "header.menu.profile")} - } + span { { translate!(i18, "header.menu.profile") } } 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)" - } - ), - on_click: move |_| { } + body: rsx!(Icon { icon : Profile, height : 32, width : 32, fill : "var(--fill-600)" }), + on_click: move |_| {} } } li { - span { - {translate!(i18, "header.menu.settings")} - } + span { { translate!(i18, "header.menu.settings") } } 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)" - } - ), - on_click: move |_| { } + body: rsx!(Icon { icon : Settings, height : 32, width : 32, fill : "var(--fill-600)" }), + on_click: move |_| {} } } } diff --git a/src/components/molecules/initiative/actions.rs b/src/components/molecules/initiative/actions.rs index 449f751..0209bd5 100644 --- a/src/components/molecules/initiative/actions.rs +++ b/src/components/molecules/initiative/actions.rs @@ -1,11 +1,10 @@ use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; - use crate::{ components::{ atoms::{ - dropdown::ElementSize, icon_button::Variant, AddPlus, Dropdown, Icon, IconButton, - SubstractLine, + dropdown::ElementSize, icon_button::Variant, AddPlus, Dropdown, Icon, + IconButton, SubstractLine, }, molecules::{MembersAction, TreasuryAction, VotingAction}, }, @@ -13,90 +12,35 @@ use crate::{ use_initiative, ActionItem, AddMembersAction, MediumOptions, MemberItem, }, }; - #[component] pub fn InitiativeActions() -> Element { let i18 = use_i18(); let mut initiative = use_initiative(); - let actions_lock = initiative.get_actions(); let mut items = vec![]; - for option in initiative.get_actions_options().into_iter() { - items.push(rsx!(span { - "{option.value}" - })) + items.push(rsx!( + span { "{option.value}" } + )) } - rsx!( ul { class: "form__inputs form__inputs--initiative", - { - actions_lock.iter().enumerate().map(|(index, action)| { - rsx!( - li { - div { class: "form__input", - IconButton { - variant: Variant::Round, - size: ElementSize::Small, - class: "button--action", - body: rsx!( - Icon { - icon: SubstractLine, - height: 24, - width: 24, - fill: "var(--fill-00)" - } - ), - on_click: move |_| { - initiative.remove_action(index); - } - } - Dropdown { - class: "action__option dropdown--left".to_string(), - value: Some(action.option()), - placeholder: translate!(i18, "header.cta.account"), - size: ElementSize::Small, - default: None, - on_change: move |event: usize| { - let options = initiative.get_actions_options(); - - let to_assign = &options[event]; - - initiative.update_action(index, initiative.to_action_option(to_assign.key.clone())); - }, - body: items.clone() - } - } - match action { - ActionItem::AddMembers(meta) => { - rsx!( - MembersAction { - index: index, - meta: meta.clone() - } - ) - }, - ActionItem::KusamaTreasury(meta) => { - rsx!( - TreasuryAction { - index: index, - meta: meta.clone() - } - ) - } - ActionItem::VotingOpenGov(meta) => { - rsx!( - VotingAction { - index: index, - meta: meta.clone() - } - ) - } - } - } - ) - }) - } + { actions_lock.iter() + .enumerate().map(| (index, action) | { rsx!(li { div { class : "form__input", + IconButton { variant : Variant::Round, size : ElementSize::Small, class : + "button--action", body : rsx!(Icon { icon : SubstractLine, height : 24, width : + 24, fill : "var(--fill-00)" }), on_click : move | _ | { initiative + .remove_action(index); } } Dropdown { class : "action__option dropdown--left" + .to_string(), value : Some(action.option()), placeholder : translate!(i18, + "header.cta.account"), size : ElementSize::Small, default : None, on_change : + move | event : usize | { let options = initiative.get_actions_options(); let + to_assign = & options[event]; initiative.update_action(index, initiative + .to_action_option(to_assign.key.clone())); }, body : items.clone() } } match + action { ActionItem::AddMembers(meta) => { rsx!(MembersAction { index : index, + meta : meta.clone() }) }, ActionItem::KusamaTreasury(meta) => { + rsx!(TreasuryAction { index : index, meta : meta.clone() }) } + ActionItem::VotingOpenGov(meta) => { rsx!(VotingAction { index : index, meta : + meta.clone() }) } } }) }) }, li { div { class: "form__input", Dropdown { @@ -105,27 +49,26 @@ pub fn InitiativeActions() -> Element { placeholder: translate!(i18, "header.cta.account"), size: ElementSize::Small, default: None, - on_change: move |event: usize| { - // let to_assign = &dropdown_options[event]; - - // dropdown_value.set(Some(to_assign.clone())); - }, + on_change: move |event: usize| {}, body: items } IconButton { variant: Variant::Round, size: ElementSize::Small, class: "button--action", - body: rsx!( - Icon { - icon: AddPlus, - height: 24, - width: 24, - fill: "var(--fill-00)" - } - ), + body: rsx!(Icon { icon : AddPlus, height : 24, width : 24, fill : "var(--fill-00)" }), on_click: move |_| { - initiative.push_action(ActionItem::AddMembers(AddMembersAction { members: vec![MemberItem { medium: MediumOptions::Wallet, account: String::from("") }] })); + initiative + .push_action( + ActionItem::AddMembers(AddMembersAction { + members: vec![ + MemberItem { + medium: MediumOptions::Wallet, + account: String::from(""), + }, + ], + }), + ); } } } diff --git a/src/components/molecules/initiative/confirmation.rs b/src/components/molecules/initiative/confirmation.rs index 7c8fab3..e800ed6 100644 --- a/src/components/molecules/initiative/confirmation.rs +++ b/src/components/molecules/initiative/confirmation.rs @@ -1,11 +1,9 @@ use dioxus::prelude::*; use dioxus_std::i18n::use_i18; - #[component] pub fn InitiativeConfirmation() -> Element { let i18 = use_i18(); - - rsx!(div { - class: "form__inputs", - }) + rsx!( + div { class: "form__inputs" } + ) } diff --git a/src/components/molecules/initiative/info.rs b/src/components/molecules/initiative/info.rs index 5af195e..385c36c 100644 --- a/src/components/molecules/initiative/info.rs +++ b/src/components/molecules/initiative/info.rs @@ -1,31 +1,29 @@ 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}, }; - #[component] pub fn InitiativeInfo(error: bool) -> Element { let i18 = use_i18(); let onboard = use_onboard(); let mut initiative = use_initiative(); - let mut name_maxlength = use_signal(|| 24); - rsx!( div { class: "form__inputs form__inputs--initiative", div { class: "form__input form__input--initiative", div { class: "form__input__info", span { class: "form__input__info__title", - {translate!(i18, "initiative.steps.info.name.label")} + { translate!(i18, + "initiative.steps.info.name.label") } } p { class: "form__input__info__description", - {translate!(i18, "initiative.steps.info.name.description")} + { translate!(i18, + "initiative.steps.info.name.description") } } } Input { @@ -38,45 +36,59 @@ pub fn InitiativeInfo(error: bool) -> Element { } else { None } - } else { None }, + } else { + None + }, maxlength: 150, required: true, on_input: move |event: Event| { if event.value().len() < 150 { initiative.info_mut().with_mut(|info| info.name = event.value()); } else { - name_maxlength.set(event.value().chars().count().try_into().expect("Should convert usize into u8") ); + name_maxlength + .set( + event + .value() + .chars() + .count() + .try_into() + .expect("Should convert usize into u8"), + ); } }, on_keypress: move |_| {}, - on_click: move |_| {}, + on_click: move |_| {} } } hr { class: "form__divider" } div { class: "form__input form__input--initiative", div { class: "form__input__info", span { class: "form__input__info__title", - {translate!(i18, "initiative.steps.info.description.label")} + { translate!(i18, + "initiative.steps.info.description.label") } } p { class: "form__input__info__description", - {translate!(i18, "initiative.steps.info.description.description")} + { translate!(i18, + "initiative.steps.info.description.description") } } } Markdown { content: initiative.get_info().description, on_input: move |event: MarkdownEvent| { initiative.info_mut().with_mut(|info| info.description = event.value); - }, + } } } hr { class: "form__divider" } div { class: "form__input form__input--initiative", div { class: "form__input__info", span { class: "form__input__info__title", - {translate!(i18, "initiative.steps.info.categories.label")} + { translate!(i18, + "initiative.steps.info.categories.label") } } p { class: "form__input__info__description", - {translate!(i18, "initiative.steps.info.categories.description")} + { translate!(i18, + "initiative.steps.info.categories.description") } } } InputTags { @@ -89,14 +101,16 @@ pub fn InitiativeInfo(error: bool) -> Element { } else { None } - } else { None }, + } else { + None + }, maxlength: 5, required: true, on_input: move |event: InputTagsEvent| { initiative.info_mut().with_mut(|info| info.categories = event.tags); }, on_keypress: move |_| {}, - on_click: move |_| {}, + on_click: move |_| {} } } } diff --git a/src/components/molecules/initiative/mod.rs b/src/components/molecules/initiative/mod.rs index ef04a99..88f6981 100644 --- a/src/components/molecules/initiative/mod.rs +++ b/src/components/molecules/initiative/mod.rs @@ -2,7 +2,6 @@ pub mod actions; pub mod confirmation; pub mod info; pub mod settings; - pub use actions::InitiativeActions; pub use confirmation::InitiativeConfirmation; pub use info::InitiativeInfo; diff --git a/src/components/molecules/initiative/settings.rs b/src/components/molecules/initiative/settings.rs index 1965bba..4013bf8 100644 --- a/src/components/molecules/initiative/settings.rs +++ b/src/components/molecules/initiative/settings.rs @@ -1,6 +1,5 @@ use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; - use crate::{ components::atoms::{ dropdown::{DropdownItem, ElementSize}, @@ -11,16 +10,13 @@ use crate::{ use_spaces_client::use_spaces_client, }, }; - #[component] pub fn InitiativeSettings() -> Element { let i18 = use_i18(); let mut onboard = use_onboard(); let mut notification = use_notification(); let spaces_client = use_spaces_client(); - let mut dropdown_value = use_signal::>(|| None); - let mut items = vec![]; let mut dropdown_options = vec![ DropdownItem { @@ -32,23 +28,17 @@ pub fn InitiativeSettings() -> Element { value: "Community".to_string(), }, ]; - for account in dropdown_options.clone().into_iter() { - items.push(rsx!(span { - "{account.value}" - })) + items.push(rsx!( + span { "{account.value}" } + )) } - rsx!( div { class: "form__inputs form__inputs--initiative", div { class: "form__input form__input--initiative", div { class: "form__input__info", - span { class: "form__input__info__title", - "Origin" - } - p { class: "form__input__info__description", - "Lorem Ipsum Dolor" - } + span { class: "form__input__info__title", "Origin" } + p { class: "form__input__info__description", "Lorem Ipsum Dolor" } } Dropdown { class: "header__wallet dropdown--left".to_string(), diff --git a/src/components/molecules/mod.rs b/src/components/molecules/mod.rs index e853e51..5d30306 100644 --- a/src/components/molecules/mod.rs +++ b/src/components/molecules/mod.rs @@ -5,7 +5,6 @@ pub mod initiative; pub mod onboarding; pub mod sidebar; pub mod tabs; - pub use action_request_list::ActionRequestList; pub use actions::*; pub use header::Header; diff --git a/src/components/molecules/onboarding/basics.rs b/src/components/molecules/onboarding/basics.rs index 28c9336..eb1eba5 100644 --- a/src/components/molecules/onboarding/basics.rs +++ b/src/components/molecules/onboarding/basics.rs @@ -1,31 +1,26 @@ use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; - use crate::{ components::atoms::{dropdown::ElementSize, Attach, Input, TextareaInput, Title}, hooks::{ - use_attach::AttachFile, use_notification::use_notification, use_onboard::use_onboard, - use_spaces_client::use_spaces_client, + use_attach::AttachFile, use_notification::use_notification, + use_onboard::use_onboard, use_spaces_client::use_spaces_client, }, }; - #[component] pub fn OnboardingBasics(error: bool) -> Element { let i18 = use_i18(); let mut onboard = use_onboard(); let mut notification = use_notification(); let spaces_client = use_spaces_client(); - let mut name_maxlength = use_signal(|| 24); - rsx!( div { class: "form__title", span { class: "label", - {translate!(i18, "onboard.basics.label")} - } - Title { - text: translate!(i18, "onboard.basics.title") + { translate!(i18, + "onboard.basics.label") } } + Title { text: translate!(i18, "onboard.basics.title") } } div { class: "form__inputs", Attach { @@ -33,9 +28,10 @@ pub fn OnboardingBasics(error: bool) -> Element { supported_types: vec![String::from("image/png"), String::from("image/png")], on_change: move |event: AttachFile| { spawn(async move { - let Ok(uri) = spaces_client.get().upload(&event.data, &event.name).await else { + let Ok(uri) = spaces_client.get().upload(&event.data, &event.name).await + else { notification.handle_error(&translate!(i18, "errors.form.upload_fail")); - return + return; }; onboard.basics_mut().with_mut(|basics| basics.logo = Some(uri)) }); @@ -51,18 +47,28 @@ pub fn OnboardingBasics(error: bool) -> Element { } else { None } - } else { None }, + } else { + None + }, maxlength: name_maxlength(), required: true, on_input: move |event: Event| { if event.value().as_bytes().len() < 24usize { onboard.basics_mut().with_mut(|basics| basics.name = event.value()); } else { - name_maxlength.set(event.value().chars().count().try_into().expect("Should convert usize into u8") ); + name_maxlength + .set( + event + .value() + .chars() + .count() + .try_into() + .expect("Should convert usize into u8"), + ); } }, on_keypress: move |_| {}, - on_click: move |_| {}, + on_click: move |_| {} } TextareaInput { value: onboard.get_basics().description, @@ -71,9 +77,8 @@ pub fn OnboardingBasics(error: bool) -> Element { onboard.basics_mut().with_mut(|basics| basics.description = event.value()); }, on_keypress: move |_| {}, - on_click: move |_| {}, + on_click: move |_| {} } - Input { message: onboard.get_basics().industry, size: ElementSize::Big, @@ -84,13 +89,15 @@ pub fn OnboardingBasics(error: bool) -> Element { } else { None } - } else { None }, + } else { + None + }, required: true, on_input: move |event: Event| { onboard.basics_mut().with_mut(|basics| basics.industry = event.value()); }, on_keypress: move |_| {}, - on_click: move |_| {}, + on_click: move |_| {} } } ) diff --git a/src/components/molecules/onboarding/invite.rs b/src/components/molecules/onboarding/invite.rs index 9ba14ef..0db244d 100644 --- a/src/components/molecules/onboarding/invite.rs +++ b/src/components/molecules/onboarding/invite.rs @@ -1,121 +1,79 @@ use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; - use crate::{ components::atoms::{ combo_input::{ComboInputOption, ComboInputValue}, dropdown::{DropdownItem, ElementSize}, - icon_button::Variant, - AddPlus, ComboInput, Icon, IconButton, MinusCircle, Title, + icon_button::Variant, AddPlus, ComboInput, Icon, IconButton, MinusCircle, Title, }, hooks::use_onboard::{use_onboard, InvitationItem, MediumOptions}, }; - #[component] pub fn OnboardingInvite() -> Element { let i18 = use_i18(); let mut onboard = use_onboard(); - let members_lock = onboard.get_invitations(); let mut to_pay = consume_context::>(); - - use_effect(use_reactive(&onboard.get_invitations().len(), move |_| { - let members = onboard - .get_invitations() - .into_iter() - .filter_map(|invitation| { - if !invitation.account.is_empty() { - Some(invitation.account) - } else { - None - } - }) - .collect::>(); - - to_pay.set(0.51 + 0.11 + members.len() as f64 * 0.3) - })); - + use_effect( + use_reactive( + &onboard.get_invitations().len(), + move |_| { + let members = onboard + .get_invitations() + .into_iter() + .filter_map(|invitation| { + if !invitation.account.is_empty() { + Some(invitation.account) + } else { + None + } + }) + .collect::>(); + to_pay.set(0.51 + 0.11 + members.len() as f64 * 0.3) + }, + ), + ); rsx!( div { class: "form__title", span { class: "label", - {translate!(i18, "onboard.invite.label")} - } - Title { - text: translate!(i18, "onboard.invite.title") + { translate!(i18, + "onboard.invite.label") } } + Title { text: translate!(i18, "onboard.invite.title") } } ul { class: "form__inputs", - { - members_lock.iter().enumerate().map(|(index, member)| { - let x = DropdownItem { key: match member.medium { - MediumOptions::Wallet => translate!(i18, "onboard.invite.form.wallet.label"), - }, value: match member.medium.clone() { - MediumOptions::Wallet => translate!(i18, "onboard.invite.form.wallet.label"), - } }; - - rsx!( - li { - ComboInput { - size: ElementSize::Big, - value: ComboInputValue { - option: ComboInputOption::Dropdown(x), - input: member.account.clone() - }, - placeholder: match member.medium { - MediumOptions::Wallet => translate!(i18, "onboard.invite.form.wallet.placeholder"), - }, - on_change: move |event: ComboInputValue| { - let medium = match event.option { - ComboInputOption::Dropdown(value) => { - match value.key.as_str() { - "Wallet" => MediumOptions::Wallet, - _ => todo!() - } - }, - _ => todo!() - }; - - onboard.update_invitation(index, InvitationItem { medium, account: event.input }); - } - } - IconButton { - variant: Variant::Round, - size: ElementSize::Medium, - class: "button--avatar", - body: rsx!( - Icon { - icon: MinusCircle, - height: 24, - width: 24, - fill: "var(--state-primary-active)" - } - ), - on_click: move |_| { - onboard.remove_invitation(index); - } - } - } - ) - }) - } + { members_lock.iter() + .enumerate().map(| (index, member) | { let x = DropdownItem { key : match member + .medium { MediumOptions::Wallet => translate!(i18, + "onboard.invite.form.wallet.label"), }, value : match member.medium.clone() { + MediumOptions::Wallet => translate!(i18, "onboard.invite.form.wallet.label"), } + }; rsx!(li { ComboInput { size : ElementSize::Big, value : ComboInputValue { + option : ComboInputOption::Dropdown(x), input : member.account.clone() }, + placeholder : match member.medium { MediumOptions::Wallet => translate!(i18, + "onboard.invite.form.wallet.placeholder"), }, on_change : move | event : + ComboInputValue | { let medium = match event.option { + ComboInputOption::Dropdown(value) => { match value.key.as_str() { "Wallet" => + MediumOptions::Wallet, _ => todo!() } }, _ => todo!() }; onboard + .update_invitation(index, InvitationItem { medium, account : event.input }); } } + IconButton { variant : Variant::Round, size : ElementSize::Medium, class : + "button--avatar", body : rsx!(Icon { icon : MinusCircle, height : 24, width : 24, + fill : "var(--state-primary-active)" }), on_click : move | _ | { onboard + .remove_invitation(index); } } }) }) }, IconButton { variant: Variant::Round, size: ElementSize::Medium, class: "button--avatar", body: rsx!( - Icon { - icon: AddPlus, - height: 24, - width: 24, - fill: "var(--state-primary-active)" - } + Icon { icon : AddPlus, height : 24, width : 24, fill : + "var(--state-primary-active)" } ), on_click: move |_| { - onboard.push_invitation(InvitationItem { - medium: MediumOptions::Wallet, - account: String::from(""), - }); - } + onboard + .push_invitation(InvitationItem { + medium: MediumOptions::Wallet, + account: String::from(""), + }); + } } } ) diff --git a/src/components/molecules/onboarding/management.rs b/src/components/molecules/onboarding/management.rs index 33331d7..d36f01c 100644 --- a/src/components/molecules/onboarding/management.rs +++ b/src/components/molecules/onboarding/management.rs @@ -1,26 +1,22 @@ use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; - use crate::{ components::atoms::{ CheckboxCard, Icon, KeyFill, MedalFill, ShieldKeyholeFill, TeamFill, Title, }, hooks::use_onboard::{use_onboard, ManagementOptions}, }; - #[component] pub fn OnboardingManagement() -> Element { let i18 = use_i18(); let mut onboard = use_onboard(); - rsx!( div { class: "form__title", span { class: "label", - {translate!(i18, "onboard.management.label")} - } - Title { - text: translate!(i18, "onboard.management.title") + { translate!(i18, + "onboard.management.label") } } + Title { text: translate!(i18, "onboard.management.title") } } div { class: "form__inputs", CheckboxCard { @@ -28,18 +24,13 @@ pub fn OnboardingManagement() -> Element { title: translate!(i18, "onboard.management.form.membership.title"), description: translate!(i18, "onboard.management.form.membership.description"), name: String::from("management"), - checked: matches!(onboard.get_management().value, ManagementOptions::Membership ), - icon: rsx!( - Icon { - icon: TeamFill, - height: 20, - width: 20, - fill: "var(--fill-600)" - } - ), + checked: matches!(onboard.get_management().value, ManagementOptions::Membership), + icon: rsx!(Icon { icon : TeamFill, height : 20, width : 20, fill : "var(--fill-600)" }), on_change: move |_| { - onboard.management_mut().with_mut(|management| management.value = ManagementOptions::Membership); - }, + onboard + .management_mut() + .with_mut(|management| management.value = ManagementOptions::Membership); + } } CheckboxCard { id: "a".to_string(), @@ -48,15 +39,8 @@ pub fn OnboardingManagement() -> Element { name: String::from("management"), checked: false, soon: true, - icon: rsx!( - Icon { - icon: MedalFill, - height: 20, - width: 20, - fill: "var(--fill-600)" - } - ), - on_change: move |_| {}, + icon: rsx!(Icon { icon : MedalFill, height : 20, width : 20, fill : "var(--fill-600)" }), + on_change: move |_| {} } CheckboxCard { id: "a".to_string(), @@ -65,15 +49,8 @@ pub fn OnboardingManagement() -> Element { name: String::from("management"), checked: false, soon: true, - icon: rsx!( - Icon { - icon: KeyFill, - height: 20, - width: 20, - fill: "var(--fill-600)" - } - ), - on_change: move |_| {}, + icon: rsx!(Icon { icon : KeyFill, height : 20, width : 20, fill : "var(--fill-600)" }), + on_change: move |_| {} } CheckboxCard { id: "a".to_string(), @@ -83,14 +60,10 @@ pub fn OnboardingManagement() -> Element { checked: false, soon: true, icon: rsx!( - Icon { - icon: ShieldKeyholeFill, - height: 20, - width: 20, - fill: "var(--fill-600)" - } + Icon { icon : ShieldKeyholeFill, height : 20, width : 20, fill : + "var(--fill-600)" } ), - on_change: move |_| {}, + on_change: move |_| {} } } ) diff --git a/src/components/molecules/onboarding/mod.rs b/src/components/molecules/onboarding/mod.rs index 80f707d..d7dd780 100644 --- a/src/components/molecules/onboarding/mod.rs +++ b/src/components/molecules/onboarding/mod.rs @@ -1,7 +1,6 @@ pub mod basics; pub mod invite; pub mod management; - pub use basics::OnboardingBasics; pub use invite::OnboardingInvite; pub use management::OnboardingManagement; diff --git a/src/components/molecules/sidebar.rs b/src/components/molecules/sidebar.rs index 7fa9cba..59544b2 100644 --- a/src/components/molecules/sidebar.rs +++ b/src/components/molecules/sidebar.rs @@ -1,24 +1,19 @@ use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; use futures_util::StreamExt; - use crate::{ components::atoms::{ - avatar::Variant, dropdown::ElementSize, icon_button, AddPlus, Avatar, Compass, Hamburguer, - Home, Icon, IconButton, + avatar::Variant, dropdown::ElementSize, icon_button, AddPlus, Avatar, Compass, + Hamburguer, Home, Icon, IconButton, }, hooks::{ - use_accounts::use_accounts, - use_communities::use_communities, - use_notification::use_notification, - use_our_navigator::use_our_navigator, + use_accounts::use_accounts, use_communities::use_communities, + use_notification::use_notification, use_our_navigator::use_our_navigator, use_tooltip::{use_tooltip, TooltipItem}, }, - middlewares::is_dao_owner::is_dao_owner, - pages::dashboard::Community, + middlewares::is_dao_owner::is_dao_owner, pages::dashboard::Community, services::kreivo::community_memberships::get_communities_by_member, }; - #[component] pub fn Sidebar() -> Element { let i18 = use_i18(); @@ -27,32 +22,23 @@ pub fn Sidebar() -> Element { let mut tooltip = use_tooltip(); let mut nav = use_our_navigator(); let mut notification = use_notification(); - let header_handled = consume_context::>(); let mut is_active = use_signal(|| false); let mut communities_by_address = use_signal::>(|| vec![]); - let active_class = if is_active() { "sidebar--active" } else { "" }; - rsx!( - section { - class: "sidebar {active_class}", - IconButton { + section { class: "sidebar {active_class}", + IconButton { class: "button--hamburguer", body: rsx!( - Icon { - icon: Hamburguer, - height: 30, - width: 30, - stroke_width: 2, - stroke: "var(--text-1)" - } + Icon { icon : Hamburguer, height : 30, width : 30, stroke_width : 2, stroke : + "var(--text-1)" } ), on_click: move |_| { is_active.toggle(); } } - div { class: "sidebar__container", + div { class: "sidebar__container", div { class: "sidebar__scream", onclick: move |_| { @@ -60,87 +46,62 @@ pub fn Sidebar() -> Element { } } ul { class: "sidebar__list", - if !communities.get_community().name.is_empty() || communities.get_community().logo.is_some() { - li { class: "sidebar__item sidebar__item--uncomplete", - onclick: move |_|{}, + if !communities.get_community().name.is_empty() + || communities.get_community().logo.is_some() + { + li { + class: "sidebar__item sidebar__item--uncomplete", + onclick: move |_| {}, IconButton { class: "button--avatar", body: rsx!( - Avatar { - name: "{communities.get_community().name}", - size: 60, - uri: communities.get_community().logo, - variant: Variant::SemiRound - } + Avatar { name : "{communities.get_community().name}", size : 60, uri : + communities.get_community().logo, variant : Variant::SemiRound } ), - on_click: move |_| { } - } - span { - {communities.get_community().name} + on_click: move |_| {} } + span { { communities.get_community().name } } } } - li { class: "sidebar__item", - onclick: move |_|{}, + li { class: "sidebar__item", onclick: move |_| {}, IconButton { 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)" - } + Icon { icon : Home, height : 32, width : 32, stroke_width : 1, fill : + "var(--fill-00)" } ), on_click: move |_| { nav.push(vec![], "/"); } } - span { - {translate!(i18, "sidebar.cta")} - } + span { { translate!(i18, "sidebar.cta") } } } - li { class: "sidebar__item", - onclick: move |_|{}, + li { class: "sidebar__item", onclick: move |_| {}, IconButton { 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)" - } + Icon { icon : Compass, height : 32, width : 32, stroke_width : 1.5, fill : + "var(--fill-00)" } ), on_click: move |_| { tooltip.hide(); nav.push(vec![Box::new(is_dao_owner())], "/explore"); } } - span { - {translate!(i18, "sidebar.cta")} - } + span { { translate!(i18, "sidebar.cta") } } } - li { class: "sidebar__item", - onclick: move |_|{}, + li { class: "sidebar__item", onclick: move |_| {}, IconButton { class: "button--icon bg--state-primary-active", size: ElementSize::Big, variant: icon_button::Variant::Round, body: rsx!( - Icon { - icon: AddPlus, - height: 32, - width: 32, - stroke_width: 1.5, - fill: "var(--fill-00)" - } + Icon { icon : AddPlus, height : 32, width : 32, stroke_width : 1.5, fill : + "var(--fill-00)" } ), on_click: move |_| { tooltip.hide(); @@ -148,34 +109,26 @@ pub fn Sidebar() -> Element { } } span { - {translate!(i18, "sidebar.cta")} + { + translate!(i18, "sidebar.cta") } } } - hr { class: "sidebar__divider" } - for community in communities_by_address.read().iter() { - li { class: "sidebar__item", - onclick: move |_|{}, + li { class: "sidebar__item", onclick: move |_| {}, IconButton { class: "button--avatar", body: rsx!( - Avatar { - name: "{community.name}", - size: 60, - uri: None, - variant: Variant::Round - } + Avatar { name : "{community.name}", size : 60, uri : None, variant : + Variant::Round } ), - on_click: move |_| { } + on_click: move |_| {} } - span { - "{community.name}" - }, + span { "{community.name}" } } } } } - } + } ) } diff --git a/src/components/molecules/tabs.rs b/src/components/molecules/tabs.rs index 0688cbf..29a568e 100644 --- a/src/components/molecules/tabs.rs +++ b/src/components/molecules/tabs.rs @@ -1,22 +1,18 @@ use dioxus::prelude::*; - #[derive(PartialEq, Props, Clone, Default)] pub struct TabItem { pub k: String, pub value: String, } - #[derive(PartialEq, Props, Clone)] pub struct TabsProps { body: Vec, } - pub fn Tabs(props: TabsProps) -> Element { - rsx!( section { class: "tabs", - {props.body.into_iter().map(|item| { - rsx!( - {item} - ) - })} - }) + rsx!( + section { class: "tabs", + { props.body.into_iter().map(| item | { rsx!({ item }) + }) } + } + ) } diff --git a/src/hooks/use_accounts.rs b/src/hooks/use_accounts.rs index 98b7e89..ba6292e 100644 --- a/src/hooks/use_accounts.rs +++ b/src/hooks/use_accounts.rs @@ -1,65 +1,51 @@ use dioxus::prelude::*; - use pjs::Account as PjsAccount; - pub type Account = PjsAccount; pub type Accounts = Vec; - pub struct IsDaoOwner(pub bool); - pub fn use_accounts() -> UseAccountsState { let accounts = consume_context::>>(); let account = consume_context::>>(); let is_dao_owner = consume_context::>(); - use_hook(|| UseAccountsState { inner: accounts, account, is_dao_owner, }) } - #[derive(Clone, Copy)] pub struct UseAccountsState { inner: Signal, account: Signal>, is_dao_owner: Signal, } - impl UseAccountsState { pub fn get(&self) -> Accounts { self.inner.read().clone() } - pub fn get_one(&self, index: u8) -> Option { let accounts = self.inner.read(); let account = accounts.get(index as usize); account.cloned() } - pub fn set(&mut self, accounts: Accounts) { let mut inner = self.inner.write(); *inner = accounts; } - pub fn get_account(&self) -> Option { self.account.read().clone() } - pub fn set_account(&mut self, account: Option) { let mut c = self.account.write(); *c = account; } - pub fn is_active_account_an_admin(&self) -> bool { self.is_dao_owner.read().0.clone() } - pub fn set_is_active_account_an_admin(&mut self, is_dao_owner: IsDaoOwner) { let mut c = self.is_dao_owner.write(); *c = is_dao_owner; } - pub fn default(&mut self) { self.set(Accounts::default()) } diff --git a/src/hooks/use_attach.rs b/src/hooks/use_attach.rs index 8e20b82..9eaf6aa 100644 --- a/src/hooks/use_attach.rs +++ b/src/hooks/use_attach.rs @@ -1,7 +1,6 @@ use dioxus::prelude::*; use gloo::file::ObjectUrl; use mime::Mime; - #[derive(Clone)] pub struct AttachFile { pub name: String, @@ -10,35 +9,28 @@ pub struct AttachFile { pub content_type: Mime, pub size: u64, } - #[derive(Clone, Debug)] pub enum AttachError { NotFound, UncoverType, UnknownContent, } - pub fn use_attach() -> UseAttachState { let attach = consume_context::>>(); - use_hook(move || UseAttachState { inner: attach }) } - #[derive(Clone, Copy)] pub struct UseAttachState { inner: Signal>, } - impl UseAttachState { pub fn get(&self) -> Option { self.inner.read().as_ref().cloned() } - pub fn set(&mut self, value: Option) { let mut inner = self.inner.write(); *inner = value; } - pub fn get_file(&self) -> Result { let attach_read = self.inner.read().as_ref().cloned(); match attach_read { @@ -46,7 +38,6 @@ impl UseAttachState { None => Err(AttachError::NotFound), } } - pub fn reset(&mut self) { self.set(None) } diff --git a/src/hooks/use_communities.rs b/src/hooks/use_communities.rs index 0c87b60..edc4b99 100644 --- a/src/hooks/use_communities.rs +++ b/src/hooks/use_communities.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use crate::components::atoms::dropdown::DropdownItem; - #[derive(Clone, Debug, Default)] pub struct Community { pub id: String, @@ -10,49 +8,39 @@ pub struct Community { pub description: String, pub logo: Option, } - pub type Communities = Vec; - pub fn use_communities() -> UseCommunitiesState { let communities = consume_context::>(); let community = consume_context::>(); - use_hook(|| UseCommunitiesState { inner: communities, community, }) } - #[derive(Clone, Copy)] pub struct UseCommunitiesState { inner: Signal, community: Signal, } - impl UseCommunitiesState { pub fn get(&self) -> Communities { self.inner.read().clone() } - pub fn set(&mut self, communities: Communities) { let mut inner = self.inner.write(); *inner = communities; } - pub fn push(&mut self, community: Community) { let mut inner = self.inner.write(); inner.push(community); } - pub fn get_community(&self) -> Community { self.community.read().clone() } - pub fn set_community(&mut self, community: Community) { let mut c = self.community.write(); *c = community; } - pub fn default(&mut self) { self.set(Communities::default()) } diff --git a/src/hooks/use_connect_wallet.rs b/src/hooks/use_connect_wallet.rs index b09a174..476ed4a 100644 --- a/src/hooks/use_connect_wallet.rs +++ b/src/hooks/use_connect_wallet.rs @@ -1,47 +1,42 @@ use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; use futures_util::TryFutureExt; - use super::{use_accounts::use_accounts, use_notification::use_notification}; - pub enum PjsError { ConnectionFailed, AccountsNotFound, } - pub fn use_connect_wallet() { let i18 = use_i18(); let mut accounts = use_accounts(); let mut notification = use_notification(); let mut pjs = use_context::>>(); - use_coroutine(|_: UnboundedReceiver<()>| { async move { let mut vault = pjs::PjsExtension::connect("virto") .await .map_err(|_| PjsError::ConnectionFailed)?; - - vault - .fetch_accounts() - .await - .map_err(|_| PjsError::AccountsNotFound)?; + vault.fetch_accounts().await.map_err(|_| PjsError::AccountsNotFound)?; let vault_accounts = vault.accounts(); - accounts.set(vault_accounts); - pjs.set(Some(vault)); - Ok::<(), PjsError>(()) } - .unwrap_or_else(move |e: PjsError| { - match e { - PjsError::ConnectionFailed => { - notification.handle_error(&translate!(i18, "errors.wallet.connection_failed")) - } - PjsError::AccountsNotFound => { - notification.handle_error(&translate!(i18, "errors.wallet.accounts_not_found")); - } - }; - }) + .unwrap_or_else(move |e: PjsError| { + match e { + PjsError::ConnectionFailed => { + notification + .handle_error( + &translate!(i18, "errors.wallet.connection_failed"), + ) + } + PjsError::AccountsNotFound => { + notification + .handle_error( + &translate!(i18, "errors.wallet.accounts_not_found"), + ); + } + }; + }) }); } diff --git a/src/hooks/use_initiative.rs b/src/hooks/use_initiative.rs index 86d7ab6..26ca64b 100644 --- a/src/hooks/use_initiative.rs +++ b/src/hooks/use_initiative.rs @@ -1,51 +1,41 @@ use dioxus::prelude::*; use serde::{Deserialize, Serialize}; - use crate::components::atoms::dropdown::DropdownItem; - #[derive(Clone, Default, Deserialize, Serialize, Debug)] pub struct InfoForm { pub name: String, pub description: String, pub categories: Vec, } - #[derive(PartialEq, Clone, Default, Deserialize, Serialize, Debug)] pub enum MediumOptions { #[default] Wallet, } - #[derive(PartialEq, Clone, Default, Deserialize, Serialize, Debug)] pub struct MemberItem { pub medium: MediumOptions, pub account: String, } - pub type Members = Vec; - #[derive(PartialEq, Clone, Default, Deserialize, Serialize, Debug)] pub struct KusamaTreasury { pub date: String, pub amount: u64, } - #[derive(PartialEq, Clone, Default, Deserialize, Serialize, Debug)] pub struct KusamaTreasuryPeriod { pub blocks: Option, pub amount: u64, } - #[derive(PartialEq, Clone, Debug, Deserialize, Serialize, Default)] pub struct AddMembersAction { pub members: Members, } - impl AddMembersAction { pub fn add_member(&mut self, member: MemberItem) { self.members.push(member); } - pub fn update_member(&mut self, index: usize, member: MemberItem) { if index < self.members.len() { self.members[index] = member; @@ -53,7 +43,6 @@ impl AddMembersAction { println!("Index out of bounds."); } } - pub fn remove_member(&mut self, index: usize) { if index < self.members.len() { self.members.remove(index); @@ -62,19 +51,15 @@ impl AddMembersAction { } } } - pub type KusamaTreasuryPeriods = Vec; - #[derive(PartialEq, Clone, Debug, Deserialize, Serialize, Default)] pub struct KusamaTreasuryAction { pub periods: KusamaTreasuryPeriods, } - impl KusamaTreasuryAction { pub fn add_period(&mut self, period: KusamaTreasury) { self.periods.push(period); } - pub fn update_period(&mut self, index: usize, period: KusamaTreasury) { if index < self.periods.len() { self.periods[index] = period; @@ -82,7 +67,6 @@ impl KusamaTreasuryAction { println!("Index out of bounds."); } } - pub fn remove_period(&mut self, index: usize) { if index < self.periods.len() { self.periods.remove(index); @@ -91,7 +75,6 @@ impl KusamaTreasuryAction { } } } - #[derive(PartialEq, Clone, Default, Deserialize, Serialize, Debug)] pub enum ConvictionVote { #[default] @@ -103,19 +86,16 @@ pub enum ConvictionVote { Locked5x, Locked6x, } - #[derive(PartialEq, Clone, Debug, Deserialize, Serialize, Default)] pub struct StandardVote { pub aye: bool, pub conviction: ConvictionVote, pub balance: u64, } - #[derive(PartialEq, Clone, Deserialize, Serialize, Debug)] pub enum VoteType { Standard(StandardVote), } - impl Default for VoteType { fn default() -> Self { VoteType::Standard(StandardVote { @@ -125,49 +105,40 @@ impl Default for VoteType { }) } } - impl VoteType { pub fn key_string(&self) -> &str { match *self { - VoteType::Standard(_) => "Standard" + VoteType::Standard(_) => "Standard", } } } - #[derive(PartialEq, Clone, Default, Deserialize, Serialize, Debug)] pub struct VotingOpenGov { pub poll_index: u64, pub vote: VoteType, } - impl VotingOpenGov { pub fn serialize_vote_type(&self) -> serde_json::Value { match &self.vote { - VoteType::Standard(vote) => serde_json::json!({ - "pollIndex": self.poll_index, - "vote": { - "type": "Standard", - "aye": vote.aye, - "conviction": vote.conviction, - "balance": vote.balance - } - }) + VoteType::Standard(vote) => { + serde_json::json!( + { "pollIndex" : self.poll_index, "vote" : { "type" : "Standard", + "aye" : vote.aye, "conviction" : vote.conviction, "balance" : vote + .balance } } + ) + } } } } - pub type VotingOpenGovActionProposals = Vec; - #[derive(PartialEq, Clone, Debug, Deserialize, Serialize, Default)] pub struct VotingOpenGovAction { pub proposals: VotingOpenGovActionProposals, } - impl VotingOpenGovAction { pub fn add_proposal(&mut self, proposal: VotingOpenGov) { self.proposals.push(proposal); } - pub fn update_proposal(&mut self, index: usize, proposal: VotingOpenGov) { if index < self.proposals.len() { self.proposals[index] = proposal; @@ -175,7 +146,6 @@ impl VotingOpenGovAction { println!("Index out of bounds."); } } - pub fn remove_proposal(&mut self, index: usize) { if index < self.proposals.len() { self.proposals.remove(index); @@ -184,7 +154,6 @@ impl VotingOpenGovAction { } } } - #[derive(PartialEq, Clone, Deserialize, Serialize, Debug)] #[serde(tag = "action_type")] pub enum ActionItem { @@ -192,34 +161,39 @@ pub enum ActionItem { KusamaTreasury(KusamaTreasuryAction), VotingOpenGov(VotingOpenGovAction), } - impl ActionItem { pub fn option(&self) -> DropdownItem { match self { - ActionItem::AddMembers(_) => DropdownItem { - key: "AddMembers".to_string(), - value: "Add Members".to_string(), - }, - ActionItem::KusamaTreasury(_) => DropdownItem { - key: "KusamaTreasury".to_string(), - value: "Kusama - Request treasury spend".to_string(), - }, - ActionItem::VotingOpenGov(_) => DropdownItem { - key: "VotingOpenGov".to_string(), - value: "Kusama - Vote in OpenGov".to_string(), - }, + ActionItem::AddMembers(_) => { + DropdownItem { + key: "AddMembers".to_string(), + value: "Add Members".to_string(), + } + } + ActionItem::KusamaTreasury(_) => { + DropdownItem { + key: "KusamaTreasury".to_string(), + value: "Kusama - Request treasury spend".to_string(), + } + } + ActionItem::VotingOpenGov(_) => { + DropdownItem { + key: "VotingOpenGov".to_string(), + value: "Kusama - Vote in OpenGov".to_string(), + } + } } } - fn to_option(option: String) -> ActionItem { match &*option { "AddMembers" => ActionItem::AddMembers(AddMembersAction::default()), - "KusamaTreasury" => ActionItem::KusamaTreasury(KusamaTreasuryAction::default()), + "KusamaTreasury" => { + ActionItem::KusamaTreasury(KusamaTreasuryAction::default()) + } "VotingOpenGov" => ActionItem::VotingOpenGov(VotingOpenGovAction::default()), _ => todo!(), } } - fn get_options() -> Vec { vec![ ActionItem::AddMembers(AddMembersAction::default()).option(), @@ -228,24 +202,19 @@ impl ActionItem { ] } } - #[derive(Clone, Default, Debug)] pub struct ActionsForm { pub value: Vec, } - #[derive(Clone, Default, Debug)] pub struct SettingsForm {} - #[derive(Clone, Default, Debug)] pub struct ConfirmationForm {} - #[derive(PartialEq, Clone, Debug, Deserialize, Serialize, Default)] pub struct InitiativeInitContent { pub sender: String, pub is_admin: bool, } - #[derive(PartialEq, Clone, Debug, Deserialize, Serialize, Default)] pub struct InitiativeInfoContent { pub name: String, @@ -253,56 +222,46 @@ pub struct InitiativeInfoContent { pub tags: Vec, pub actions: Vec, } - #[derive(PartialEq, Deserialize, Serialize, Debug)] pub struct InitiativeData { pub init: InitiativeInitContent, pub info: InitiativeInfoContent, } - #[derive(PartialEq, Deserialize, Serialize, Clone, Debug)] - pub enum VoteOf { Yes, No, } - #[derive(PartialEq, Deserialize, Serialize, Clone, Debug)] pub enum Vote { Standard(VoteOf), } - #[derive(PartialEq, Clone, Debug, Deserialize, Serialize)] pub struct InitiativeVoteContent { pub user: String, pub vote: Vote, } - #[derive(PartialEq, Clone, Debug, Deserialize, Serialize)] pub struct InitiativeVoteData { pub user: String, pub room: String, pub vote: Vote, } - #[derive(PartialEq, Deserialize, Serialize, Debug, Default)] pub struct InitiativeHistory { pub init: InitiativeInitContent, pub info: InitiativeInfoContent, pub votes: Vec, } - #[derive(PartialEq, Deserialize, Serialize, Debug, Default)] pub struct CommunityInitiative { id: Option, } - pub fn use_initiative() -> UseInitiativeState { let info = consume_context::>(); let actions = consume_context::>(); let settings = consume_context::>(); let confirmation = consume_context::>(); - use_hook(|| UseInitiativeState { inner: UseInitiativeInner { info, @@ -312,12 +271,10 @@ pub fn use_initiative() -> UseInitiativeState { }, }) } - #[derive(Clone, Copy)] pub struct UseInitiativeState { inner: UseInitiativeInner, } - #[derive(Clone, Copy, Default)] pub struct UseInitiativeInner { info: Signal, @@ -325,85 +282,66 @@ pub struct UseInitiativeInner { settings: Signal, confirmation: Signal, } - impl UseInitiativeState { pub fn get(&self) -> UseInitiativeInner { self.inner.clone() } - pub fn get_info(&self) -> InfoForm { self.inner.info.read().clone() } - pub fn set_info(&mut self, info: InfoForm) { let mut inner = self.inner.info.write(); *inner = info; } - pub fn info_mut(&mut self) -> Signal { self.inner.info.clone() } - pub fn get_actions(&self) -> Vec { self.inner.actions.read().value.clone() } - pub fn get_action(&self, position: usize) -> ActionItem { self.inner.actions.read().value[position].clone() } - pub fn get_actions_options(&self) -> Vec { ActionItem::get_options() } - pub fn to_action_option(&self, option: String) -> ActionItem { ActionItem::to_option(option) } - pub fn set_actions(&mut self, actions: ActionsForm) { let mut inner = self.inner.actions.write(); *inner = actions; } - pub fn push_action(&mut self, action: ActionItem) { self.inner.actions.with_mut(|i| i.value.push(action)); } - pub fn remove_action(&mut self, position: usize) { self.inner.actions.with_mut(|i| i.value.remove(position)); } - pub fn update_action(&mut self, position: usize, action: ActionItem) { self.inner.actions.with_mut(|i| i.value[position] = action); } - pub fn get_settings(&self) -> SettingsForm { self.inner.settings.read().clone() } - pub fn set_settings(&mut self, settings: SettingsForm) { let mut inner = self.inner.settings.write(); *inner = settings; } - pub fn settings_mut(&mut self) -> Signal { self.inner.settings } - pub fn get_confirmation(&self) -> ConfirmationForm { self.inner.confirmation.read().clone() } - pub fn set_confirmation(&mut self, confirmation: ConfirmationForm) { let mut inner = self.inner.confirmation.write(); *inner = confirmation; } - pub fn confirmation_mut(&mut self) -> Signal { self.inner.confirmation } - pub fn default(&mut self) { - self.inner = UseInitiativeInner::default() + self.inner = UseInitiativeInner::default(); } } diff --git a/src/hooks/use_language.rs b/src/hooks/use_language.rs index 395b47e..e556876 100644 --- a/src/hooks/use_language.rs +++ b/src/hooks/use_language.rs @@ -1,34 +1,31 @@ use std::str::FromStr; - use dioxus_std::i18n::{use_init_i18n, Language}; use unic_langid::LanguageIdentifier; use web_sys::window; - static EN_US: &str = include_str!("../locales/en-US.json"); static ES_ES: &str = include_str!("../locales/es-ES.json"); - pub fn use_language() { let navigator_language = window() .expect("window") .navigator() .language() .unwrap_or("en-US".to_string()); - let default_language = if navigator_language.starts_with("es") { "es-ES" } else { "en-US" }; - let selected_language: LanguageIdentifier = default_language .parse() .expect("can't parse es-ES language"); - let fallback_language: LanguageIdentifier = selected_language.clone(); - - use_init_i18n(selected_language, fallback_language, || { - let en_us = Language::from_str(EN_US).expect("can't get EN_US language"); - let es_es = Language::from_str(ES_ES).expect("can't get ES_ES language"); - vec![en_us, es_es] - }); + use_init_i18n( + selected_language, + fallback_language, + || { + let en_us = Language::from_str(EN_US).expect("can't get EN_US language"); + let es_es = Language::from_str(ES_ES).expect("can't get ES_ES language"); + vec![en_us, es_es] + }, + ); } diff --git a/src/hooks/use_notification.rs b/src/hooks/use_notification.rs index 398c52d..b0ced0b 100644 --- a/src/hooks/use_notification.rs +++ b/src/hooks/use_notification.rs @@ -1,6 +1,5 @@ use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; - #[derive(Debug, PartialEq, Clone, Default)] pub enum NotificationVariant { Warning, @@ -8,7 +7,6 @@ pub enum NotificationVariant { #[default] Success, } - #[derive(Debug, Clone, Default)] pub struct NotificationItem { pub title: String, @@ -17,48 +15,39 @@ pub struct NotificationItem { pub show: bool, pub handle: NotificationHandle, } - #[derive(Debug, Clone, Default)] pub struct NotificationHandle { pub value: NotificationHandler, } - #[derive(Debug, Clone, Default)] pub enum NotificationHandler { Click, #[default] None, } - pub fn use_notification() -> UseNotificationState { let notification = consume_context::>(); - use_hook(move || UseNotificationState { inner: notification, }) } - #[derive(Clone, Copy)] pub struct UseNotificationState { inner: Signal, } - use gloo::timers::future::TimeoutFuture; impl UseNotificationState { pub fn get(&self) -> NotificationItem { self.inner.read().clone() } - pub fn handle_notification(&mut self, item: NotificationItem) { let mut inner = self.inner.clone(); *inner.write() = item; - use_future(move || async move { TimeoutFuture::new(3000).await; *inner.write() = NotificationItem::default(); }); } - pub fn handle_success(&mut self, body: &str) { self.handle_notification(NotificationItem { title: translate!(use_i18(), "success.title"), @@ -70,7 +59,6 @@ impl UseNotificationState { }, }); } - pub fn handle_error(&mut self, body: &str) { self.handle_notification(NotificationItem { title: String::from("Error"), @@ -82,7 +70,6 @@ impl UseNotificationState { }, }); } - pub fn handle_warning(&mut self, body: &str) { self.handle_notification(NotificationItem { title: translate!(use_i18(), "warnings.title"), @@ -94,7 +81,6 @@ impl UseNotificationState { }, }); } - pub fn clear(&mut self) { let mut inner = self.inner.write(); *inner = NotificationItem::default(); diff --git a/src/hooks/use_onboard.rs b/src/hooks/use_onboard.rs index f3a063e..ae21f7e 100644 --- a/src/hooks/use_onboard.rs +++ b/src/hooks/use_onboard.rs @@ -1,5 +1,4 @@ use dioxus::prelude::*; - #[derive(Clone, Default, Debug)] pub struct BasicsForm { pub logo: Option, @@ -7,43 +6,35 @@ pub struct BasicsForm { pub description: String, pub industry: String, } - #[derive(Clone, Default, Debug)] pub enum ManagementOptions { #[default] Membership, Ranked, } - #[derive(Clone, Default, Debug)] pub struct ManagementForm { pub value: ManagementOptions, } - #[derive(Clone, Default, Debug)] pub enum MediumOptions { #[default] Wallet, } - #[derive(Clone, Default, Debug)] pub struct InvitationItem { pub medium: MediumOptions, pub account: String, } - pub type Invitations = Vec; - #[derive(Clone, Default, Debug)] pub struct InvitationForm { pub invitations: Invitations, } - pub fn use_onboard() -> UseOnboardState { let basics = consume_context::>(); let management = consume_context::>(); let invitations = consume_context::>(); - use_hook(|| UseOnboardState { inner: UseOnboardInner { basics, @@ -52,78 +43,57 @@ pub fn use_onboard() -> UseOnboardState { }, }) } - #[derive(Clone, Copy)] pub struct UseOnboardState { inner: UseOnboardInner, } - #[derive(Clone, Copy, Default)] pub struct UseOnboardInner { basics: Signal, management: Signal, invitations: Signal, } - impl UseOnboardState { pub fn get(&self) -> UseOnboardInner { self.inner.clone() } - pub fn get_basics(&self) -> BasicsForm { self.inner.basics.read().clone() } - pub fn set_basics(&mut self, basics: BasicsForm) { let mut inner = self.inner.basics.write(); *inner = basics; } - pub fn basics_mut(&mut self) -> Signal { self.inner.basics.clone() } - pub fn get_management(&self) -> ManagementForm { self.inner.management.read().clone() } - pub fn management_mut(&mut self) -> Signal { self.inner.management } - pub fn get_invitations(&self) -> Invitations { self.inner.invitations.read().invitations.clone() } - pub fn set_management(&mut self, management: ManagementForm) { let mut inner = self.inner.management.write(); *inner = management; } - pub fn set_invitations(&mut self, invitations: InvitationForm) { let mut inner = self.inner.invitations.write(); *inner = invitations; } - pub fn push_invitation(&mut self, invitation: InvitationItem) { - self.inner - .invitations - .with_mut(|i| i.invitations.push(invitation)); + self.inner.invitations.with_mut(|i| i.invitations.push(invitation)); } - pub fn remove_invitation(&mut self, position: usize) { - self.inner - .invitations - .with_mut(|i| i.invitations.remove(position)); + self.inner.invitations.with_mut(|i| i.invitations.remove(position)); } - pub fn update_invitation(&mut self, position: usize, invitation: InvitationItem) { - self.inner - .invitations - .with_mut(|i| i.invitations[position] = invitation); + self.inner.invitations.with_mut(|i| i.invitations[position] = invitation); } - pub fn default(&mut self) { - self.inner = UseOnboardInner::default() + self.inner = UseOnboardInner::default(); } } diff --git a/src/hooks/use_our_navigator.rs b/src/hooks/use_our_navigator.rs index b8a972e..445c81b 100644 --- a/src/hooks/use_our_navigator.rs +++ b/src/hooks/use_our_navigator.rs @@ -1,36 +1,31 @@ use dioxus::prelude::*; - #[derive(Clone, Default)] pub struct FromMiddleware(pub bool); - pub fn use_our_navigator() -> UseOurNavigatorState { let nav = use_navigator(); - use_hook(|| UseOurNavigatorState { nav }) } - #[derive(Clone, Copy)] pub struct UseOurNavigatorState { nav: Navigator, } - impl UseOurNavigatorState { - pub fn push(&self, middlewares: Vec Result<(), &'static str>>>, to: &str) { + pub fn push( + &self, + middlewares: Vec Result<(), &'static str>>>, + to: &str, + ) { for middleware in middlewares { if let Err(e) = middleware() { - // Handle the error, log it, or show a notification println!("Middleware failed: {}", e); return; } } - self.nav.push(to); } - pub fn can_go_back(&self) -> bool { self.nav.can_go_back() } - pub fn go_back(&self) { self.nav.go_back() } diff --git a/src/hooks/use_paginator.rs b/src/hooks/use_paginator.rs index ccc3ac6..940ad1e 100644 --- a/src/hooks/use_paginator.rs +++ b/src/hooks/use_paginator.rs @@ -1,48 +1,40 @@ use dioxus::prelude::*; - #[derive(Clone, Default)] pub struct Paginator { pub from: u8, pub total: u8, pub current: u8, } - pub fn use_paginator() -> UsePaginatorState { let paginator = consume_context::>(); - - use_hook(|| UsePaginatorState { inner: paginator }) + use_hook(|| UsePaginatorState { + inner: paginator, + }) } - #[derive(Clone, Copy)] pub struct UsePaginatorState { inner: Signal, } - impl UsePaginatorState { pub fn get(&self) -> Paginator { self.inner.read().clone() } - pub fn set(&mut self, paginator: Paginator) { let mut inner = self.inner.write(); *inner = paginator; } - pub fn set_from(&mut self, from: u8) { let mut inner = self.inner.write(); inner.from = from; } - pub fn set_total(&mut self, total: u8) { let mut inner = self.inner.write(); inner.total = total; } - pub fn set_current(&mut self, current: u8) { let mut inner = self.inner.write(); inner.current = current; } - pub fn default(&mut self) { self.set(Paginator::default()) } diff --git a/src/hooks/use_session.rs b/src/hooks/use_session.rs index 8a8bc89..ea2b5aa 100644 --- a/src/hooks/use_session.rs +++ b/src/hooks/use_session.rs @@ -1,76 +1,62 @@ use dioxus::prelude::*; use gloo::storage::{errors::StorageError, LocalStorage}; use serde::{Deserialize, Serialize}; - pub fn use_session() -> UseSessionState { let user = consume_context::>>(); - use_hook(move || UseSessionState { data: user }) } - #[derive(Clone, Copy)] pub struct UseSessionState { data: Signal>, } - #[derive(Clone, Debug, Serialize, Deserialize)] pub struct UserSession { pub name: String, pub address: String, pub account_id: u8, } - #[derive(Debug)] pub enum SessionError { SaveFailed, GetFailed, } - impl UseSessionState { pub fn set(&mut self, data: &UserSession) { *self.data.write() = Some(data.clone()); } - pub fn get(&self) -> Option { self.data.read().clone() } - pub fn persist_session_file(&self, session_file: &str) -> Result<(), SessionError> { ::set("session_file", session_file) .map_err(|_| SessionError::SaveFailed) } - pub fn update_account(&mut self, account_id: u8) -> Result<(), SessionError> { - let serialized_session: Result = - ::get("session_file"); - - let serialized_session = serialized_session.map_err(|_| SessionError::GetFailed)?; - let mut full_session: UserSession = - serde_json::from_str(&serialized_session).map_err(|_| SessionError::GetFailed)?; - + let serialized_session: Result = ::get( + "session_file", + ); + let serialized_session = serialized_session + .map_err(|_| SessionError::GetFailed)?; + let mut full_session: UserSession = serde_json::from_str(&serialized_session) + .map_err(|_| SessionError::GetFailed)?; full_session.account_id = account_id; self.set(&full_session); - - let serialized_session = - serde_json::to_string(&full_session).map_err(|_| SessionError::GetFailed)?; + let serialized_session = serde_json::to_string(&full_session) + .map_err(|_| SessionError::GetFailed)?; ::set("session_file", serialized_session) .map_err(|_| SessionError::SaveFailed)?; - Ok(()) } - pub fn is_logged(&self) -> bool { - let serialized_session: Result = - ::get("session_file"); - + let serialized_session: Result = ::get( + "session_file", + ); let Ok(serialized_session) = serialized_session else { return false; }; - let Ok(_) = serde_json::from_str::(&serialized_session) else { return false; }; - true } } diff --git a/src/hooks/use_spaces_client.rs b/src/hooks/use_spaces_client.rs index 04c6815..2a5f794 100644 --- a/src/hooks/use_spaces_client.rs +++ b/src/hooks/use_spaces_client.rs @@ -1,18 +1,13 @@ use dioxus::prelude::*; - use crate::services::bot::client::SpacesClient; - pub fn use_spaces_client() -> UseSpacesClient { let client = consume_context::>(); - use_hook(move || UseSpacesClient { client }) } - #[derive(Clone, Copy)] pub struct UseSpacesClient { pub client: Signal, } - impl UseSpacesClient { pub fn get(&self) -> SpacesClient { self.client.read().clone() diff --git a/src/hooks/use_startup.rs b/src/hooks/use_startup.rs index e92da60..59365a2 100644 --- a/src/hooks/use_startup.rs +++ b/src/hooks/use_startup.rs @@ -1,60 +1,56 @@ use dioxus::{hooks::use_context_provider, signals::Signal}; use pjs::PjsExtension; - use crate::{pages::initiatives::InitiativeWrapper, services::bot::client::SpacesClient}; - use super::{ use_accounts::{Account, IsDaoOwner}, - use_attach::AttachFile, - use_communities::{Communities, Community}, + use_attach::AttachFile, use_communities::{Communities, Community}, use_initiative::{ActionsForm, ConfirmationForm, InfoForm, SettingsForm}, use_notification::NotificationItem, use_onboard::{BasicsForm, InvitationForm, ManagementForm}, - use_paginator::Paginator, - use_session::UserSession, - use_theme::Theme, + use_paginator::Paginator, use_session::UserSession, use_theme::Theme, use_timestamp::{IsTimestampHandled, TimestampValue}, use_tooltip::TooltipItem, }; - const SPACES_CLIENT_URL: &str = "https://bot-api.virto.app"; - pub fn use_startup() { use_context_provider::>(|| Signal::new(Theme::default())); - use_context_provider::>(|| Signal::new(BasicsForm::default())); - use_context_provider::>(|| Signal::new(ManagementForm::default())); - use_context_provider::>(|| Signal::new(InvitationForm::default())); - + use_context_provider::< + Signal, + >(|| Signal::new(ManagementForm::default())); + use_context_provider::< + Signal, + >(|| Signal::new(InvitationForm::default())); use_context_provider::>(|| Signal::new(vec![])); use_context_provider::>(|| Signal::new(Community::default())); use_context_provider::>>(|| Signal::new(None)); - use_context_provider::>(|| Signal::new(NotificationItem::default())); + use_context_provider::< + Signal, + >(|| Signal::new(NotificationItem::default())); use_context_provider::>(|| Signal::new(TooltipItem::default())); use_context_provider::>(|| Signal::new(Paginator::default())); - use_context_provider::>>(|| Signal::new(None)); use_context_provider::>>(|| Signal::new(vec![])); use_context_provider::>>(|| Signal::new(None)); use_context_provider::>(|| Signal::new(IsDaoOwner(false))); use_context_provider::>>(|| Signal::new(None)); - use_context_provider::>(|| Signal::new(false)); use_context_provider::>(|| Signal::new(String::new())); use_context_provider::>(|| Signal::new(0.0)); - use_context_provider::>>(|| Signal::new(None)); use_context_provider::>(|| Signal::new(InfoForm::default())); use_context_provider::>(|| Signal::new(ActionsForm::default())); - use_context_provider::>(|| Signal::new(SettingsForm::default())); - use_context_provider::>(|| Signal::new(ConfirmationForm::default())); - + use_context_provider::< + Signal, + >(|| Signal::new(SettingsForm::default())); + use_context_provider::< + Signal, + >(|| Signal::new(ConfirmationForm::default())); use_context_provider::>(|| Signal::new(TimestampValue(0))); - use_context_provider::>(|| Signal::new(IsTimestampHandled(false))); - - // Clients - - use_context_provider::>(|| { - Signal::new(SpacesClient::new(SPACES_CLIENT_URL)) - }); + use_context_provider::< + Signal, + >(|| Signal::new(IsTimestampHandled(false))); + use_context_provider::< + Signal, + >(|| { Signal::new(SpacesClient::new(SPACES_CLIENT_URL)) }); } diff --git a/src/hooks/use_theme.rs b/src/hooks/use_theme.rs index b28ac80..119fe8d 100644 --- a/src/hooks/use_theme.rs +++ b/src/hooks/use_theme.rs @@ -1,5 +1,4 @@ use dioxus::prelude::*; - #[derive(Clone)] pub struct Theme { pub background: String, @@ -8,7 +7,6 @@ pub struct Theme { pub text_3: String, pub text_4: String, } - impl Default for Theme { fn default() -> Self { Self { @@ -20,56 +18,44 @@ impl Default for Theme { } } } - pub fn use_theme() -> UsethemeState { let theme = consume_context::>(); - use_hook(|| UsethemeState { inner: theme }) } - #[derive(Clone, Copy)] pub struct UsethemeState { inner: Signal, } - impl UsethemeState { pub fn get(&self) -> Theme { self.inner.read().clone() } - pub fn set(&mut self, theme: Theme) { let mut inner = self.inner.write(); *inner = theme; } - pub fn set_background(&mut self, background: String) { let mut inner = self.inner.write(); inner.background = background; } - pub fn set_text_1(&mut self, text_1: String) { let mut inner = self.inner.write(); inner.text_1 = text_1; } - pub fn set_text_2(&mut self, text_2: String) { let mut inner = self.inner.write(); inner.text_2 = text_2; } - pub fn set_text_3(&mut self, text_3: String) { let mut inner = self.inner.write(); inner.text_3 = text_3; } - pub fn set_text_4(&mut self, text_4: String) { let mut inner = self.inner.write(); inner.text_4 = text_4; } - pub fn get_style(self) -> String { let inner = self.inner.read(); - format!( r#" --background: {}; @@ -78,10 +64,13 @@ impl UsethemeState { --text-3: {}; --text-4: {}; "#, - inner.background, inner.text_1, inner.text_2, inner.text_3, inner.text_4 + inner.background, + inner.text_1, + inner.text_2, + inner.text_3, + inner.text_4, ) } - pub fn default(&mut self) { self.set(Theme::default()) } diff --git a/src/hooks/use_timestamp.rs b/src/hooks/use_timestamp.rs index 317e4dd..69fd4a0 100644 --- a/src/hooks/use_timestamp.rs +++ b/src/hooks/use_timestamp.rs @@ -1,28 +1,20 @@ use dioxus::prelude::*; - #[derive(Debug, Clone, Copy, PartialEq)] pub struct IsTimestampHandled(pub bool); - - #[derive(Debug, Clone, Copy, PartialEq)] pub struct TimestampValue(pub u64); - pub fn use_timestamp() -> UseTimestampState { let timestamp = consume_context::>(); - use_hook(|| UseTimestampState { timestamp }) } - #[derive(Clone, Copy)] pub struct UseTimestampState { timestamp: Signal, } - impl UseTimestampState { pub fn get(&self) -> TimestampValue { self.timestamp.read().clone() } - pub fn set(&mut self, timestamp: TimestampValue) { let mut inner = self.timestamp.write(); *inner = timestamp; diff --git a/src/hooks/use_tooltip.rs b/src/hooks/use_tooltip.rs index 19fded9..99ce14b 100644 --- a/src/hooks/use_tooltip.rs +++ b/src/hooks/use_tooltip.rs @@ -1,35 +1,26 @@ use dioxus::prelude::*; - #[derive(Debug, Clone, Default)] pub struct TooltipItem { pub title: String, pub body: String, pub show: bool, } - pub fn use_tooltip() -> UseTooltipState { let tooltip = consume_context::>(); - - use_hook(move || UseTooltipState { - inner: tooltip, - }) + use_hook(move || UseTooltipState { inner: tooltip }) } - #[derive(Clone, Copy)] pub struct UseTooltipState { inner: Signal, } - impl UseTooltipState { pub fn get(&self) -> TooltipItem { self.inner.read().clone() } - pub fn handle_tooltip(&mut self, item: TooltipItem) { let mut inner = self.inner.clone(); *inner.write() = item; } - pub fn hide(&mut self) { let mut inner = self.inner.write(); *inner = TooltipItem::default(); diff --git a/src/hooks/use_vote.rs b/src/hooks/use_vote.rs index dafbd3e..9a4716d 100644 --- a/src/hooks/use_vote.rs +++ b/src/hooks/use_vote.rs @@ -1,5 +1,4 @@ use dioxus::prelude::*; - #[derive(Clone, Debug)] pub enum ProposalStatus { APPROVED, @@ -7,25 +6,21 @@ pub enum ProposalStatus { VOTING, QUEUE, } - #[derive(Clone, Debug)] pub enum BadgeColor { YELLOW, RED, GREEN, } - #[derive(Clone, Debug, Default)] pub struct VoteDigest { pub aye: u64, pub nay: u64, } - impl VoteDigest { pub fn total(&self) -> u64 { self.aye + self.nay } - pub fn percent_aye(&self) -> f64 { if self.total() > 0 { let percent_unit = 100.0 / self.total() as f64; @@ -34,7 +29,6 @@ impl VoteDigest { 50.0 } } - pub fn percent_nay(&self) -> f64 { if self.total() > 0 { let percent_unit = 100.0 / self.total() as f64; @@ -44,12 +38,9 @@ impl VoteDigest { } } } - pub fn use_vote() -> UseVoteState { use_hook(move || UseVoteState {}) } - #[derive(Clone, Copy)] pub struct UseVoteState {} - impl UseVoteState {} diff --git a/src/layouts/authenticated.rs b/src/layouts/authenticated.rs index e46c6b5..5ea8185 100644 --- a/src/layouts/authenticated.rs +++ b/src/layouts/authenticated.rs @@ -1,18 +1,14 @@ use dioxus::prelude::*; - -use crate::{components::molecules::{Header, Sidebar}, pages::route::Route}; - +use crate::{ + components::molecules::{Header, Sidebar}, + pages::route::Route, +}; #[component] pub fn Authenticated() -> Element { rsx! { div { class: "page", - div { - class: "layout layout--onboard grid-sidebar", - Sidebar {} - } - div { class: "layout layout--authenticated grid-header", - Header {}, - }, + div { class: "layout layout--onboard grid-sidebar", Sidebar {} } + div { class: "layout layout--authenticated grid-header", Header {} } Outlet:: {} } } diff --git a/src/layouts/onboard.rs b/src/layouts/onboard.rs index 6003cc5..937783a 100644 --- a/src/layouts/onboard.rs +++ b/src/layouts/onboard.rs @@ -1,7 +1,5 @@ use dioxus::prelude::*; - use crate::{components::molecules::Sidebar, pages::route::Route}; - #[component] pub fn Onboard() -> Element { rsx! { diff --git a/src/lib.rs b/src/lib.rs index b032631..34260ef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,17 +9,14 @@ pub mod pages { pub mod route; pub mod vote; } - pub mod middlewares { pub mod is_chain_available; pub mod is_dao_owner; } - pub mod layouts { pub mod authenticated; pub mod onboard; } - pub mod hooks { pub mod use_accounts; pub mod use_attach; @@ -39,12 +36,10 @@ pub mod hooks { pub mod use_tooltip; pub mod use_vote; } - pub mod components { pub mod atoms; pub mod molecules; } - pub mod services { pub mod bot { pub mod client; @@ -61,7 +56,6 @@ pub mod services { pub mod system; pub mod timestamp; } - pub mod kusama { pub mod system; } diff --git a/src/main.rs b/src/main.rs index e5e5f6e..281889d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,7 @@ #![allow(non_snake_case)] - use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; use gloo::storage::{errors::StorageError, LocalStorage}; - use virto_communities::{ components::atoms::{Notification, Tooltip}, hooks::{ @@ -14,17 +12,13 @@ use virto_communities::{ use_timestamp::{use_timestamp, IsTimestampHandled, TimestampValue}, use_tooltip::use_tooltip, }, - pages::route::Route, - services::kreivo::timestamp::now, + pages::route::Route, services::kreivo::timestamp::now, }; - fn main() { wasm_logger::init(wasm_logger::Config::default()); console_error_panic_hook::set_once(); - launch(App); } - fn App() -> Element { use_language(); use_startup(); @@ -34,33 +28,28 @@ fn App() -> Element { let mut session = use_session(); let mut timestamp = use_timestamp(); let mut is_timestamp_handled = consume_context::>(); - use_coroutine(move |_: UnboundedReceiver<()>| async move { let Ok(result_now) = now().await else { notification.handle_error(&translate!(i18, "errors.timestamp.query_failed")); is_timestamp_handled.set(IsTimestampHandled(true)); return; }; - timestamp.set(TimestampValue(result_now)); is_timestamp_handled.set(IsTimestampHandled(true)); }); - use_coroutine(move |_: UnboundedReceiver<()>| async move { - let serialized_session: Result = - ::get("session_file"); - + let serialized_session: Result = ::get( + "session_file", + ); let Ok(serialized_session) = serialized_session else { return; }; - - let Ok(user_session) = serde_json::from_str::(&serialized_session) else { + let Ok(user_session) = serde_json::from_str::(&serialized_session) + else { return; }; - session.set(&user_session); }); - rsx! { if notification.get().show { Notification { @@ -75,14 +64,9 @@ fn App() -> Element { } } } - if tooltip.get().show { - Tooltip { - title: "{tooltip.get().title}", - body: "{tooltip.get().body}", - } + Tooltip { title: "{tooltip.get().title}", body: "{tooltip.get().body}" } } - Router:: {} } } diff --git a/src/middlewares/is_chain_available.rs b/src/middlewares/is_chain_available.rs index 97cd386..a99f15c 100644 --- a/src/middlewares/is_chain_available.rs +++ b/src/middlewares/is_chain_available.rs @@ -1,22 +1,21 @@ use dioxus::router::hooks::use_navigator; use dioxus_std::{i18n::use_i18, translate}; use web_sys::js_sys::Date; - use crate::{ components::atoms::notification, hooks::{use_notification::use_notification, use_timestamp::use_timestamp}, }; - const THRESHOLD: u64 = 1000 * 60; - pub fn is_chain_available() -> impl FnOnce() -> Result<(), &'static str> { move || { let i18 = use_i18(); let timestamp = use_timestamp(); let mut notification = use_notification(); - if Date::now() as u64 - timestamp.get().0 > THRESHOLD { - notification.handle_warning(&translate!(i18, "warnings.middleware.chain_unavailable")); + notification + .handle_warning( + &translate!(i18, "warnings.middleware.chain_unavailable"), + ); Err("Chain unavailable") } else { Ok(()) diff --git a/src/middlewares/is_dao_owner.rs b/src/middlewares/is_dao_owner.rs index 0ea3c6d..738ce88 100644 --- a/src/middlewares/is_dao_owner.rs +++ b/src/middlewares/is_dao_owner.rs @@ -1,13 +1,10 @@ use dioxus_std::{i18n::use_i18, translate}; - use crate::hooks::{use_accounts::use_accounts, use_notification::use_notification}; - pub fn is_dao_owner() -> impl FnOnce() -> Result<(), &'static str> { move || { let i18 = use_i18(); let accounts = use_accounts(); let mut notification = use_notification(); - if accounts.is_active_account_an_admin() { notification.handle_warning(&translate!(i18, "warnings.middleware.has_dao")); Err("User is DAO owner") diff --git a/src/pages/dashboard.rs b/src/pages/dashboard.rs index 14a36b1..c695046 100644 --- a/src/pages/dashboard.rs +++ b/src/pages/dashboard.rs @@ -1,23 +1,20 @@ use std::str::FromStr; - use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; use futures_util::StreamExt; - use crate::{ components::{ atoms::{ - avatar::Variant as AvatarVariant, dropdown::ElementSize, icon_button::Variant, - input::InputType, AddPlus, ArrowLeft, ArrowRight, Avatar, Badge, Chat, Compass, Icon, - IconButton, SearchInput, Suitcase, Tab, UserAdd, UserGroup, + avatar::Variant as AvatarVariant, dropdown::ElementSize, + icon_button::Variant, input::InputType, AddPlus, ArrowLeft, ArrowRight, + Avatar, Badge, Chat, Compass, Icon, IconButton, SearchInput, Suitcase, Tab, + UserAdd, UserGroup, }, molecules::tabs::TabItem, }, hooks::{ - use_accounts::use_accounts, - use_notification::use_notification, - use_our_navigator::use_our_navigator, - use_session::use_session, + use_accounts::use_accounts, use_notification::use_notification, + use_our_navigator::use_our_navigator, use_session::use_session, use_tooltip::{use_tooltip, TooltipItem}, }, middlewares::{is_chain_available::is_chain_available, is_dao_owner::is_dao_owner}, @@ -27,13 +24,11 @@ use crate::{ community_track::{tracks, tracksIds}, }, }; - #[derive(PartialEq, Clone)] pub enum CommunityTag { Neighborhood, SocialImpact, } - #[derive(PartialEq, Clone, Debug)] pub struct Community { pub id: u16, @@ -44,9 +39,7 @@ pub struct Community { pub tags: Vec, pub members: u16, } - static SKIP: u8 = 6; - #[component] pub fn Dashboard() -> Element { let i18 = use_i18(); @@ -54,67 +47,57 @@ pub fn Dashboard() -> Element { let mut tooltip = use_tooltip(); let nav = use_our_navigator(); let session = use_session(); - let mut current_page = use_signal::(|| 1); let mut search_word = use_signal::(|| String::new()); - - let tab_items = vec![TabItem { - k: String::from("all"), - value: translate!(i18, "dashboard.tabs.all"), - }]; - + let tab_items = vec![ + TabItem { + k: String::from("all"), + value: translate!(i18, "dashboard.tabs.all"), + }, + ]; let tab_value = use_signal::(|| String::from("all")); - let mut communities_by_address = use_signal::>(|| vec![]); let mut filtered_communities = use_signal::>(|| vec![]); - use_coroutine(move |_: UnboundedReceiver<()>| async move { - tooltip.handle_tooltip(TooltipItem { - title: translate!(i18, "dao.tips.loading.title"), - body: translate!(i18, "dao.tips.loading.description"), - show: true, - }); - + tooltip + .handle_tooltip(TooltipItem { + title: translate!(i18, "dao.tips.loading.title"), + body: translate!(i18, "dao.tips.loading.description"), + show: true, + }); let Some(session) = session.get() else { log::info!("error here by account"); - notification.handle_error(&translate!(i18, "errors.communities.query_failed")); + notification + .handle_error(&translate!(i18, "errors.communities.query_failed")); tooltip.hide(); return; }; - let Ok(address) = sp_core::sr25519::Public::from_str(&session.address) else { log::info!("error here by address"); notification.handle_error(&translate!(i18, "errors.wallet.account_address")); tooltip.hide(); return; }; - let Ok(community_tracks) = get_communities_by_member(&address.0).await else { log::info!("error here by memeber"); - notification.handle_error(&translate!(i18, "errors.communities.query_failed")); + notification + .handle_error(&translate!(i18, "errors.communities.query_failed")); tooltip.hide(); return; }; - communities_by_address.set(community_tracks.clone()); filtered_communities.set(community_tracks.clone()); - tooltip.hide(); }); - rsx! { - div { - class: "dashboard grid-main", + div { class: "dashboard grid-main", div { class: "dashboard__head", section { class: "tabs", - // body: items for item in tab_items.into_iter() { Tab { text: item.value, - is_active: if tab_value() == item.k {true} else {false}, - on_click: move |_| { - // tab_value.set(item.k); - }, + is_active: if tab_value() == item.k { true } else { false }, + on_click: move |_| {} } } } @@ -125,32 +108,37 @@ pub fn Dashboard() -> Element { error: None, on_input: move |event: Event| { search_word.set(event.value()); - if search_word().trim().is_empty() { filtered_communities.set(communities_by_address()); } else { let pattern = search_word().trim().to_lowercase(); - filtered_communities.set(communities_by_address().into_iter().filter(|community| community.name.to_lowercase().contains(&pattern)).collect::>()); + filtered_communities + .set( + communities_by_address() + .into_iter() + .filter(|community| { + community.name.to_lowercase().contains(&pattern) + }) + .collect::>(), + ); } }, on_keypress: move |_| {}, - on_click: move |_| {}, + on_click: move |_| {} } 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)" - } + Icon { icon : AddPlus, height : 26, width : 26, stroke_width : 1.5, fill : + "var(--fill-00)" } ), on_click: move |_| { tooltip.hide(); - nav.push(vec![Box::new(is_chain_available()), Box::new(is_dao_owner())], "/onboarding"); + nav.push( + vec![Box::new(is_chain_available()), Box::new(is_dao_owner())], + "/onboarding", + ); } } } @@ -162,24 +150,15 @@ pub fn Dashboard() -> Element { div { class: "card__head", IconButton { body: rsx!( - Avatar { - name: "{community.name}", - size: 48, - uri: community.icon, - variant: AvatarVariant::SemiRound - } + Avatar { name : "{community.name}", size : 48, uri : community.icon, variant : + AvatarVariant::SemiRound } ), - on_click: move |_| { } - } - h3 { class: "card__title", - "{community.name}" + on_click: move |_| {} } + h3 { class: "card__title", "{community.name}" } } - p { class: "card__description", - "{community.description}" - } + p { class: "card__description", "{community.description}" } div { class: "card__metrics", - span { class: "card__metric", Icon { icon: UserAdd, @@ -188,9 +167,7 @@ pub fn Dashboard() -> Element { stroke_width: 2, stroke: "var(--text-primary)" } - small { - "{community.memberships} Free Memberships" - } + small { "{community.memberships} Free Memberships" } } span { class: "card__metric", Icon { @@ -200,36 +177,22 @@ pub fn Dashboard() -> Element { stroke_width: 1, fill: "var(--text-primary)" } - small { - "{community.members} Members" - } + small { "{community.members} Members" } } } div { class: "card__tags", for tag in community.tags { - { - rsx!( - Badge { - class: "badge--lavanda-dark", - text: tag - } - ) - } + { 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)" - } + Icon { icon : ArrowRight, height : 32, width : 32, stroke_width : 2, fill : + "var(--fill-00)" } ), on_click: move |_| { let path = format!("/dao/{}/initiatives", community.id); @@ -243,25 +206,19 @@ pub fn Dashboard() -> Element { div { class: "card__container", div { class: "card__head", h3 { class: "card__title", - {translate!(i18, "dashboard.cta_cards.explore.title")} + { translate!(i18, + "dashboard.cta_cards.explore.title") } } } p { class: "card__description", - {translate!(i18, "dashboard.cta_cards.explore.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)" - } - ), + body: rsx!(Icon { icon : Compass, height : 32, width : 32, fill : "var(--fill-00)" }), on_click: move |_| { nav.push(vec![], "/explore"); } @@ -272,15 +229,16 @@ pub fn Dashboard() -> Element { div { class: "card__container", div { class: "card__head", h3 { class: "card__title", - {translate!(i18, "dashboard.cta_cards.create.title")} + { translate!(i18, "dashboard.cta_cards.create.title") } } } p { class: "card__description", - {translate!(i18, "dashboard.cta_cards.create.description")} + { translate!(i18, + "dashboard.cta_cards.create.description") } } div { class: "card__head", a { class: "card__learn", - {translate!(i18, "dashboard.cta_cards.create.cta")} + { translate!(i18, "dashboard.cta_cards.create.cta") } } Icon { icon: ArrowRight, @@ -291,24 +249,21 @@ pub fn Dashboard() -> Element { } } } - 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)" - } + 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()), Box::new(is_dao_owner())], "/onboarding"); - } + nav.push( + vec![Box::new(is_chain_available()), Box::new(is_dao_owner())], + "/onboarding", + ); + } } } } @@ -316,43 +271,27 @@ pub fn Dashboard() -> Element { div { class: "dashboard__footer grid-footer", div { class: "dashboard__footer__pagination", span { class: "dashboard__footer__paginator", - {translate!(i18, "dashboard.footer.paginator", from: current_page(), to: (((communities_by_address.len() as f64 + 1f64) / SKIP as f64) as f64).ceil())} + { translate!(i18, + "dashboard.footer.paginator", from : current_page(), to : + (((communities_by_address.len() as f64 + 1f64) / SKIP as f64) as f64).ceil()) } } div { class: "dashboard__footer__paginators", IconButton { class: "button--avatar", 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); - - // get_community_track.send(current_page()) } } IconButton { class: "button--avatar", size: ElementSize::Small, - 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); - - // get_community_track.send(current_page()) } } } @@ -361,24 +300,13 @@ pub fn Dashboard() -> Element { } } } - fn nice_money(value: u64) -> String { let units = vec!["", "K", "M", "B"]; let mut l = 0; let mut n = value as f64; - while n >= 1000.0 && l < units.len() - 1 { n /= 1000.0; l += 1; } - - format!( - "${:.2}{}", - n, - if n < 10.0 && l > 0 { - units[l] - } else { - units[l] - } - ) + format!("${:.2}{}", n, if n < 10.0 && l > 0 { units[l] } else { units[l] }) } diff --git a/src/pages/explore.rs b/src/pages/explore.rs index 62b470b..fa35a4c 100644 --- a/src/pages/explore.rs +++ b/src/pages/explore.rs @@ -1,54 +1,48 @@ use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; use futures_util::StreamExt; - use crate::{ components::{ atoms::{ - avatar::Variant as AvatarVariant, dropdown::ElementSize, icon_button::Variant, input::InputType, AddPlus, ArrowLeft, ArrowRight, Avatar, Badge, Chat, Icon, IconButton, SearchInput, Suitcase, Tab, UserAdd, UserGroup + avatar::Variant as AvatarVariant, dropdown::ElementSize, + icon_button::Variant, input::InputType, AddPlus, ArrowLeft, ArrowRight, + Avatar, Badge, Chat, Icon, IconButton, SearchInput, Suitcase, Tab, UserAdd, + UserGroup, }, molecules::tabs::TabItem, }, hooks::{ - use_notification::use_notification, - use_our_navigator::use_our_navigator, + use_notification::use_notification, use_our_navigator::use_our_navigator, use_tooltip::{use_tooltip, TooltipItem}, }, - middlewares::is_dao_owner::is_dao_owner, - pages::dashboard::Community, + middlewares::is_dao_owner::is_dao_owner, pages::dashboard::Community, services::kreivo::{ community_memberships::{collection, get_owned_memberships, item}, community_track::{tracks, tracksIds}, }, }; - static SKIP: u8 = 7; - #[component] pub fn Explore() -> Element { let i18 = use_i18(); let mut notification = use_notification(); let mut tooltip = use_tooltip(); let nav = use_our_navigator(); - let mut current_page = use_signal::(|| 1); let mut search_word = use_signal::(|| String::new()); - - let tab_items = vec![TabItem { - k: String::from("all"), - value: translate!(i18, "dashboard.tabs.all"), - }]; - + let tab_items = vec![ + TabItem { + k: String::from("all"), + value: translate!(i18, "dashboard.tabs.all"), + }, + ]; let tab_value = use_signal::(|| String::from("all")); - let mut communities_ids = use_signal::>(|| vec![]); let mut communities = use_signal::>(|| vec![]); let mut filtered_communities = use_signal::>(|| vec![]); - let get_community_track = use_coroutine(move |mut rx: UnboundedReceiver| async move { while let Some(f) = rx.next().await { communities.clear(); - let from = if f - 1 > 0 { (f - 1) * SKIP } else { 0 }; let to = if usize::from(f * SKIP) >= communities_ids.len() { communities_ids.len() as u8 @@ -56,38 +50,34 @@ pub fn Explore() -> Element { f * SKIP }; let range = &communities_ids()[from as usize..to as usize]; - for track in range { let response_track = tracks(*track).await; let response_collection = collection(*track).await; let response_item = item(*track, None).await; - let collection_items = match response_collection { Ok(ref collection) => { - let address = format!("0x{}", hex::encode(collection.owner.clone())); + let address = format!( + "0x{}", + hex::encode(collection.owner.clone()), + ); get_owned_memberships(&address).await.unwrap_or(0u16) } Err(_) => 0u16, }; - let Ok(track_info) = response_track else { continue; }; - let filtered_name = track_info .name .iter() .filter(|b| **b != 0) .cloned() .collect::>(); - let filtered_name: &[u8] = &filtered_name; - let item_details = match response_item { Ok(items) => items, Err(_) => 0u16, }; - let community = Community { id: *track, icon: None, @@ -97,44 +87,37 @@ pub fn Explore() -> Element { memberships: collection_items, members: item_details, }; - communities.with_mut(|c| c.push(community)) } tooltip.hide(); filtered_communities.set(communities()) } }); - use_coroutine(move |_: UnboundedReceiver<()>| async move { - tooltip.handle_tooltip(TooltipItem { + tooltip + .handle_tooltip(TooltipItem { title: translate!(i18, "dashboard.tips.loading.title"), body: translate!(i18, "dashboard.tips.loading.description"), show: true, }); - - let Ok(community_tracks) = tracksIds().await else { - notification.handle_error(&translate!(i18, "errors.communities.query_failed")); - tooltip.hide(); - return; - }; - - communities_ids.set(community_tracks.communities); - get_community_track.send(current_page()); + let Ok(community_tracks) = tracksIds().await else { + notification + .handle_error(&translate!(i18, "errors.communities.query_failed")); + tooltip.hide(); + return; + }; + communities_ids.set(community_tracks.communities); + get_community_track.send(current_page()); }); - rsx! { - div { - class: "dashboard grid-main", + div { class: "dashboard grid-main", div { class: "dashboard__head", section { class: "tabs", - // body: items for item in tab_items.into_iter() { Tab { text: item.value, - is_active: if tab_value() == item.k {true} else {false}, - on_click: move |_| { - // tab_value.set(item.k); - }, + is_active: if tab_value() == item.k { true } else { false }, + on_click: move |_| {} } } } @@ -145,28 +128,30 @@ pub fn Explore() -> Element { error: None, on_input: move |event: Event| { search_word.set(event.value()); - if search_word().trim().is_empty() { filtered_communities.set(communities()); } else { let pattern = search_word().trim().to_lowercase(); - filtered_communities.set(communities().into_iter().filter(|community| community.name.to_lowercase().contains(&pattern)).collect::>()); + filtered_communities + .set( + communities() + .into_iter() + .filter(|community| { + community.name.to_lowercase().contains(&pattern) + }) + .collect::>(), + ); } }, on_keypress: move |_| {}, - on_click: move |_| {}, + on_click: move |_| {} } 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)" - } + Icon { icon : AddPlus, height : 26, width : 26, stroke_width : 1.5, fill : + "var(--fill-00)" } ), on_click: move |_| { tooltip.hide(); @@ -182,24 +167,15 @@ pub fn Explore() -> Element { div { class: "card__head", IconButton { body: rsx!( - Avatar { - name: "{community.name}", - size: 48, - uri: community.icon, - variant: AvatarVariant::SemiRound - } + Avatar { name : "{community.name}", size : 48, uri : community.icon, variant : + AvatarVariant::SemiRound } ), - on_click: move |_| { } + on_click: move |_| {} } - h3 { class: "card__title", - "{community.name}" - } - } - p { class: "card__description", - "{community.description}" + h3 { class: "card__title", "{community.name}" } } + p { class: "card__description", "{community.description}" } div { class: "card__metrics", - span { class: "card__metric", Icon { icon: UserAdd, @@ -208,9 +184,7 @@ pub fn Explore() -> Element { stroke_width: 2, stroke: "var(--text-primary)" } - small { - "{community.memberships} Memberships" - } + small { "{community.memberships} Memberships" } } span { class: "card__metric", Icon { @@ -220,36 +194,21 @@ pub fn Explore() -> Element { stroke_width: 1, fill: "var(--text-primary)" } - small { - "{community.members} Members" - } + small { "{community.members} Members" } } } div { class: "card__tags", for tag in community.tags { - { - rsx!( - Badge { - class: "badge--lavanda-dark", - text: tag - } - ) - } + { 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)" - } + Icon { icon : ArrowRight, height : 32, width : 32, stroke_width : 2, fill : + "var(--fill-00)" } ), on_click: move |_| { let path = format!("/dao/{}/initiatives", community.id); @@ -263,15 +222,16 @@ pub fn Explore() -> Element { div { class: "card__container", div { class: "card__head", h3 { class: "card__title", - {translate!(i18, "dashboard.cta_cards.create.title")} + { translate!(i18, "dashboard.cta_cards.create.title") } } } p { class: "card__description", - {translate!(i18, "dashboard.cta_cards.create.description")} + { translate!(i18, + "dashboard.cta_cards.create.description") } } div { class: "card__head", a { class: "card__learn", - {translate!(i18, "dashboard.cta_cards.create.cta")} + { translate!(i18, "dashboard.cta_cards.create.cta") } } Icon { icon: ArrowRight, @@ -282,24 +242,18 @@ pub fn Explore() -> Element { } } } - 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)" - } + 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_dao_owner())], "/onboarding"); - } + } } } } @@ -307,42 +261,28 @@ pub fn Explore() -> Element { div { class: "dashboard__footer grid-footer", div { class: "dashboard__footer__pagination", span { class: "dashboard__footer__paginator", - {translate!(i18, "dashboard.footer.paginator", from: current_page(), to: (((communities_ids.len() as f64 + 1f64) / SKIP as f64) as f64).ceil())} + { translate!(i18, "dashboard.footer.paginator", + from : current_page(), to : (((communities_ids.len() as f64 + 1f64) / SKIP as + f64) as f64).ceil()) } } div { class: "dashboard__footer__paginators", IconButton { class: "button--avatar", 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); - get_community_track.send(current_page()) } } IconButton { class: "button--avatar", size: ElementSize::Small, - 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); - get_community_track.send(current_page()) } } diff --git a/src/pages/initiative.rs b/src/pages/initiative.rs index 426dc1c..b8ad501 100644 --- a/src/pages/initiative.rs +++ b/src/pages/initiative.rs @@ -1,16 +1,15 @@ use std::str::FromStr; - use chrono::{DateTime, Duration, NaiveDate, Utc}; use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; use futures_util::TryFutureExt; use wasm_bindgen::prelude::*; - use crate::{ components::{ atoms::{ - button::Variant, dropdown::ElementSize, icon_button::Variant as IconButtonVariant, - Arrow, Button, Icon, IconButton, Step, StepCard, + button::Variant, dropdown::ElementSize, + icon_button::Variant as IconButtonVariant, Arrow, Button, Icon, IconButton, + Step, StepCard, }, molecules::{InitiativeActions, InitiativeInfo}, }, @@ -20,10 +19,8 @@ use crate::{ InitiativeInitContent, KusamaTreasury, KusamaTreasuryPeriod, VotingOpenGov, VotingOpenGovAction, }, - use_notification::use_notification, - use_our_navigator::use_our_navigator, - use_session::use_session, - use_spaces_client::use_spaces_client, + 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, @@ -32,7 +29,6 @@ use crate::{ kusama::system::number, }, }; - #[derive(Clone, Debug)] pub enum InitiativeStep { Info, @@ -41,7 +37,6 @@ pub enum InitiativeStep { Confirmation, None, } - #[wasm_bindgen] extern "C" { #[wasm_bindgen(catch, js_namespace = window, js_name = topupThenInitiativeSetup)] @@ -56,9 +51,7 @@ extern "C" { proposals_voting_open_gov: JsValue, ) -> Result; } - const BLOCK_TIME_IN_SECONDS: i64 = 6; - #[component] pub fn Initiative(id: u16) -> Element { let i18 = use_i18(); @@ -68,14 +61,11 @@ pub fn Initiative(id: u16) -> Element { let mut tooltip = use_tooltip(); let mut notification = use_notification(); let spaces_client = use_spaces_client(); - let mut onboarding_step = use_signal::(|| InitiativeStep::Info); let mut handle_required_inputs = use_signal::(|| false); - use_before_render(move || { initiative.default(); }); - rsx! { div { class: "page--initiative", div { class: "progress progress--steps-cube", @@ -86,7 +76,7 @@ pub fn Initiative(id: u16) -> Element { name: Some(translate!(i18, "initiative.steps.info.label")), on_click: move |_| { onboarding_step.set(InitiativeStep::Info); - }, + } } Step { is_active: matches!(*onboarding_step.read(), InitiativeStep::Actions), @@ -102,98 +92,56 @@ pub fn Initiative(id: u16) -> Element { handle_required_inputs.set(false); } onboarding_step.set(InitiativeStep::Actions); - }, + } } } div { class: "initiative__form", div { class: "form__wrapper form__wrapper--initiative", h2 { class: "form__title", - {translate!(i18, "initiative.title")} + { + translate!(i18, "initiative.title") } } div { class: "steps__wrapper", StepCard { name: translate!(i18, "initiative.steps.info.label"), - checked: matches!(*onboarding_step.read(), InitiativeStep::Info ), + 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); - } - } - } - } + 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() - } - } + div { class : "step-card__editable", InitiativeInfo { error : + handle_required_inputs() } } ), on_change: move |_| { onboarding_step.set(InitiativeStep::Info); - }, + } } StepCard { name: translate!(i18, "initiative.steps.actions.label"), - checked: matches!(*onboarding_step.read(), InitiativeStep::Actions ), + 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 {} - } + 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); - }, + } } } } @@ -207,7 +155,7 @@ pub fn Initiative(id: u16) -> Element { on_click: move |_| { nav.go_back(); }, - status: None, + status: None } Button { class: "", @@ -216,17 +164,18 @@ pub fn Initiative(id: u16) -> Element { on_click: move |_| { spawn( async move { - tooltip.handle_tooltip(TooltipItem { - title: translate!(i18, "initiative.tips.loading.title"), - body: translate!(i18, "initiative.tips.loading.description"), - show: true - }); - - let last_initiative = referendum_count().await.map_err(|_| { - log::warn!("Failed to get last initiative"); - translate!(i18, "errors.form.initiative_creation") - })?; - + tooltip + .handle_tooltip(TooltipItem { + title: translate!(i18, "initiative.tips.loading.title"), + body: translate!(i18, "initiative.tips.loading.description"), + show: true, + }); + let last_initiative = referendum_count() + .await + .map_err(|_| { + log::warn!("Failed to get last initiative"); + translate!(i18, "errors.form.initiative_creation") + })?; let response_bot = spaces_client .get() .create_initiative(InitiativeData { @@ -249,199 +198,228 @@ pub fn Initiative(id: u16) -> Element { log::warn!("Failed to create off-chain"); translate!(i18, "errors.form.initiative_creation") })?; - let room_id = response_bot.get_id(); - - let add_members_action = initiative.get_actions().into_iter().filter_map(|action| { - match action { - ActionItem::AddMembers(add_members_action) => { - Some(add_members_action.members.clone() - .into_iter() - .filter_map(|member| - if !member.account.is_empty() { Some(member.account) } else { None } - ) - .collect::>()) - }, - _ => None - } - }).collect::>>(); - - let add_members_action = add_members_action.into_iter().flat_map(|v| v.into_iter()).collect::>(); - + let add_members_action = initiative + .get_actions() + .into_iter() + .filter_map(|action| { + match action { + ActionItem::AddMembers(add_members_action) => { + Some( + add_members_action + .members + .clone() + .into_iter() + .filter_map(|member| { + if !member.account.is_empty() { + Some(member.account) + } else { + None + } + }) + .collect::>(), + ) + } + _ => None, + } + }) + .collect::>>(); + let add_members_action = add_members_action + .into_iter() + .flat_map(|v| v.into_iter()) + .collect::>(); log::info!("add_members_action: {:?}", add_members_action); - - let current_block = number().await.map_err(|_| { - log::warn!("Failed to get last block kusama"); - translate!(i18, "errors.form.initiative_creation") - })?; - - let now_kusama = now().await.map_err(|_| { - log::warn!("Failed to get timestamp kusama"); - translate!(i18, "errors.form.initiative_creation") - })?; - + let current_block = number() + .await + .map_err(|_| { + log::warn!("Failed to get last block kusama"); + translate!(i18, "errors.form.initiative_creation") + })?; + let now_kusama = now() + .await + .map_err(|_| { + log::warn!("Failed to get timestamp kusama"); + translate!(i18, "errors.form.initiative_creation") + })?; log::info!("{} {}", current_block, now_kusama); - - let treasury_action = initiative.get_actions().into_iter().filter_map(|action| { - match action { - ActionItem::KusamaTreasury(treasury_action) => { - Some(treasury_action.periods.clone() - .into_iter() - .filter_map(|period|{ - if period.amount > 0 { - Some(convert_treasury_to_period(period, current_block, now_kusama)) - } else { - None - } - }) - .collect::>()) - }, - _ => None - } - }).collect::>>(); - - let treasury_action = treasury_action.into_iter().flat_map(|v| v.into_iter()).collect::>(); - + let treasury_action = initiative + .get_actions() + .into_iter() + .filter_map(|action| { + match action { + ActionItem::KusamaTreasury(treasury_action) => { + Some( + treasury_action + .periods + .clone() + .into_iter() + .filter_map(|period| { + if period.amount > 0 { + Some( + convert_treasury_to_period( + period, + current_block, + now_kusama, + ), + ) + } else { + None + } + }) + .collect::>(), + ) + } + _ => None, + } + }) + .collect::>>(); + let treasury_action = treasury_action + .into_iter() + .flat_map(|v| v.into_iter()) + .collect::>(); log::info!("treasury {:?}", treasury_action); - - let votiong_open_gov_action = initiative.get_actions().into_iter().filter_map(|action| { - match action { - ActionItem::VotingOpenGov(votiong_open_gov_action) => { - Some(votiong_open_gov_action.proposals.clone() - .into_iter() - .filter_map(|proposal|{ - if proposal.poll_index > 0 { - Some(proposal) - } else { - None - } - }) - .collect::>()) - }, - _ => None - } - }).collect::>>(); - - let votiong_open_gov_action = votiong_open_gov_action.into_iter().flat_map(|v| v.into_iter()).collect::>(); - let votiong_open_gov_action = votiong_open_gov_action.into_iter().map(|v| v.serialize_vote_type()).collect::>(); - + let votiong_open_gov_action = initiative + .get_actions() + .into_iter() + .filter_map(|action| { + match action { + ActionItem::VotingOpenGov(votiong_open_gov_action) => { + Some( + votiong_open_gov_action + .proposals + .clone() + .into_iter() + .filter_map(|proposal| { + if proposal.poll_index > 0 { Some(proposal) } else { None } + }) + .collect::>(), + ) + } + _ => None, + } + }) + .collect::>>(); + let votiong_open_gov_action = votiong_open_gov_action + .into_iter() + .flat_map(|v| v.into_iter()) + .collect::>(); + let votiong_open_gov_action = votiong_open_gov_action + .into_iter() + .map(|v| v.serialize_vote_type()) + .collect::>(); log::info!("votiong_open_gov_action {:?}", votiong_open_gov_action); - - let votiong_open_gov_action = convert_to_jsvalue(&votiong_open_gov_action) - .map_err(|_| { - log::warn!("Malformed voting open gov"); - translate!(i18, "errors.form.initiative_creation") - })?; - + let votiong_open_gov_action = convert_to_jsvalue( + &votiong_open_gov_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"); - translate!(i18, "errors.form.initiative_creation") - })?; - + .map_err(|_| { + log::warn!("Malformed membership accounts add"); + translate!(i18, "errors.form.initiative_creation") + })?; let membership_accounts_add = convert_to_jsvalue(&add_members_action) - .map_err(|_| { - log::warn!("Malformed membership accounts add"); - translate!(i18, "errors.form.initiative_creation") - })?; - - let membership_accounts_remove = convert_to_jsvalue(&Vec::::new()) + .map_err(|_| { + log::warn!("Malformed membership accounts add"); + translate!(i18, "errors.form.initiative_creation") + })?; + let membership_accounts_remove = convert_to_jsvalue( + &Vec::::new(), + ) .map_err(|_| { log::warn!("Malformed membership accounts remove"); translate!(i18, "errors.form.initiative_creation") })?; - - let room_id = - convert_to_jsvalue(&room_id.clone()).map_err(|_| { + let room_id = convert_to_jsvalue(&room_id.clone()) + .map_err(|_| { log::warn!("Malformed room id"); translate!(i18, "errors.form.initiative_creation") })?; - - let remark = - convert_to_jsvalue(&initiative.get_info().name).map_err(|_| { + let remark = convert_to_jsvalue(&initiative.get_info().name) + .map_err(|_| { log::warn!("Malformed remark"); translate!(i18, "errors.form.initiative_creation") })?; - let response = topup_then_initiative_setup( - id, - last_initiative, - room_id, - remark, - membership_accounts_add, - membership_accounts_remove, - treasury_action, - votiong_open_gov_action - ) - .await; - + id, + last_initiative, + room_id, + remark, + membership_accounts_add, + membership_accounts_remove, + treasury_action, + votiong_open_gov_action, + ) + .await; tooltip.hide(); - let path = format!("/dao/{id}/initiatives"); nav.push(vec![], &path); - Ok::<(), String>(()) } - .unwrap_or_else(move |e: String| { - tooltip.hide(); - notification.handle_error(&e); - }) + .unwrap_or_else(move |e: String| { + tooltip.hide(); + notification.handle_error(&e); + }), ); }, - status: None, + status: None } } } } } - fn calculate_future_block( current_block: u32, current_date_millis: u64, future_date_str: &str, ) -> u32 { - let future_date_naive = NaiveDate::from_str(future_date_str).expect("Fecha futura no vĂ¡lida"); + let future_date_naive = NaiveDate::from_str(future_date_str) + .expect("Fecha futura no vĂ¡lida"); let future_date = DateTime::::from_utc(future_date_naive.and_hms(0, 0, 0), Utc); - - let current_date = DateTime::::from_utc( + let current_date = DateTime::< + Utc, + >::from_utc( chrono::NaiveDateTime::from_timestamp( (current_date_millis / 1000).try_into().unwrap(), ((current_date_millis % 1000) * 1_000_000) as u32, ), Utc, ); - let elapsed_time_in_seconds = (future_date - current_date).num_seconds(); let blocks_to_add = elapsed_time_in_seconds / BLOCK_TIME_IN_SECONDS; (current_block + blocks_to_add as u32).into() } - fn calculate_date_from_block( current_block: u32, current_date_millis: u64, target_block: u32, ) -> DateTime { - let current_date = DateTime::::from_utc( + let current_date = DateTime::< + Utc, + >::from_utc( chrono::NaiveDateTime::from_timestamp( (current_date_millis / 1000).try_into().unwrap(), ((current_date_millis % 1000) * 1_000_000) as u32, ), Utc, ); - let blocks_to_add = target_block as i64 - current_block as i64; let elapsed_time_in_seconds = blocks_to_add * BLOCK_TIME_IN_SECONDS; current_date + Duration::seconds(elapsed_time_in_seconds) } - fn convert_treasury_to_period( treasury: KusamaTreasury, current_block: u32, current_date_millis: u64, ) -> KusamaTreasuryPeriod { if treasury.date != "" { - let future_block = - calculate_future_block(current_block, current_date_millis, &treasury.date); + let future_block = calculate_future_block( + current_block, + current_date_millis, + &treasury.date, + ); KusamaTreasuryPeriod { blocks: Some(future_block as u64), amount: treasury.amount, diff --git a/src/pages/initiatives.rs b/src/pages/initiatives.rs index f5de7db..ffa6e93 100644 --- a/src/pages/initiatives.rs +++ b/src/pages/initiatives.rs @@ -1,79 +1,66 @@ use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; use serde::{Deserialize, Serialize}; - use crate::{ components::{ atoms::{ - dropdown::ElementSize, AddPlus, ArrowLeft, ArrowRight, Badge, CircleCheck, Icon, - IconButton, SearchInput, StopSign, Tab, + dropdown::ElementSize, AddPlus, ArrowLeft, ArrowRight, Badge, CircleCheck, + Icon, IconButton, SearchInput, StopSign, Tab, }, molecules::tabs::TabItem, }, hooks::{ use_accounts::use_accounts, use_initiative::{use_initiative, InitiativeInfoContent}, - use_notification::use_notification, - use_our_navigator::use_our_navigator, - use_spaces_client::use_spaces_client, - use_tooltip::{use_tooltip, TooltipItem}, + use_notification::use_notification, use_our_navigator::use_our_navigator, + use_spaces_client::use_spaces_client, use_tooltip::{use_tooltip, TooltipItem}, }, services::kreivo::{ - community_referenda::{metadata_of, referendum_count, referendum_info_for, Ongoing}, + community_referenda::{ + metadata_of, referendum_count, referendum_info_for, Ongoing, + }, preimage::{preimage_for, request_status_for}, }, }; - static SKIP: u8 = 6; - #[derive(Clone, Debug, Deserialize, Serialize)] pub struct InitiativeWrapper { pub id: u16, pub info: InitiativeInfoContent, pub ongoing: Ongoing, } - #[component] pub fn Initiatives(id: u16) -> Element { let i18 = use_i18(); let mut tooltip = use_tooltip(); let nav = use_our_navigator(); let spaces_client = use_spaces_client(); - let mut initiative_wrapper = consume_context::>>(); - let mut current_page = use_signal::(|| 1); let mut search_word = use_signal::(|| String::new()); - - let tab_items = vec![TabItem { - k: String::from("all"), - value: translate!(i18, "dao.tabs.all"), - }]; - + let tab_items = vec![ + TabItem { + k: String::from("all"), + value: translate!(i18, "dao.tabs.all"), + }, + ]; let tab_value = use_signal::(|| String::from("all")); - let initiatives_ids = use_signal::>(|| vec![]); let mut initiatives = use_signal::>(|| vec![]); let mut filtered_initiatives = use_signal::>(|| vec![]); - use_coroutine(move |_: UnboundedReceiver<()>| async move { - tooltip.handle_tooltip(TooltipItem { - title: translate!(i18, "dao.tips.loading.title"), - body: translate!(i18, "dao.tips.loading.description"), - show: true, - }); - // Temporal value for FIFO ongoing initiative + tooltip + .handle_tooltip(TooltipItem { + title: translate!(i18, "dao.tips.loading.title"), + body: translate!(i18, "dao.tips.loading.description"), + show: true, + }); let from = 29; - - let count = referendum_count() - .await - .expect("Should get referendum count"); - + let count = referendum_count().await.expect("Should get referendum count"); for track in from..count { let Ok(response) = referendum_info_for(track).await else { continue; }; - if response.ongoing.origin.communities.community_id == id { let name = format!("Ref: {:?}", track); let mut init = InitiativeWrapper { @@ -86,56 +73,51 @@ pub fn Initiatives(id: u16) -> Element { }, ongoing: response.ongoing, }; - - log::info!("{:?}", metadata_of(track).await); + log::info!("{:?}", metadata_of(track). await); let Ok(initiative_metadata) = metadata_of(track).await else { initiatives.with_mut(|c| c.push(init)); continue; }; - - let initiative_metadata = format!("0x{}", hex::encode(initiative_metadata)); - - let Ok(preimage_len) = request_status_for(&initiative_metadata).await else { + let initiative_metadata = format!( + "0x{}", + hex::encode(initiative_metadata), + ); + let Ok(preimage_len) = request_status_for(&initiative_metadata).await + else { continue; }; - - let Ok(room_id_metadata) = preimage_for(&initiative_metadata, preimage_len).await - else { + let Ok(room_id_metadata) = preimage_for( + &initiative_metadata, + preimage_len, + ) + .await else { initiatives.with_mut(|c| c.push(init)); continue; }; - let Ok(response) = spaces_client .get() .get_initiative_by_id(&room_id_metadata) - .await - else { + .await else { initiatives.with_mut(|c| c.push(init)); continue; }; - log::info!("{:?}", response.info); - init.info = response.info; - initiatives.with_mut(|c| c.push(init)); } } - tooltip.hide(); filtered_initiatives.set(initiatives()); }); - rsx! { - div { - class: "dashboard grid-main", + div { class: "dashboard grid-main", div { class: "dashboard__head", section { class: "tabs", for item in tab_items.into_iter() { Tab { text: item.value, - is_active: if tab_value() == item.k {true} else {false}, - on_click: move |_| {}, + is_active: if tab_value() == item.k { true } else { false }, + on_click: move |_| {} } } } @@ -150,23 +132,26 @@ pub fn Initiatives(id: u16) -> Element { filtered_initiatives.set(initiatives()); } else { let pattern = search_word().trim().to_lowercase(); - filtered_initiatives.set(initiatives().into_iter().filter(|initiative| initiative.info.name.to_lowercase().contains(&pattern)).collect::>()); + filtered_initiatives + .set( + initiatives() + .into_iter() + .filter(|initiative| { + initiative.info.name.to_lowercase().contains(&pattern) + }) + .collect::>(), + ); } }, on_keypress: move |_| {}, - on_click: move |_| {}, + on_click: move |_| {} } 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)" - } + Icon { icon : AddPlus, height : 26, width : 26, stroke_width : 1.5, fill : + "var(--fill-00)" } ), on_click: move |_| { tooltip.hide(); @@ -181,14 +166,9 @@ pub fn Initiatives(id: u16) -> Element { section { class: "card", div { class: "card__container", div { class: "card__head", - - h3 { class: "card__title", - "{initiative.info.name}" - } - } - p { class: "card__description", - "" + h3 { class: "card__title", "{initiative.info.name}" } } + p { class: "card__description", "" } div { class: "card__metrics", span { class: "card__metric", Icon { @@ -198,48 +178,32 @@ pub fn Initiatives(id: u16) -> Element { stroke_width: 2, stroke: "var(--text-primary)" } - small { - "{initiative.ongoing.tally.ayes} Aye" - } + 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" + Icon { + icon: StopSign, + height: 16, + width: 16, + stroke_width: 2, + stroke: "var(--text-primary)" } + 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 - } - ) - } + { 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)" - } + Icon { icon : ArrowRight, height : 32, width : 32, stroke_width : 2, fill : + "var(--fill-00)" } ), on_click: move |_| { tooltip.hide(); @@ -255,15 +219,18 @@ pub fn Initiatives(id: u16) -> Element { div { class: "card__container", div { class: "card__head", h3 { class: "card__title", - {translate!(i18, "dao.cta_cards.create.title")} + { translate!(i18, + "dao.cta_cards.create.title") } } } p { class: "card__description", - {translate!(i18, "dao.cta_cards.create.description")} + { + translate!(i18, "dao.cta_cards.create.description") } } div { class: "card__head", a { class: "card__learn", - {translate!(i18, "dao.cta_cards.create.cta")} + { translate!(i18, + "dao.cta_cards.create.cta") } } Icon { icon: ArrowRight, @@ -274,19 +241,13 @@ pub fn Initiatives(id: u16) -> Element { } } } - 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)" - } + Icon { icon : AddPlus, height : 32, width : 32, stroke_width : 1.5, fill : + "var(--fill-00)" } ), on_click: move |_| { tooltip.hide(); @@ -300,20 +261,15 @@ pub fn Initiatives(id: u16) -> Element { div { class: "dashboard__footer grid-footer", div { class: "dashboard__footer__pagination", span { class: "dashboard__footer__paginator", - {translate!(i18, "dashboard.footer.paginator", from: current_page(), to: (((initiatives_ids.len() as f64 + 1f64) / SKIP as f64) as f64).ceil())} + { + translate!(i18, "dashboard.footer.paginator", from : current_page(), to : + (((initiatives_ids.len() as f64 + 1f64) / SKIP as f64) as f64).ceil()) } } div { class: "dashboard__footer__paginators", IconButton { class: "button--avatar", 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); @@ -322,14 +278,7 @@ pub fn Initiatives(id: u16) -> Element { IconButton { class: "button--avatar", size: ElementSize::Small, - 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/pages/not_found.rs b/src/pages/not_found.rs index 6343ea0..8192e80 100644 --- a/src/pages/not_found.rs +++ b/src/pages/not_found.rs @@ -1,5 +1,4 @@ use dioxus::prelude::*; - #[component] pub fn PageNotFound(route: Vec) -> Element { rsx! { diff --git a/src/pages/onboarding.rs b/src/pages/onboarding.rs index 86eb926..889295b 100644 --- a/src/pages/onboarding.rs +++ b/src/pages/onboarding.rs @@ -1,43 +1,37 @@ use std::vec; - use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; use futures_util::TryFutureExt; use gloo::utils::format::JsValueSerdeExt; use serde::Serialize; - use crate::{ components::{ atoms::{ - button::Variant, dropdown::ElementSize, ArrowLeft, ArrowRight, Button, Icon, VirtoLogo, + button::Variant, dropdown::ElementSize, ArrowLeft, ArrowRight, Button, Icon, + VirtoLogo, }, molecules::{OnboardingBasics, OnboardingInvite, OnboardingManagement}, }, hooks::{ - use_accounts::use_accounts, - use_attach::use_attach, + use_accounts::use_accounts, use_attach::use_attach, use_notification::{ use_notification, NotificationHandle, NotificationHandler, NotificationItem, NotificationVariant, }, - use_onboard::use_onboard, - use_our_navigator::use_our_navigator, - use_session::use_session, - use_spaces_client::use_spaces_client, + use_onboard::use_onboard, use_our_navigator::use_our_navigator, + use_session::use_session, use_spaces_client::use_spaces_client, use_tooltip::{use_tooltip, TooltipItem}, }, services::{bot::types::CommunitySpace, kreivo::community_track::tracksIds}, }; use serde_json::{to_value, Error}; use wasm_bindgen::prelude::*; - #[derive(Clone, Debug)] pub enum OnboardingStep { Basics, Management, Invite, } - #[derive(Serialize)] #[serde(rename_all = "camelCase")] struct TopupDetails { @@ -45,21 +39,11 @@ struct TopupDetails { pub community_account_in_kreivo: u32, pub community_account_in_people: u32, } - #[derive(Serialize)] struct Identity { pub display: String, - // TODO: enable this to integrate the actual required fields by blockchain - // pub legal: Option, - // pub web: Option, pub matrix: Option, - // pub pgpFingerprint: Option, - // pub image: Option, - // pub twitter: Option, - // pub github: Option, - // pub discord: Option, } - #[derive(Serialize)] #[serde(tag = "type", rename_all = "camelCase")] enum DecisionMethod { @@ -68,7 +52,6 @@ enum DecisionMethod { NativeToken, CommunityAsset { id: String, min_vote: i32 }, } - #[derive(Serialize)] struct CommunityData { signer: String, @@ -76,13 +59,11 @@ struct CommunityData { decision_method: DecisionMethod, identity: Identity, } - pub fn convert_to_jsvalue(value: &T) -> Result { to_value(value) .map(|t: serde_json::Value| JsValue::from_serde(&t)) .unwrap_or_else(|e| Ok(JsValue::from_str("Error creating JsValue"))) } - #[wasm_bindgen] extern "C" { #[wasm_bindgen(catch, js_namespace = window, js_name = topupThenCreateCommunity)] @@ -95,7 +76,6 @@ extern "C" { maybe_topup: JsValue, ) -> Result; } - #[component] pub fn Onboarding() -> Element { let i18 = use_i18(); @@ -107,35 +87,25 @@ pub fn Onboarding() -> Element { let mut notification = use_notification(); let spaces_client = use_spaces_client(); let mut nav = use_our_navigator(); - let mut to_pay = consume_context::>(); - let mut id_number = use_signal::(|| String::new()); let mut onboarding_step = use_signal::(|| OnboardingStep::Basics); - let mut onboarding_steps = use_signal::>(|| { - vec![ - OnboardingStep::Basics, - OnboardingStep::Management, - OnboardingStep::Invite, - ] + let mut onboarding_steps = use_signal::< + Vec, + >(|| { + vec![OnboardingStep::Basics, OnboardingStep::Management, OnboardingStep::Invite] }); - let mut handle_required_inputs = use_signal::(|| false); - use_before_render(move || { onboard.default(); }); - use_drop(move || attach.reset()); - let get_account = move || { let Some(user_session) = session.get() else { return None; }; - accounts.get_one(user_session.account_id) }; - rsx! { div { class: "page page--onboarding", div { class: "row", @@ -160,7 +130,9 @@ pub fn Onboarding() -> Element { class: "step", class: if matches!(*onboarding_step.read(), OnboardingStep::Management) { "step--active" }, onclick: move |_| { - if onboard.get_basics().name.is_empty() || onboard.get_basics().industry.is_empty() { + if onboard.get_basics().name.is_empty() + || onboard.get_basics().industry.is_empty() + { onboarding_step.set(OnboardingStep::Basics); handle_required_inputs.set(true); return; @@ -174,7 +146,9 @@ pub fn Onboarding() -> Element { class: "step", class: if matches!(*onboarding_step.read(), OnboardingStep::Invite) { "step--active" }, onclick: move |_| { - if onboard.get_basics().name.is_empty() || onboard.get_basics().industry.is_empty() { + if onboard.get_basics().name.is_empty() + || onboard.get_basics().industry.is_empty() + { onboarding_step.set(OnboardingStep::Basics); handle_required_inputs.set(true); return; @@ -185,14 +159,11 @@ pub fn Onboarding() -> Element { } } } - match *onboarding_step.read() { - OnboardingStep::Basics => rsx!(OnboardingBasics { - error: handle_required_inputs() - }), - OnboardingStep::Management => rsx!(OnboardingManagement {}), - OnboardingStep::Invite => rsx!(OnboardingInvite {}), - } - + match * + onboarding_step.read() { OnboardingStep::Basics => rsx!(OnboardingBasics { error + : handle_required_inputs() }), OnboardingStep::Management => + rsx!(OnboardingManagement {}), OnboardingStep::Invite => rsx!(OnboardingInvite + {}), } } div { class: "form__cta", if !matches!(*onboarding_step.read(), OnboardingStep::Basics) { @@ -211,50 +182,38 @@ pub fn Onboarding() -> Element { }, status: None, left_icon: rsx!( - Icon { - icon: ArrowLeft, - height: 32, - width: 32, - stroke_width: 1, - fill: "var(--text-primary)" - } - ), + Icon { icon : ArrowLeft, height : 32, width : 32, stroke_width : 1, fill : + "var(--text-primary)" } + ) } } - if !matches!(onboarding_step(), OnboardingStep::Invite) { Button { class: "", text: translate!(i18, "onboard.management.cta.next"), size: ElementSize::Big, on_click: move |_| { - if onboard.get_basics().name.is_empty() || onboard.get_basics().industry.is_empty() { + if onboard.get_basics().name.is_empty() + || onboard.get_basics().industry.is_empty() + { onboarding_step.set(OnboardingStep::Basics); handle_required_inputs.set(true); return; } else { handle_required_inputs.set(false); } - let step = onboarding_step(); match step { OnboardingStep::Basics => onboarding_step.set(OnboardingStep::Management), OnboardingStep::Management => onboarding_step.set(OnboardingStep::Invite), - OnboardingStep::Invite => { - - }, + OnboardingStep::Invite => {} }; }, status: None, right_icon: rsx!( - Icon { - icon: ArrowRight, - height: 32, - width: 32, - stroke_width: 1, - fill: "var(--white)" - } - ), + Icon { icon : ArrowRight, height : 32, width : 32, stroke_width : 1, fill : + "var(--white)" } + ) } } else { Button { @@ -262,135 +221,149 @@ pub fn Onboarding() -> Element { text: format!("{}: {:.2} KSM", translate!(i18, "onboard.invite.cta.next"), to_pay()), size: ElementSize::Big, on_click: move |_| { - if onboard.get_basics().name.is_empty() || onboard.get_basics().industry.is_empty() { + if onboard.get_basics().name.is_empty() + || onboard.get_basics().industry.is_empty() + { onboarding_step.set(OnboardingStep::Basics); handle_required_inputs.set(true); return; } else { handle_required_inputs.set(false); } - let step = onboarding_step(); match step { OnboardingStep::Basics => { onboarding_step.set(OnboardingStep::Management); - }, + } OnboardingStep::Management => { onboarding_step.set(OnboardingStep::Invite); - }, + } OnboardingStep::Invite => { spawn({ async move { let community = CommunitySpace { name: onboard.get_basics().name, logo: onboard.get_basics().logo, - description: if onboard.get_basics().description.is_empty() { None } else { Some(onboard.get_basics().description) }, - industry: onboard.get_basics().industry + description: if onboard.get_basics().description.is_empty() { + None + } else { + Some(onboard.get_basics().description) + }, + industry: onboard.get_basics().industry, }; - - let response_track_ids = tracksIds().await.map_err(|_| translate!(i18, "errors.form.community_creation"))?; - + let response_track_ids = tracksIds() + .await + .map_err(|_| { + translate!(i18, "errors.form.community_creation") + })?; let name_bytes = Vec::from(onboard.get_basics().name); - let community_id = name_bytes.into_iter().fold(0u16, |acc, elem| acc + elem as u16); + let community_id = name_bytes + .into_iter() + .fold(0u16, |acc, elem| acc + elem as u16); let mut offset = 0u16; - - while response_track_ids.communities.contains(&(community_id + offset)) { + while response_track_ids + .communities + .contains(&(community_id + offset)) + { offset += 1u16; } - let current_id = community_id + offset; id_number.set(current_id.to_string()); - - tooltip.handle_tooltip(TooltipItem { - title: translate!(i18, "onboard.tips.loading.title"), - body: translate!(i18, "onboard.tips.loading.description"), - show: true - }); - - let decision_method = convert_to_jsvalue(&DecisionMethod::Membership).map_err(|_| { - log::warn!("Malformed decision method"); - translate!(i18, "errors.form.community_creation") - })?; - - let response = spaces_client.get().create(community).await.map_err(|_| translate!(i18, "errors.form.community_creation"))?; - + tooltip + .handle_tooltip(TooltipItem { + title: translate!(i18, "onboard.tips.loading.title"), + body: translate!(i18, "onboard.tips.loading.description"), + show: true, + }); + let decision_method = convert_to_jsvalue( + &DecisionMethod::Membership, + ) + .map_err(|_| { + log::warn!("Malformed decision method"); + translate!(i18, "errors.form.community_creation") + })?; + let response = spaces_client + .get() + .create(community) + .await + .map_err(|_| { + translate!(i18, "errors.form.community_creation") + })?; let identity = Identity { display: onboard.get_basics().name, - matrix: Some(response.get_id()) + matrix: Some(response.get_id()), }; - - let encoded_identity = convert_to_jsvalue(&identity).map_err(|_| { - log::warn!("Malformed identity"); - translate!(i18, "errors.form.community_creation") - })?; - - let members = onboard.get_invitations() + let encoded_identity = convert_to_jsvalue(&identity) + .map_err(|_| { + log::warn!("Malformed identity"); + translate!(i18, "errors.form.community_creation") + })?; + let members = onboard + .get_invitations() .into_iter() - .filter_map(|invitation| if !invitation.account.is_empty() { Some(invitation.account) } else { None }) + .filter_map(|invitation| { + if !invitation.account.is_empty() { + Some(invitation.account) + } else { + None + } + }) .collect::>(); - - let membership_accounts = convert_to_jsvalue(&members).map_err(|_| { - log::warn!("Malformed membership accounts"); - translate!(i18, "errors.form.community_creation") - })?; - + let membership_accounts = convert_to_jsvalue(&members) + .map_err(|_| { + log::warn!("Malformed membership accounts"); + translate!(i18, "errors.form.community_creation") + })?; let response = topup_then_create_community( - current_id, - identity.display.clone(), - decision_method, - encoded_identity, - membership_accounts, - JsValue::UNDEFINED - ).await.map_err(|_| { - log::warn!("Error on xcm program"); - translate!(i18, "errors.form.community_creation") - })?; - + current_id, + identity.display.clone(), + decision_method, + encoded_identity, + membership_accounts, + JsValue::UNDEFINED, + ) + .await + .map_err(|_| { + log::warn!("Error on xcm program"); + translate!(i18, "errors.form.community_creation") + })?; tooltip.hide(); - notification.handle_notification( - NotificationItem { + notification + .handle_notification(NotificationItem { title: translate!(i18, "onboard.tips.created.title"), body: translate!(i18, "onboard.tips.created.description"), variant: NotificationVariant::Success, show: true, - handle: NotificationHandle {value: NotificationHandler::None} - } - ); + handle: NotificationHandle { + value: NotificationHandler::None, + }, + }); nav.push(Vec::new(), "/"); - Ok::<(), String>(()) } - .unwrap_or_else(move |e: String| { - tooltip.hide(); - notification.handle_error(&e); - }) + .unwrap_or_else(move |e: String| { + tooltip.hide(); + notification.handle_error(&e); + }) }); - }, + } }; }, status: None, right_icon: rsx!( - Icon { - icon: ArrowRight, - height: 32, - width: 32, - stroke_width: 1, - fill: "var(--white)" - } - ), + Icon { icon : ArrowRight, height : 32, width : 32, stroke_width : 1, fill : + "var(--white)" } + ) } } - } } div { class: "onboarding__image", - img { - src: match *onboarding_step.read() { + img { src: match *onboarding_step.read() { OnboardingStep::Basics => "images/window.png", OnboardingStep::Management => "images/phone.png", OnboardingStep::Invite => "images/faces.png", - } - } + } } } } } diff --git a/src/pages/route.rs b/src/pages/route.rs index f410afc..b27e3bd 100644 --- a/src/pages/route.rs +++ b/src/pages/route.rs @@ -1,35 +1,34 @@ use dioxus::prelude::*; - use crate::{ layouts::{authenticated::Authenticated, onboard::Onboard}, pages::{ - dashboard::Dashboard, explore::Explore, initiative::Initiative, initiatives::Initiatives, - not_found::PageNotFound, onboarding::Onboarding, vote::Vote, + dashboard::Dashboard, explore::Explore, initiative::Initiative, + initiatives::Initiatives, not_found::PageNotFound, onboarding::Onboarding, + vote::Vote, }, }; - #[derive(Clone, Routable, Debug, PartialEq)] #[rustfmt::skip] pub enum Route { #[route("/onboarding")] Onboarding {}, #[layout(Authenticated)] - #[route("/")] - Dashboard {}, - #[layout(Onboard)] - #[route("/explore")] - Explore {}, - #[nest("/dao")] - #[nest("/:id")] - #[route("/initiatives")] - Initiatives {id: u16}, - #[route("/initiative")] - Initiative {id: u16}, - #[route("/vote/:initiativeid")] - Vote {id: u16, initiativeid: u16}, - #[end_nest] - #[end_nest] - #[end_layout] + #[route("/")] + Dashboard {}, + #[layout(Onboard)] + #[route("/explore")] + Explore {}, + #[nest("/dao")] + #[nest("/:id")] + #[route("/initiatives")] + Initiatives { id: u16 }, + #[route("/initiative")] + Initiative { id: u16 }, + #[route("/vote/:initiativeid")] + Vote { id: u16, initiativeid: u16 }, + #[end_nest] + #[end_nest] + #[end_layout] #[end_layout] #[route("/:..route")] PageNotFound { route: Vec }, diff --git a/src/pages/vote.rs b/src/pages/vote.rs index 8f2ab80..9da78a4 100644 --- a/src/pages/vote.rs +++ b/src/pages/vote.rs @@ -1,23 +1,22 @@ use std::str::FromStr; - use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; use futures_util::{StreamExt, TryFutureExt}; - use crate::{ components::{ atoms::{ - button::Variant, dropdown::ElementSize, key_value::Variant as KeyValueVariant, - ActionRequest, Badge, Bar, Button, CircleCheck, Icon, KeyValue, StopSign, + button::Variant, dropdown::ElementSize, + key_value::Variant as KeyValueVariant, ActionRequest, Badge, Bar, Button, + CircleCheck, Icon, KeyValue, StopSign, }, molecules::ActionRequestList, }, hooks::{ - use_initiative::{ActionItem, InitiativeInfoContent, InitiativeVoteData, Vote, VoteOf}, - use_notification::use_notification, - use_our_navigator::use_our_navigator, - use_session::use_session, - use_spaces_client::use_spaces_client, + use_initiative::{ + ActionItem, InitiativeInfoContent, InitiativeVoteData, Vote, VoteOf, + }, + 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_vote::{ProposalStatus, VoteDigest}, }, @@ -31,7 +30,6 @@ use crate::{ }, }; use wasm_bindgen::prelude::*; - #[wasm_bindgen] extern "C" { #[wasm_bindgen(catch, js_namespace = window, js_name = topupThenInitiativeVote)] @@ -41,206 +39,173 @@ extern "C" { vote: bool, ) -> Result; } - #[component] pub fn Vote(id: u16, initiativeid: u16) -> Element { let i18 = use_i18(); let session = use_session(); let spaces_client = use_spaces_client(); let nav = use_our_navigator(); - let mut notification = use_notification(); let mut tooltip = use_tooltip(); - let mut votes_statistics = use_signal(|| VoteDigest::default()); let mut content = use_signal(|| String::new()); let mut can_vote = use_signal(|| false); - let mut show_requests = use_signal(|| false); let mut show_vote = use_signal(|| true); - let mut initiative_wrapper = consume_context::>>(); let mut current_block = use_signal(|| 0); let mut track_info = use_signal(|| None); let mut members = use_signal(|| 0); let mut room_id = use_signal(|| None); - let mut approval_threshold = use_signal(|| 100.0); let mut participation_threshold = use_signal(|| 100.0); - let cont = &*content.read(); let parser = pulldown_cmark::Parser::new(cont); - let mut html_buf = String::new(); pulldown_cmark::html::push_html(&mut html_buf, parser); - let on_handle_vote = use_coroutine(move |mut rx: UnboundedReceiver<()>| async move { while let Some(_) = rx.next().await { let Some(account) = session.get() else { log::info!("error here by account"); - notification.handle_error(&translate!(i18, "errors.communities.query_failed")); - + notification + .handle_error(&translate!(i18, "errors.communities.query_failed")); return; }; - let Ok(address) = sp_core::sr25519::Public::from_str(&account.address) else { log::info!("error here by address"); - notification.handle_error(&translate!(i18, "errors.wallet.account_address")); - + notification + .handle_error(&translate!(i18, "errors.wallet.account_address")); return; }; - let Ok(community_tracks) = get_communities_by_member(&address.0).await else { log::info!("error here by memeber"); - notification.handle_error(&translate!(i18, "errors.communities.query_failed")); - + notification + .handle_error(&translate!(i18, "errors.communities.query_failed")); return; }; - - // get community members let response_item = item(id, None).await; let item_details = match response_item { Ok(items) => items, Err(_) => 0u16, }; - members.set(item_details); - - // get current block let Ok(block) = number().await else { log::warn!("Failed to get last block kusama"); continue; }; - current_block.set(block); - - // get track let Ok(track) = tracks(id).await else { log::warn!("Failed to get track"); continue; }; - track_info.set(Some(track)); - if initiative_wrapper().is_none() { let Ok(response) = referendum_info_for(initiativeid).await else { continue; }; - let name = format!("Ref: {:?}", initiativeid); - initiative_wrapper.set(Some(InitiativeWrapper { - id: initiativeid, - info: InitiativeInfoContent { - name, - description: String::new(), - tags: vec![], - actions: vec![], - }, - ongoing: response.ongoing, - })); - }; - + initiative_wrapper + .set( + Some(InitiativeWrapper { + id: initiativeid, + info: InitiativeInfoContent { + name, + description: String::new(), + tags: vec![], + actions: vec![], + }, + ongoing: response.ongoing, + }), + ); + } let threshold = get_approval_threshold( &*track_info.read(), &initiative_wrapper.unwrap().ongoing.deciding, current_block(), ); - approval_threshold.set(threshold); - let threshold = get_participation_threshold( &*track_info.read(), &initiative_wrapper.unwrap().ongoing.deciding, current_block(), ); participation_threshold.set(threshold); - if community_tracks.iter().any(|community| community.id == id) { can_vote.set(true); } - if let Some(wrapper) = initiative_wrapper() { votes_statistics.set(VoteDigest::default()); - votes_statistics.with_mut(|votes| votes.aye = wrapper.ongoing.tally.ayes); - votes_statistics.with_mut(|votes| votes.nay = wrapper.ongoing.tally.nays); + votes_statistics + .with_mut(|votes| votes.aye = wrapper.ongoing.tally.ayes); + votes_statistics + .with_mut(|votes| votes.nay = wrapper.ongoing.tally.nays); } - if let Some(mut wrapper) = initiative_wrapper() { let Ok(initiative_metadata) = metadata_of(initiativeid).await else { content.set(wrapper.info.description); continue; }; - - let initiative_metadata = format!("0x{}", hex::encode(initiative_metadata)); - - let Ok(preimage_len) = request_status_for(&initiative_metadata).await else { + let initiative_metadata = format!( + "0x{}", + hex::encode(initiative_metadata), + ); + let Ok(preimage_len) = request_status_for(&initiative_metadata).await + else { continue; }; - - let Ok(room_id_metadata) = preimage_for(&initiative_metadata, preimage_len).await - else { + let Ok(room_id_metadata) = preimage_for( + &initiative_metadata, + preimage_len, + ) + .await else { continue; }; - log::info!("{}", room_id_metadata); - let Ok(response) = spaces_client .get() .get_initiative_by_id(&room_id_metadata) - .await - else { + .await else { content.set(wrapper.info.description); continue; }; - room_id.set(Some(room_id_metadata)); - content.set(response.info.description.clone()); - wrapper.info = response.info.clone(); - initiative_wrapper.set(Some(wrapper.clone())); } } }); - let handle_vote = move |is_vote_aye: bool| { spawn( async move { - tooltip.handle_tooltip(TooltipItem { - title: translate!(i18, "governance.tips.voting.title"), - body: translate!(i18, "governance.tips.voting.description"), - show: true, - }); - + tooltip + .handle_tooltip(TooltipItem { + title: translate!(i18, "governance.tips.voting.title"), + body: translate!(i18, "governance.tips.voting.description"), + show: true, + }); let account_address = session .get() .ok_or(translate!(i18, "errors.wallet.account_address"))? .address; - - let address = - sp_core::sr25519::Public::from_str(&account_address).map_err(|e| { + let address = sp_core::sr25519::Public::from_str(&account_address) + .map_err(|e| { log::warn!("Not found public address: {}", e); translate!(i18, "errors.wallet.account_address") })?; - let hex_address = hex::encode(address.0); - let membership_id = get_membership_id(&format!("0x{}", hex_address), id) .await .map_err(|_| translate!(i18, "errors.wallet.account_address"))?; - if let Some(room_id) = room_id() { spaces_client .get() .vote_initiative(InitiativeVoteData { user: account_address, room: room_id, - vote: Vote::Standard(if is_vote_aye { - VoteOf::Yes - } else { - VoteOf::No - }), + vote: Vote::Standard( + if is_vote_aye { VoteOf::Yes } else { VoteOf::No }, + ), }) .await .map_err(|e| { @@ -248,41 +213,37 @@ pub fn Vote(id: u16, initiativeid: u16) -> Element { translate!(i18, "errors.vote.persist_failed") })?; } - topup_then_initiative_vote(membership_id, initiativeid, is_vote_aye) .await .map_err(|e| { log::warn!("Failed to vote on-chain: {:?}", e); translate!(i18, "errors.vote.chain") })?; - on_handle_vote.send(()); tooltip.hide(); - - notification.handle_success(&translate!(i18, "governance.tips.voted.description")); - + notification + .handle_success( + &translate!(i18, "governance.tips.voted.description"), + ); let path = format!("/dao/{id}/initiatives"); nav.push(vec![], &path); - Ok::<(), String>(()) } - .unwrap_or_else(move |e: String| { - tooltip.hide(); - notification.handle_error(&e); - }), + .unwrap_or_else(move |e: String| { + tooltip.hide(); + notification.handle_error(&e); + }), ); }; - - use_coroutine(move |_: UnboundedReceiver<()>| async move { on_handle_vote.send(()) }); - + use_coroutine(move |_: UnboundedReceiver<()>| async move { + on_handle_vote.send(()) + }); rsx! { div { class: "page--vote", div { class: "initiative__form", if let Some(initiative_wrapper) = &*initiative_wrapper.read() { div { class: "form__wrapper form__wrapper--initiative", - h2 { class: "form__title", - "{initiative_wrapper.info.name}" - } + h2 { class: "form__title", "{initiative_wrapper.info.name}" } div { class: "details__metadata", KeyValue { class: "key-value", @@ -290,10 +251,8 @@ pub fn Vote(id: u16, initiativeid: u16) -> Element { size: ElementSize::Medium, variant: KeyValueVariant::Secondary, body: rsx!( - { - let hex_string = hex::encode(&initiative_wrapper.ongoing.submission_deposit.who); - format!("0x{}", hex_string) - } + { let hex_string = hex::encode(& initiative_wrapper.ongoing.submission_deposit + .who); format!("0x{}", hex_string) } ) } } @@ -301,27 +260,30 @@ pub fn Vote(id: u16, initiativeid: u16) -> Element { div { class: "row", section { class: "details__voting", div { class: "vote-card", - h4 { class: "vote-card__title", - "Request" - } - button { class: "button--tertiary", + h4 { class: "vote-card__title", "Request" } + button { + class: "button--tertiary", onclick: move |_| show_requests.toggle(), ActionRequest { name: if show_requests() { "Hide all requests" } else { "See all requests" }, - details: initiative_wrapper.info.actions.iter().map(|item| { - match item { - ActionItem::AddMembers(action) => action.members.len(), - ActionItem::KusamaTreasury(action) => action.periods.len(), - ActionItem::VotingOpenGov(action) => action.proposals.len(), - } - }).sum::().to_string(), + details: initiative_wrapper + .info + .actions + .iter() + .map(|item| { + match item { + ActionItem::AddMembers(action) => action.members.len(), + ActionItem::KusamaTreasury(action) => action.periods.len(), + ActionItem::VotingOpenGov(action) => action.proposals.len(), + } + }) + .sum::() + .to_string(), size: ElementSize::Small } } if show_requests() { - ActionRequestList { - actions: initiative_wrapper.info.actions.clone() - } + ActionRequestList { actions: initiative_wrapper.info.actions.clone() } } } } @@ -330,64 +292,35 @@ pub fn Vote(id: u16, initiativeid: u16) -> Element { div { class: "details__statistics", div { class: "details__head", h2 { class: "vote-card__title statistics__title", - {translate!(i18, "governance.description.details.status.title")} - } - { - let status = if initiative_wrapper.ongoing.in_queue | initiative_wrapper.ongoing.deciding.is_none() { - ProposalStatus::QUEUE - } else { - ProposalStatus::VOTING - }; - let (badge_title, badge_color) = match status { - ProposalStatus::APPROVED => (translate!(i18, "governance.description.details.status.options.approved"), "badge--green-dark"), - ProposalStatus::REJECTED => (translate!(i18, "governance.description.details.status.options.rejected"), "badge--red-dark"), - ProposalStatus::VOTING => (translate!(i18, "governance.description.details.status.options.voting"), "badge--lavanda-dark"), - ProposalStatus::QUEUE => (translate!(i18, "governance.description.details.status.options.queue"), "badge--blue-light"), - }; - - rsx!( - Badge { - text: badge_title, - class: badge_color.to_string() - } - ) + { translate!(i18, + "governance.description.details.status.title") } } + { let status = if + initiative_wrapper.ongoing.in_queue | initiative_wrapper.ongoing.deciding + .is_none() { ProposalStatus::QUEUE } else { ProposalStatus::VOTING }; let + (badge_title, badge_color) = match status { ProposalStatus::APPROVED => + (translate!(i18, "governance.description.details.status.options.approved"), + "badge--green-dark"), ProposalStatus::REJECTED => (translate!(i18, + "governance.description.details.status.options.rejected"), "badge--red-dark"), + ProposalStatus::VOTING => (translate!(i18, + "governance.description.details.status.options.voting"), "badge--lavanda-dark"), + ProposalStatus::QUEUE => (translate!(i18, + "governance.description.details.status.options.queue"), "badge--blue-light"), }; + rsx!(Badge { text : badge_title, class : badge_color.to_string() }) } } div { { - let mut consumed = 0; - - if let Some(deciding) = &initiative_wrapper.ongoing.deciding { - if current_block() > 0 { - consumed = current_block() - deciding.since; - } - } - - let decision = match &*track_info.read() { - Some(info) => info.decision_period, - None => 36000 - }; - - let consumed_percent = 100.0 / decision as f64 * consumed as f64; - - rsx!( - Bar { - left_value: consumed_percent, - right_value: 100.0 - consumed_percent, - right_helper: if blocks_to_days(decision - consumed) == 0 { - format!("{}", blocks_to_days(decision - consumed) + 1) - } else { - format!("{}", blocks_to_days(decision - consumed)) - }, - left_title: "Decision", - right_title: match blocks_to_times(decision) { - Times::Minutes(time) => {format!("{} Minutes", time)}, - Times::Hours(time) => {format!("{} Hours", time)}, - Times::Days(time) => {format!("{} Days", time)}, - }, - } - ) - } + let mut consumed = 0; if let Some(deciding) = & initiative_wrapper.ongoing + .deciding { if current_block() > 0 { consumed = current_block() - deciding.since; + } } let decision = match &* track_info.read() { Some(info) => info + .decision_period, None => 36000 }; let consumed_percent = 100.0 / decision as f64 + * consumed as f64; rsx!(Bar { left_value : consumed_percent, right_value : 100.0 + - consumed_percent, right_helper : if blocks_to_days(decision - consumed) == 0 { + format!("{}", blocks_to_days(decision - consumed) + 1) } else { format!("{}", + blocks_to_days(decision - consumed)) }, left_title : "Decision", right_title : + match blocks_to_times(decision) { Times::Minutes(time) => { format!("{} Minutes", + time) }, Times::Hours(time) => { format!("{} Hours", time) }, Times::Days(time) + => { format!("{} Days", time) }, }, }) } } } } @@ -397,7 +330,8 @@ pub fn Vote(id: u16, initiativeid: u16) -> Element { div { class: "details__statistics", div { class: "details__head", h2 { class: "vote-card__title statistics__title", - {translate!(i18, "governance.description.voting.title")} + { translate!(i18, + "governance.description.voting.title") } } Button { text: if show_vote() { "Hide vote" } else { "Vote" }, @@ -406,7 +340,7 @@ pub fn Vote(id: u16, initiativeid: u16) -> Element { on_click: move |_| { show_vote.toggle(); }, - status: None, + status: None } } if show_vote() { @@ -414,25 +348,18 @@ pub fn Vote(id: u16, initiativeid: u16) -> Element { "Explain that this is a dynamic voting, and thresholds might change." } } - if show_vote() && can_vote(){ + if show_vote() && can_vote() { div { class: "row", Button { class: "vote-cta", text: translate!(i18, "governance.description.voting.cta.for"), size: ElementSize::Medium, variant: Variant::Secondary, - on_click: move |_| { - handle_vote(true) - }, + on_click: move |_| { handle_vote(true) }, status: None, left_icon: rsx!( - Icon { - icon: CircleCheck, - height: 16, - width: 16, - stroke_width: 2, - stroke: "#56C95F" - } + Icon { icon : CircleCheck, height : 16, width : 16, stroke_width : 2, stroke : + "#56C95F" } ) } Button { @@ -440,18 +367,11 @@ pub fn Vote(id: u16, initiativeid: u16) -> Element { text: translate!(i18, "governance.description.voting.cta.against"), size: ElementSize::Medium, variant: Variant::Secondary, - on_click: move |_| { - handle_vote(false) - }, + on_click: move |_| { handle_vote(false) }, status: None, left_icon: rsx!( - Icon { - icon: StopSign, - height: 16, - width: 16, - stroke_width: 2, - stroke: "#f44336bd" - } + Icon { icon : StopSign, height : 16, width : 16, stroke_width : 2, stroke : + "#f44336bd" } ) } } @@ -472,88 +392,56 @@ 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()) }) } } } if show_vote() { div { div { class: "votes-counter votes-counter--for", - Icon { - icon: CircleCheck, - height: 16, - width: 16, - stroke_width: 2, - stroke: "#56C95F" - } + Icon { icon: CircleCheck, height: 16, width: 16, stroke_width: 2, stroke: "#56C95F" } p { class: "votes-counter__total", - "{votes_statistics().aye} " {translate!(i18, "governance.description.voting.votes")} + "{votes_statistics().aye} " + { translate!(i18, + "governance.description.voting.votes") } } } - div { class: "votes-counter votes-counter--against", - Icon { - icon: StopSign, - height: 16, - width: 16, - stroke_width: 2, - stroke: "#f44336bd" - } + Icon { icon: StopSign, height: 16, width: 16, stroke_width: 2, stroke: "#f44336bd" } p { class: "votes-counter__total", - "{votes_statistics().nay} " {translate!(i18, "governance.description.voting.votes")} + "{votes_statistics().nay} " + { translate!(i18, + "governance.description.voting.votes") } } } } - div { - { - let consumed_percent = 100.0 / members() as f64 * votes_statistics().total() as f64; - rsx!( - Bar { - left_value: consumed_percent, - center_value: participation_threshold(), - right_value: 100.0 - consumed_percent, - left_helper: "Participation", - left_title: "{votes_statistics().total()}", - right_title: "{members()}", - } - ) - } + { let consumed_percent = + 100.0 / members() as f64 * votes_statistics().total() as f64; rsx!(Bar { + left_value : consumed_percent, center_value : participation_threshold(), + right_value : 100.0 - consumed_percent, left_helper : "Participation", left_title + : "{votes_statistics().total()}", right_title : "{members()}", }) } } div { class: "note", KeyValue { 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!( - { - let consumed_percent = 100.0 / members() as f64 * votes_statistics().total() as f64; - format!("{:.1}%", consumed_percent) - } + { let consumed_percent = 100.0 / members() as f64 * votes_statistics().total() as + f64; format!("{:.1}%", consumed_percent) } ) } } @@ -563,21 +451,16 @@ pub fn Vote(id: u16, initiativeid: u16) -> Element { } } section { class: "details__proposal", - div { class: "details__subtitle", - "Content" - } + div { class: "details__subtitle", "Content" } div { class: "details__tags", div { class: "card__tags", for tag in initiative_wrapper.clone().info.tags { - Badge { - class: "badge--lavanda-dark", - text: tag - } + Badge { class: "badge--lavanda-dark", text: tag } } } } - - div { class: "details__description markdown-preview", + div { + class: "details__description markdown-preview", dangerous_inner_html: "{html_buf}" } } @@ -588,19 +471,15 @@ pub fn Vote(id: u16, initiativeid: u16) -> Element { } } } - enum Times { Minutes(u32), Hours(u32), Days(u32), } - fn blocks_to_times(blocks: u32) -> Times { let seconds = blocks * 12; let minutes = seconds / 60; - log::info!("minutes {}", minutes); - if minutes / (24 * 60) > 0 { Times::Days(minutes / (24 * 60)) } else if minutes / 60 > 0 { @@ -609,14 +488,11 @@ fn blocks_to_times(blocks: u32) -> Times { Times::Minutes(minutes) } } - fn blocks_to_days(blocks: u32) -> u32 { let seconds = blocks * 12; let minutes = seconds / 60; - minutes / (24 * 60) } - fn calculate_threshold( track_info: &Option, deciding: &Option, @@ -630,33 +506,34 @@ where let Some(deciding) = deciding else { return 100.0; }; - if current_block == 0 { return 100.0; } - let consumed = current_block - deciding.since; let progress = consumed as f64 / 36000.0; - threshold_fn(info, progress) } - fn get_approval_threshold( track_info: &Option, deciding: &Option, current_block: u32, ) -> f64 { - calculate_threshold(track_info, deciding, current_block, |info, progress| { - info.min_approval.calculate_threshold(progress) - }) + calculate_threshold( + track_info, + deciding, + current_block, + |info, progress| { info.min_approval.calculate_threshold(progress) }, + ) } - fn get_participation_threshold( track_info: &Option, deciding: &Option, current_block: u32, ) -> f64 { - calculate_threshold(track_info, deciding, current_block, |info, progress| { - info.min_support.calculate_threshold(progress) - }) + calculate_threshold( + track_info, + deciding, + current_block, + |info, progress| { info.min_support.calculate_threshold(progress) }, + ) } diff --git a/src/services/bot/client.rs b/src/services/bot/client.rs index a596ed5..ba6bae3 100644 --- a/src/services/bot/client.rs +++ b/src/services/bot/client.rs @@ -1,13 +1,12 @@ -use crate::hooks::use_initiative::{InitiativeData, InitiativeHistory, InitiativeVoteData}; - +use crate::hooks::use_initiative::{ + InitiativeData, InitiativeHistory, InitiativeVoteData, +}; use super::types::{CommunityMatrixId, CommunitySpace, Uri}; - #[derive(Clone)] pub struct SpacesClient { base_path: String, client: reqwest::Client, } - impl SpacesClient { pub fn new(base_path: &str) -> Self { Self { @@ -15,7 +14,6 @@ impl SpacesClient { client: reqwest::Client::new(), } } - pub async fn create( &self, community: CommunitySpace, @@ -29,11 +27,12 @@ impl SpacesClient { .await? .json::() .await?; - Ok(response) } - - pub async fn get_by_alias(&self, alias: &str) -> Result { + pub async fn get_by_alias( + &self, + alias: &str, + ) -> Result { let path = format!("{}/room/alias/{}", self.base_path, alias); let response = self .client @@ -42,10 +41,8 @@ impl SpacesClient { .await? .json::() .await?; - Ok(response) } - pub async fn get_by_id(&self, id: &str) -> Result { let path = format!("{}/room/id/{}", self.base_path, id); let response = self @@ -55,21 +52,20 @@ impl SpacesClient { .await? .json::() .await?; - Ok(response) } - - pub async fn upload(&self, content: &[u8], name: &str) -> Result { + pub async fn upload( + &self, + content: &[u8], + name: &str, + ) -> Result { let path = format!("{}/room/upload", self.base_path); let infered_type = infer::get(content).expect("Should infer the content type"); - let part = reqwest::multipart::Part::stream(content.to_vec()) .file_name(name.to_string()) .mime_str(&infered_type.to_string()) .expect("Couldn't set MIME type"); - let form = reqwest::multipart::Form::new().part("file", part); - let response = self .client .post(path) @@ -78,10 +74,8 @@ impl SpacesClient { .await? .json::() .await?; - Ok(response.get()) } - pub async fn create_initiative( &self, initiative: InitiativeData, @@ -95,26 +89,20 @@ impl SpacesClient { .await? .json::() .await?; - Ok(response) } - pub async fn vote_initiative( &self, vote: InitiativeVoteData, ) -> Result<(), reqwest::Error> { let path = format!("{}/initiative/vote", self.base_path); - self - .client - .post(path) - .json(&vote) - .send() - .await?; - + self.client.post(path).json(&vote).send().await?; Ok(()) } - - pub async fn get_initiative_by_id(&self, id: &str) -> Result { + pub async fn get_initiative_by_id( + &self, + id: &str, + ) -> Result { let path = format!("{}/initiative/{}", self.base_path, id); let response = self .client @@ -123,7 +111,6 @@ impl SpacesClient { .await? .json::() .await?; - Ok(response) } } diff --git a/src/services/bot/types.rs b/src/services/bot/types.rs index ff48e90..ffeb262 100644 --- a/src/services/bot/types.rs +++ b/src/services/bot/types.rs @@ -1,5 +1,4 @@ use serde::{Deserialize, Serialize}; - #[derive(Serialize, Deserialize, Debug)] pub struct CommunitySpace { pub name: String, @@ -9,23 +8,19 @@ pub struct CommunitySpace { pub description: Option, pub industry: String, } - #[derive(Deserialize)] pub struct CommunityMatrixId { id: String, } - impl CommunityMatrixId { pub fn get_id(self) -> String { self.id } } - #[derive(Deserialize)] pub struct Uri { uri: String, } - impl Uri { pub fn get(self) -> String { self.uri diff --git a/src/services/kreivo/balances.rs b/src/services/kreivo/balances.rs index 969d4c8..93bd777 100644 --- a/src/services/kreivo/balances.rs +++ b/src/services/kreivo/balances.rs @@ -1,8 +1,6 @@ use serde::Deserialize; use sube::{sube, Response}; - use super::community_track::ChainStateError; - #[derive(Debug, Deserialize)] pub struct AccountInfo { pub nonce: u64, @@ -11,7 +9,6 @@ pub struct AccountInfo { pub sufficients: u64, pub data: AccountData, } - #[derive(Debug, Deserialize)] pub struct AccountData { pub free: u128, @@ -19,22 +16,15 @@ pub struct AccountData { pub frozen: u128, pub flags: u128, } - pub async fn account(account: &str) -> Result { let query = format!("wss://kreivo.io/system/account/{}", account); - log::info!("query: {:#?}", query); - let response = sube!(&query).await.map_err(|_| { - ChainStateError::FailedQuery - })?; - + let response = sube!(& query).await.map_err(|_| { ChainStateError::FailedQuery })?; let Response::Value(value) = response else { return Err(ChainStateError::InternalError); }; - let value = serde_json::to_value(&value).map_err(|_| ChainStateError::FailedDecode)?; - let account_info = - serde_json::from_value::(value).map_err(|_| ChainStateError::FailedDecode)?; - + let account_info = serde_json::from_value::(value) + .map_err(|_| ChainStateError::FailedDecode)?; Ok(account_info) } diff --git a/src/services/kreivo/communities.rs b/src/services/kreivo/communities.rs index d81009a..e37020e 100644 --- a/src/services/kreivo/communities.rs +++ b/src/services/kreivo/communities.rs @@ -1,47 +1,35 @@ use codec::Decode; use serde::Deserialize; use sube::{sube, Response}; - #[derive(Decode, Debug, Deserialize)] pub struct CommunityTracks { pub communities: Vec, } - #[derive(Debug)] pub enum ChainStateError { FailedQuery, InternalError, FailedDecode, } - pub async fn is_admin(address: &[u8]) -> Result { let query = format!("wss://kreivo.io/communities/communityIdFor"); - - let response = sube!(&query) - .await - .map_err(|_| ChainStateError::FailedQuery)?; - + let response = sube!(& query).await.map_err(|_| ChainStateError::FailedQuery)?; let Response::ValueSet(value) = response else { return Err(ChainStateError::InternalError); }; - for d in value.iter() { let Some(value) = d.0.get(0) else { continue; }; - let Ok(value) = serde_json::to_value(&value) else { continue; }; - let Some(system) = value.get("system") else { continue; }; - let Some(signed) = system.get("Signed") else { continue; }; - let Ok(value) = serde_json::to_value(&signed) else { continue; }; @@ -52,6 +40,5 @@ pub async fn is_admin(address: &[u8]) -> Result { return Ok(true); } } - Ok(false) } diff --git a/src/services/kreivo/community_memberships.rs b/src/services/kreivo/community_memberships.rs index b9cca98..f03e464 100644 --- a/src/services/kreivo/community_memberships.rs +++ b/src/services/kreivo/community_memberships.rs @@ -1,11 +1,10 @@ use codec::Decode; use serde::Deserialize; use sube::{sube, Response}; - -use crate::{pages::dashboard::Community, services::kreivo::community_track::ChainStateError}; - +use crate::{ + pages::dashboard::Community, services::kreivo::community_track::ChainStateError, +}; use super::community_track::{tracks, tracksIds}; - #[derive(Decode, Debug, Deserialize)] pub struct CollectionDetails { pub items: u16, @@ -13,135 +12,92 @@ pub struct CollectionDetails { pub attributes: u16, pub owner: Vec, } - pub async fn collection(collection: u16) -> Result { let query = format!( "wss://kreivo.io/communityMemberships/collection/{}", - collection + collection, ); - - let response = sube!(&query) - .await - .map_err(|_| ChainStateError::FailedQuery)?; - + let response = sube!(& query).await.map_err(|_| ChainStateError::FailedQuery)?; let Response::Value(value) = response else { return Err(ChainStateError::InternalError); }; - let value = serde_json::to_value(&value).map_err(|_| ChainStateError::FailedDecode)?; let account_info = serde_json::from_value::(value) .map_err(|_| ChainStateError::FailedDecode)?; - Ok(account_info) } - pub async fn item(item: u16, member: Option) -> Result { let query = format!("wss://kreivo.io/communityMemberships/item/{}", item); - let response = sube!(&query) - .await - .map_err(|_| ChainStateError::FailedQuery)?; - + let response = sube!(& query).await.map_err(|_| ChainStateError::FailedQuery)?; let Response::ValueSet(value) = response else { return Err(ChainStateError::InternalError); }; - Ok(value.len() as u16) } - -pub async fn get_membership_id(address: &str, community_id: u16) -> Result { +pub async fn get_membership_id( + address: &str, + community_id: u16, +) -> Result { let query = format!( "wss://kreivo.io/communityMemberships/account/{}/{}", - address, community_id + address, + community_id, ); - let response = sube!(&query) - .await - .map_err(|_| ChainStateError::FailedQuery)?; - + let response = sube!(& query).await.map_err(|_| ChainStateError::FailedQuery)?; let Response::ValueSet(ref value) = response else { return Err(ChainStateError::InternalError); }; - - // Get the first membership let Some(value) = value.get(0) else { return Err(ChainStateError::InternalError); }; - let value = &value.0; - - // Get the membership id let Some(value) = value.get(2) else { return Err(ChainStateError::InternalError); }; - let Ok(value) = serde_json::to_value(&value) else { return Err(ChainStateError::InternalError); }; - - let membership_id = - serde_json::from_value::(value).map_err(|_| ChainStateError::FailedDecode)?; - + let membership_id = serde_json::from_value::(value) + .map_err(|_| ChainStateError::FailedDecode)?; Ok(membership_id) } - pub async fn get_owned_memberships(address: &str) -> Result { let query = format!("wss://kreivo.io/communityMemberships/account/{}", address); - let response = sube!(&query) - .await - .map_err(|_| ChainStateError::FailedQuery)?; - + let response = sube!(& query).await.map_err(|_| ChainStateError::FailedQuery)?; let Response::ValueSet(ref value) = response else { return Err(ChainStateError::InternalError); }; - - // // Get the first membership - // let Some(value) = value.get(0) else { - // return Err(ChainStateError::InternalError); - // }; - - // let value = &value.0; - - // // Get the membership id - // let Some(value) = value.get(2) else { - // return Err(ChainStateError::InternalError); - // }; - - // let Ok(value) = serde_json::to_value(&value) else { - // return Err(ChainStateError::InternalError); - // }; - - // let membership_id = - // serde_json::from_value::(value).map_err(|_| ChainStateError::FailedDecode)?; - Ok(value.len() as u16) } - -pub async fn get_communities_by_member(member: &[u8]) -> Result, ChainStateError> { +pub async fn get_communities_by_member( + member: &[u8], +) -> Result, ChainStateError> { let mut communities = vec![]; - let address = format!("0x{}", hex::encode(member)); log::info!("address: {address}, member {member:?}"); - let community_trackIds = tracksIds().await.map_err(|e| { - log::warn!("error: {:?}", e); - ChainStateError::FailedQuery - })?; - + let community_trackIds = tracksIds() + .await + .map_err(|e| { + log::warn!("error: {:?}", e); + ChainStateError::FailedQuery + })?; for community in community_trackIds.communities.iter() { log::info!("address: {address}, community {community}"); let query = format!( "wss://kreivo.io/communityMemberships/account/{}/{}", - address, community + address, + community, ); - - let response = sube!(&query).await.map_err(|e| { - log::warn!("error: {:?}", e); - ChainStateError::FailedQuery - })?; - + let response = sube!(& query) + .await + .map_err(|e| { + log::warn!("error: {:?}", e); + ChainStateError::FailedQuery + })?; log::info!("{:?}", response); let Response::ValueSet(value) = response else { continue; }; - if value.len() > 0 { let response_track = tracks(*community).await; log::info!("{:?}", response_track); @@ -149,7 +105,6 @@ pub async fn get_communities_by_member(member: &[u8]) -> Result, log::info!("{:?}", response_collection); let response_item = item(*community, None).await; log::info!("{:?}", response_item); - let collection_items = match response_collection { Ok(ref collection) => { let address = format!("0x{}", hex::encode(collection.owner.clone())); @@ -157,25 +112,20 @@ pub async fn get_communities_by_member(member: &[u8]) -> Result, } Err(_) => 0u16, }; - let Ok(track_info) = response_track else { continue; }; - let filtered_name = track_info .name .iter() .filter(|b| **b != 0) .cloned() .collect::>(); - let filtered_name: &[u8] = &filtered_name; - let item_details = match response_item { Ok(items) => items, Err(_) => 0u16, }; - let community = Community { id: *community, icon: None, @@ -185,10 +135,8 @@ pub async fn get_communities_by_member(member: &[u8]) -> Result, memberships: collection_items, members: item_details, }; - communities.push(community) } } - Ok(communities) } diff --git a/src/services/kreivo/community_referenda.rs b/src/services/kreivo/community_referenda.rs index 645ccbc..fd7ad5a 100644 --- a/src/services/kreivo/community_referenda.rs +++ b/src/services/kreivo/community_referenda.rs @@ -1,87 +1,63 @@ use serde::{Deserialize, Serialize}; use serde_json::{from_value, Value}; use sube::{sube, Response}; - use crate::services::kreivo::community_track::ChainStateError; - #[derive(Debug, Deserialize)] pub struct TrackInfo { pub id: u32, pub count: u32, } - pub async fn track_queue(item: u16) -> Result, ChainStateError> { - let query = format!( - "wss://kreivo.io/communityReferenda/trackQueue/{}", - item - ); - let response = sube!(&query) - .await - .map_err(|_| ChainStateError::FailedQuery)?; - + let query = format!("wss://kreivo.io/communityReferenda/trackQueue/{}", item); + let response = sube!(& query).await.map_err(|_| ChainStateError::FailedQuery)?; let Response::Value(ref value) = response else { return Err(ChainStateError::InternalError); }; - let Ok(value) = serde_json::to_value(&value) else { return Err(ChainStateError::InternalError); }; - let Value::Array(track_infos) = value else { return Err(ChainStateError::InternalError); }; - let track_infos: Vec = track_infos .into_iter() .map(|item| from_value(item).expect("invalid format for track info")) .collect(); - Ok(track_infos) } - pub async fn referendum_count() -> Result { let query = format!("wss://kreivo.io/communityReferenda/referendumCount"); - let response = sube!(&query) - .await - .map_err(|_| ChainStateError::FailedQuery)?; - + let response = sube!(& query).await.map_err(|_| ChainStateError::FailedQuery)?; let Response::Value(ref value) = response else { return Err(ChainStateError::InternalError); }; - let Ok(value) = serde_json::to_value(&value) else { return Err(ChainStateError::InternalError); }; - - let count = serde_json::from_value::(value).map_err(|_| ChainStateError::FailedDecode)?; - + let count = serde_json::from_value::(value) + .map_err(|_| ChainStateError::FailedDecode)?; Ok(count) } - #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Origin { #[serde(rename = "Communities")] pub communities: Communities, } - #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Communities { #[serde(rename = "community_id")] pub community_id: u16, pub subset: Option, } - #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Deposit { pub who: Vec, pub amount: u64, } - #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Deciding { pub since: u32, } - #[derive(Clone, Copy, Debug, Deserialize, Serialize)] pub struct Tally { pub ayes: u64, @@ -89,14 +65,12 @@ pub struct Tally { #[serde(rename = "bare_ayes")] pub bare_ayes: u64, } - #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(untagged)] pub enum Alarm { Single(u32), Multiple(Vec), } - #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Ongoing { pub track: u32, @@ -108,60 +82,40 @@ pub struct Ongoing { pub tally: Tally, pub alarm: Option>, } - #[derive(Clone, Debug, Deserialize, Serialize)] pub struct OngoingWrapper { #[serde(rename = "Ongoing")] pub ongoing: Ongoing, } - pub async fn referendum_info_for(id: u16) -> Result { - let query = format!( - "wss://kreivo.io/communityReferenda/referendumInfoFor/{}", - id - ); - let response = sube!(&query) - .await - .map_err(|_| ChainStateError::FailedQuery)?; - + let query = format!("wss://kreivo.io/communityReferenda/referendumInfoFor/{}", id); + let response = sube!(& query).await.map_err(|_| ChainStateError::FailedQuery)?; let Response::Value(ref value) = response else { return Err(ChainStateError::InternalError); }; - let Ok(value) = serde_json::to_value(&value) else { return Err(ChainStateError::InternalError); }; - let initiative = serde_json::from_value::(value) .map_err(|_| ChainStateError::FailedDecode)?; - Ok(initiative) } - pub async fn metadata_of(id: u16) -> Result, ChainStateError> { let query = format!("wss://kreivo.io/communityReferenda/metadataOf/{}", id); - let response = sube!(&query) - .await - .map_err(|_| ChainStateError::FailedQuery)?; - + let response = sube!(& query).await.map_err(|_| ChainStateError::FailedQuery)?; let Response::Value(ref value) = response else { return Err(ChainStateError::InternalError); }; - let Ok(value) = serde_json::to_value(&value) else { return Err(ChainStateError::InternalError); }; - - let preimage_hash = - serde_json::from_value::>(value).map_err(|_| ChainStateError::FailedDecode)?; - + let preimage_hash = serde_json::from_value::>(value) + .map_err(|_| ChainStateError::FailedDecode)?; Ok(preimage_hash) } - pub async fn get_initiatives_by_community( track_id: u16, ) -> Result, ChainStateError> { let track_infos = track_queue(track_id).await?; - Ok(track_infos) } diff --git a/src/services/kreivo/community_track.rs b/src/services/kreivo/community_track.rs index 994598e..7421978 100644 --- a/src/services/kreivo/community_track.rs +++ b/src/services/kreivo/community_track.rs @@ -1,81 +1,52 @@ use codec::Decode; use serde::Deserialize; use sube::{sube, Response}; - #[derive(Decode, Debug, Deserialize)] pub struct CommunityTracks { pub communities: Vec, } - #[derive(Debug)] pub enum ChainStateError { FailedQuery, InternalError, FailedDecode, } - pub async fn tracksIds() -> Result { let query = format!("wss://kreivo.io/communityTracks/tracksIds"); - - let response = sube!(&query) + let response = sube!(& query) .await .map_err(|e| { log::warn!("{:?}", e); ChainStateError::FailedQuery - } )?; - + })?; log::info!("{:?}", response); - let Response::Value(value) = response else { return Err(ChainStateError::InternalError); }; - let data = value.as_ref(); - let account_info = - CommunityTracks::decode(&mut &data[..]).map_err(|e| { + let account_info = CommunityTracks::decode(&mut &data[..]) + .map_err(|e| { log::warn!("{:?}", e); ChainStateError::FailedDecode })?; - Ok(account_info) } - const DEFAULT_MAX_TRACK_NAME_LEN: usize = 25; const N: usize = DEFAULT_MAX_TRACK_NAME_LEN; - #[derive(Debug, Deserialize)] #[serde(rename_all = "PascalCase")] pub enum Curve { - LinearDecreasing { - ceil: u64, - floor: u64, - length: u64, - }, - SteppedDecreasing { - begin: u64, - end: u64, - step: u64, - period: u64, - }, - Reciprocal { - factor: i64, - x_offset: i64, - y_offset: i64, - }, + LinearDecreasing { ceil: u64, floor: u64, length: u64 }, + SteppedDecreasing { begin: u64, end: u64, step: u64, period: u64 }, + Reciprocal { factor: i64, x_offset: i64, y_offset: i64 }, } - impl Curve { pub fn calculate_threshold(&self, progress: f64) -> f64 { match self { - Curve::LinearDecreasing { - ceil, - floor, - length, - } => { + Curve::LinearDecreasing { ceil, floor, length } => { let length = *length as f64 / 10_000_000.0; let ceil = *ceil as f64 / 10_000_000.0; let floor = *floor as f64 / 10_000_000.0; - let progress = progress / (length / 100.0); ceil - progress * (ceil - floor) } @@ -83,7 +54,6 @@ impl Curve { } } } - #[derive(Debug, Deserialize)] pub struct TrackInfo { pub name: [u8; N], @@ -94,25 +64,21 @@ pub struct TrackInfo { #[serde(rename = "min_support")] pub min_support: Curve, } - pub async fn tracks(track: u16) -> Result { let query = format!("wss://kreivo.io/communityTracks/tracks/{}", track); - - let response = sube!(&query).await.map_err(|e| { - log::info!("{}", e); - ChainStateError::FailedQuery - })?; - + let response = sube!(& query) + .await + .map_err(|e| { + log::info!("{}", e); + ChainStateError::FailedQuery + })?; let Response::Value(value) = response else { return Err(ChainStateError::InternalError); }; - let Ok(value) = serde_json::to_value(&value) else { return Err(ChainStateError::InternalError); }; - - let account_info = - serde_json::from_value::(value).map_err(|_| ChainStateError::FailedDecode)?; - + let account_info = serde_json::from_value::(value) + .map_err(|_| ChainStateError::FailedDecode)?; Ok(account_info) } diff --git a/src/services/kreivo/identity.rs b/src/services/kreivo/identity.rs index 78021ad..3669ab6 100644 --- a/src/services/kreivo/identity.rs +++ b/src/services/kreivo/identity.rs @@ -1,51 +1,44 @@ use serde::Deserialize; use sube::{sube, Response}; - use super::community_track::ChainStateError; - #[derive(Debug, Deserialize)] pub struct Invitation { pub address: Vec, pub raw: Raw, } - #[derive(Debug, Deserialize)] struct Raw { #[serde(rename = "Raw6")] pub raw6: Vec, } - pub async fn superOf(account: &str) -> Result { - let query = format!("wss://people-kusama-rpc.dwellir.com/identity/superOf/0x6d6f646c6b762f636d7479730200000000000000000000000000000000000000"); - - let response = sube!(&query).await.map_err(|e| { - log::info!("{:?}", e); - ChainStateError::FailedQuery - })?; - + let query = format!( + "wss://people-kusama-rpc.dwellir.com/identity/superOf/0x6d6f646c6b762f636d7479730200000000000000000000000000000000000000", + ); + let response = sube!(& query) + .await + .map_err(|e| { + log::info!("{:?}", e); + ChainStateError::FailedQuery + })?; let Response::Value(value) = response else { return Err(ChainStateError::InternalError); }; - let value = serde_json::to_value(&value).expect("it must be a serialized object"); log::info!("super of: {:?}", value); - let account_info = - serde_json::from_value::(value).map_err(|_| ChainStateError::FailedDecode)?; - + let account_info = serde_json::from_value::(value) + .map_err(|_| ChainStateError::FailedDecode)?; Ok(account_info) } - pub async fn identityOf(account: &str) -> Result { - let query = format!("wss://people-kusama-rpc.dwellir.com/identity/identityOf/{}", account); - - let response = sube!(&query) - .await - .map_err(|_| ChainStateError::FailedQuery)?; - + let query = format!( + "wss://people-kusama-rpc.dwellir.com/identity/identityOf/{}", + account, + ); + let response = sube!(& query).await.map_err(|_| ChainStateError::FailedQuery)?; let Response::Value(value) = response else { return Err(ChainStateError::InternalError); }; - let value = serde_json::to_value(&value).expect("it must be a serialized object"); let account_info = value .get(0) @@ -54,25 +47,17 @@ pub async fn identityOf(account: &str) -> Result { .ok_or(ChainStateError::FailedDecode)? .get("web") .ok_or(ChainStateError::FailedDecode)?; - log::info!("{:?}", account_info); - - // Convertir el valor "web" a un string JSON let raw_value = value.get("Raw30").expect("Expected Raw19 key"); - if let Some(array) = raw_value.as_array() { - // Convertir el array de nĂºmeros en un string let result: String = array .iter() .filter_map(|v| v.as_u64()) .map(|v| v as u8 as char) .collect(); - log::info!("{}", result); } - - let account_info = - serde_json::from_value(account_info.clone()).map_err(|_| ChainStateError::FailedDecode)?; - + let account_info = serde_json::from_value(account_info.clone()) + .map_err(|_| ChainStateError::FailedDecode)?; Ok(account_info) } diff --git a/src/services/kreivo/preimage.rs b/src/services/kreivo/preimage.rs index 42a09b8..df1a742 100644 --- a/src/services/kreivo/preimage.rs +++ b/src/services/kreivo/preimage.rs @@ -1,50 +1,32 @@ use sube::{sube, Response}; - use crate::services::kreivo::community_track::ChainStateError; - pub async fn preimage_for(hash: &str, len: u32) -> Result { let query = format!("wss://kreivo.io/preimage/preimageFor/{}/{}", hash, len); - let response = sube!(&query) - .await - .map_err(|_| ChainStateError::FailedQuery)?; - + let response = sube!(& query).await.map_err(|_| ChainStateError::FailedQuery)?; let Response::Value(ref value) = response else { return Err(ChainStateError::InternalError); }; - let Ok(value) = serde_json::to_value(&value) else { return Err(ChainStateError::InternalError); }; - - let response = - serde_json::from_value::>(value).map_err(|_| ChainStateError::FailedDecode)?; - - let room_id = String::from_utf8(response).map_err(|_| ChainStateError::FailedDecode)?; - + let response = serde_json::from_value::>(value) + .map_err(|_| ChainStateError::FailedDecode)?; + let room_id = String::from_utf8(response) + .map_err(|_| ChainStateError::FailedDecode)?; Ok(room_id) } - pub async fn request_status_for(hash: &str) -> Result { let query = format!("wss://kreivo.io/preimage/requestStatusFor/{}", hash); - let response = sube!(&query) - .await - .map_err(|_| ChainStateError::FailedQuery)?; - + let response = sube!(& query).await.map_err(|_| ChainStateError::FailedQuery)?; let Response::Value(ref value) = response else { return Err(ChainStateError::InternalError); }; - let Ok(value) = serde_json::to_value(&value) else { return Err(ChainStateError::InternalError); }; - - let response = value - .get("Unrequested") - .ok_or(ChainStateError::FailedDecode)?; + let response = value.get("Unrequested").ok_or(ChainStateError::FailedDecode)?; let len = response.get("len").ok_or(ChainStateError::FailedDecode)?; - - let len = - serde_json::from_value::(len.clone()).map_err(|_| ChainStateError::FailedDecode)?; - + let len = serde_json::from_value::(len.clone()) + .map_err(|_| ChainStateError::FailedDecode)?; Ok(len) } diff --git a/src/services/kreivo/system.rs b/src/services/kreivo/system.rs index 41309b0..7512662 100644 --- a/src/services/kreivo/system.rs +++ b/src/services/kreivo/system.rs @@ -1,21 +1,13 @@ use sube::{sube, Response}; - use crate::services::kreivo::communities::ChainStateError; - pub async fn number() -> Result { let query = format!("wss://kreivo.io/system/number"); - - let response = sube!(&query) - .await - .map_err(|_| ChainStateError::FailedQuery)?; - + let response = sube!(& query).await.map_err(|_| ChainStateError::FailedQuery)?; let Response::Value(value) = response else { return Err(ChainStateError::InternalError); }; - let value = serde_json::to_value(&value).map_err(|_| ChainStateError::FailedDecode)?; - let number = - serde_json::from_value::(value).map_err(|_| ChainStateError::FailedDecode)?; - + let number = serde_json::from_value::(value) + .map_err(|_| ChainStateError::FailedDecode)?; Ok(number) } diff --git a/src/services/kreivo/timestamp.rs b/src/services/kreivo/timestamp.rs index b346ae2..8dcecfc 100644 --- a/src/services/kreivo/timestamp.rs +++ b/src/services/kreivo/timestamp.rs @@ -1,22 +1,14 @@ use serde::Deserialize; use sube::{sube, Response}; - use super::community_track::ChainStateError; - pub async fn now() -> Result { let query = format!("wss://kreivo.io/timestamp/now"); - - let response = sube!(&query) - .await - .map_err(|_| ChainStateError::FailedQuery)?; - + let response = sube!(& query).await.map_err(|_| ChainStateError::FailedQuery)?; let Response::Value(value) = response else { return Err(ChainStateError::InternalError); }; - let value = serde_json::to_value(&value).map_err(|_| ChainStateError::FailedDecode)?; - let timestamp = - serde_json::from_value::(value).map_err(|_| ChainStateError::FailedDecode)?; - + let timestamp = serde_json::from_value::(value) + .map_err(|_| ChainStateError::FailedDecode)?; Ok(timestamp) } diff --git a/src/services/kusama/system.rs b/src/services/kusama/system.rs index dcdf134..17acc44 100644 --- a/src/services/kusama/system.rs +++ b/src/services/kusama/system.rs @@ -1,21 +1,13 @@ use sube::{sube, Response}; - use crate::services::kreivo::communities::ChainStateError; - pub async fn number() -> Result { let query = format!("wss://kusama-rpc.dwellir.com/system/number"); - - let response = sube!(&query) - .await - .map_err(|_| ChainStateError::FailedQuery)?; - + let response = sube!(& query).await.map_err(|_| ChainStateError::FailedQuery)?; let Response::Value(value) = response else { return Err(ChainStateError::InternalError); }; - let value = serde_json::to_value(&value).map_err(|_| ChainStateError::FailedDecode)?; - let number = - serde_json::from_value::(value).map_err(|_| ChainStateError::FailedDecode)?; - + let number = serde_json::from_value::(value) + .map_err(|_| ChainStateError::FailedDecode)?; Ok(number) } diff --git a/src/services/kusama/timestamp.rs b/src/services/kusama/timestamp.rs index 409031e..f551da4 100644 --- a/src/services/kusama/timestamp.rs +++ b/src/services/kusama/timestamp.rs @@ -1,21 +1,13 @@ use sube::{sube, Response}; - use crate::services::kreivo::communities::ChainStateError; - pub async fn now() -> Result { let query = format!("wss://kusama-rpc.dwellir.com/timestamp/now"); - - let response = sube!(&query) - .await - .map_err(|_| ChainStateError::FailedQuery)?; - + let response = sube!(& query).await.map_err(|_| ChainStateError::FailedQuery)?; let Response::Value(value) = response else { return Err(ChainStateError::InternalError); }; - let value = serde_json::to_value(&value).map_err(|_| ChainStateError::FailedDecode)?; - let number = - serde_json::from_value::(value).map_err(|_| ChainStateError::FailedDecode)?; - + let number = serde_json::from_value::(value) + .map_err(|_| ChainStateError::FailedDecode)?; Ok(number) }