From ae372627174f9cb648f52dc1c9234aa123aa263a Mon Sep 17 00:00:00 2001 From: b-avb Date: Tue, 22 Oct 2024 13:18:56 -0500 Subject: [PATCH 1/4] fix: rehydrate tags --- src/components/atoms/input_tags.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/components/atoms/input_tags.rs b/src/components/atoms/input_tags.rs index 497ebcc..2f97402 100644 --- a/src/components/atoms/input_tags.rs +++ b/src/components/atoms/input_tags.rs @@ -1,7 +1,7 @@ -use dioxus::prelude::*; +use super::dropdown::ElementSize; use crate::components::atoms::icons::Close; use crate::components::atoms::{Icon, IconButton, WarningSign}; -use super::dropdown::ElementSize; +use dioxus::prelude::*; #[derive(PartialEq, Props, Clone)] pub struct InputTagsEvent { pub tags: Vec, @@ -36,7 +36,17 @@ pub fn InputTags(props: InputTagsProps) -> Element { }; let is_active = use_signal::(|| false); - let mut tags = use_signal::>(|| vec![]); + let mut tags = use_signal::>(|| { + if props.message.len() > 0 { + props + .message + .split(",") + .map(|e| String::from(e)) + .collect::>() + } else { + 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()); From 092bed875e926b37f70611df9f6cdbdf89a2ef34 Mon Sep 17 00:00:00 2001 From: b-avb Date: Tue, 22 Oct 2024 17:39:23 -0500 Subject: [PATCH 2/4] change: add context errors for inputs --- src/components/atoms/combo_input.rs | 24 +- src/components/molecules/actions/members.rs | 17 +- src/components/molecules/actions/transfer.rs | 17 +- src/components/molecules/actions/treasury.rs | 21 +- src/components/molecules/actions/voting.rs | 27 +- src/hooks/use_initiative.rs | 287 ++++++++++++++++++- src/pages/initiative.rs | 184 +----------- 7 files changed, 361 insertions(+), 216 deletions(-) diff --git a/src/components/atoms/combo_input.rs b/src/components/atoms/combo_input.rs index c2c3b98..b8d8070 100644 --- a/src/components/atoms/combo_input.rs +++ b/src/components/atoms/combo_input.rs @@ -1,9 +1,7 @@ +use super::dropdown::ElementSize; +use crate::components::atoms::{dropdown::DropdownItem, input::InputType, Dropdown, Input}; use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; -use crate::components::atoms::{ - dropdown::DropdownItem, input::InputType, Dropdown, Input, -}; -use super::dropdown::ElementSize; #[derive(PartialEq, Clone, Debug)] pub enum ComboInputOption { Dropdown(DropdownItem), @@ -34,16 +32,12 @@ pub fn ComboInput(props: ComboInputProps) -> Element { 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::< - Vec, - >(|| { + let dropdown_options = use_signal::>(|| { 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 }); @@ -61,7 +55,7 @@ pub fn ComboInput(props: ComboInputProps) -> Element { size: props.size.clone(), itype: InputType::Date, placeholder: props.placeholder.clone(), - error: None, + error: props.error.clone(), 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() }) @@ -93,7 +87,7 @@ pub fn ComboInput(props: ComboInputProps) -> Element { message: props.value.input.clone(), size: props.size, placeholder: props.placeholder, - error: None, + error: props.error, right_text: props.right_text, on_input: move |event: Event| { input_value.set(event.value().clone()); diff --git a/src/components/molecules/actions/members.rs b/src/components/molecules/actions/members.rs index 593fe50..d95f586 100644 --- a/src/components/molecules/actions/members.rs +++ b/src/components/molecules/actions/members.rs @@ -1,15 +1,18 @@ -use dioxus::prelude::*; -use dioxus_std::{i18n::use_i18, translate}; +use std::str::FromStr; + 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, }, }; +use dioxus::prelude::*; +use dioxus_std::{i18n::use_i18, translate}; #[derive(PartialEq, Props, Clone)] pub struct VotingProps { index: usize, @@ -27,7 +30,7 @@ pub fn MembersAction(props: VotingProps) -> Element { }, value: match member.medium.clone() { MediumOptions::Wallet => translate!(i18, "onboard.invite.form.wallet.label"), } }; - + rsx!( li { ComboInput { @@ -39,6 +42,12 @@ pub fn MembersAction(props: VotingProps) -> Element { placeholder: match member.medium { MediumOptions::Wallet => translate!(i18, "onboard.invite.form.wallet.placeholder"), }, + error: { + match sp_core::sr25519::Public::from_str(&member.account) { + Ok(_) => None, + Err(_) => Some("Invalid Address".to_string()) + } + }, on_change: move |event: ComboInputValue| { let medium = match event.option { ComboInputOption::Dropdown(value) => { diff --git a/src/components/molecules/actions/transfer.rs b/src/components/molecules/actions/transfer.rs index 8b837fd..86a544e 100644 --- a/src/components/molecules/actions/transfer.rs +++ b/src/components/molecules/actions/transfer.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + use crate::{ components::atoms::{ dropdown::ElementSize, icon_button::Variant, AddPlus, Icon, IconButton, @@ -32,7 +34,12 @@ pub fn TransferAction(props: VotingProps) -> Element { message: transfer.account.clone(), size: ElementSize::Small, placeholder: translate!(i18, "initiative.steps.actions.community_transfer.dest.placeholder"), - error: None, + error: { + match sp_core::sr25519::Public::from_str(&transfer.account) { + Ok(_) => None, + Err(_) => Some("Invalid Address".to_string()) + } + }, on_input: move |event: Event| { if let ActionItem::CommunityTransfer(ref mut meta) = initiative.get_action(props.index) { meta.transfers[index_meta].account = event.value() ; @@ -46,7 +53,13 @@ pub fn TransferAction(props: VotingProps) -> Element { message: (transfer.value / KUSAMA_PRECISION_DECIMALS).to_string(), size: ElementSize::Small, placeholder: translate!(i18, "initiative.steps.actions.community_transfer.amount.placeholder"), - error: None, + error: { + if transfer.value > 0 { + None + } else { + Some("Amount should be greater than 0".to_string()) + } + }, right_text: { rsx!( span { class: "input--right__text", diff --git a/src/components/molecules/actions/treasury.rs b/src/components/molecules/actions/treasury.rs index a3144d5..4774f4e 100644 --- a/src/components/molecules/actions/treasury.rs +++ b/src/components/molecules/actions/treasury.rs @@ -1,15 +1,14 @@ -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, - }, - hooks::use_initiative::{ - use_initiative, ActionItem, KusamaTreasury, KusamaTreasuryAction, + icon_button::Variant, + input::InputType, + AddPlus, Icon, IconButton, Input, MinusCircle, }, + hooks::use_initiative::{use_initiative, ActionItem, KusamaTreasury, KusamaTreasuryAction}, }; +use dioxus::prelude::*; +use dioxus_std::{i18n::use_i18, translate}; #[derive(PartialEq, Props, Clone)] pub struct VotingProps { index: usize, @@ -62,7 +61,13 @@ pub fn TreasuryAction(props: VotingProps) -> Element { message: (period.amount / KUSAMA_PRECISION_DECIMALS).to_string(), size: ElementSize::Small, placeholder: translate!(i18, "initiative.steps.actions.kusama_treasury.placeholder"), - error: None, + error: { + if period.amount > 0 { + None + } else { + Some("Amount should be greater than 0".to_string()) + } + }, right_text: { rsx!( span { class: "input--right__text", diff --git a/src/components/molecules/actions/voting.rs b/src/components/molecules/actions/voting.rs index a357ebd..15582da 100644 --- a/src/components/molecules/actions/voting.rs +++ b/src/components/molecules/actions/voting.rs @@ -1,17 +1,17 @@ -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, }, }; +use dioxus::prelude::*; +use dioxus_std::{i18n::use_i18, translate}; #[derive(PartialEq, Props, Clone)] pub struct VotingProps { index: usize, @@ -33,7 +33,13 @@ pub fn VotingAction(props: VotingProps) -> Element { message: if proposal.poll_index > 0 { proposal.poll_index.to_string() } else { String::new() }, size: ElementSize::Small, placeholder: "Ex: 000", - error: None, + error: { + if proposal.poll_index > 0 { + None + } else { + Some("Poll index should be greater than 0".to_string()) + } + }, 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) { @@ -64,6 +70,13 @@ pub fn VotingAction(props: VotingProps) -> Element { }), input: if vote.balance / KUSAMA_PRECISION_DECIMALS > 0 { (vote.balance / KUSAMA_PRECISION_DECIMALS).to_string() } else { String::new() }, }, + error: { + if vote.balance > 0 { + None + } else { + Some("Amount should be greater than 0".to_string()) + } + }, placeholder: translate!(i18, "initiative.steps.actions.voting_open_gov.standard.balance"), right_text: { rsx!( diff --git a/src/hooks/use_initiative.rs b/src/hooks/use_initiative.rs index 1e00679..86e3f1f 100644 --- a/src/hooks/use_initiative.rs +++ b/src/hooks/use_initiative.rs @@ -1,6 +1,10 @@ +use std::str::FromStr; + use crate::components::atoms::dropdown::DropdownItem; +use chrono::{DateTime, NaiveDate, NaiveDateTime, Utc}; use dioxus::prelude::*; use serde::{Deserialize, Serialize}; +const BLOCK_TIME_IN_SECONDS: i64 = 6; #[derive(Clone, Default, Deserialize, Serialize, Debug)] pub struct InfoForm { pub name: String, @@ -157,7 +161,7 @@ impl VotingOpenGovAction { #[derive(PartialEq, Clone, Default, Deserialize, Serialize, Debug)] pub struct TransferItem { pub account: String, - pub value: u64 + pub value: u64, } pub type Transfers = Vec; #[derive(PartialEq, Clone, Debug, Deserialize, Serialize, Default)] @@ -217,7 +221,9 @@ impl ActionItem { "AddMembers" => ActionItem::AddMembers(AddMembersAction::default()), "KusamaTreasury" => ActionItem::KusamaTreasury(KusamaTreasuryAction::default()), "VotingOpenGov" => ActionItem::VotingOpenGov(VotingOpenGovAction::default()), - "CommunityTransfer" => ActionItem::CommunityTransfer(CommunityTransferAction::default()), + "CommunityTransfer" => { + ActionItem::CommunityTransfer(CommunityTransferAction::default()) + } _ => todo!(), } } @@ -301,11 +307,11 @@ pub fn use_initiative() -> UseInitiativeState { }, }) } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub struct UseInitiativeState { inner: UseInitiativeInner, } -#[derive(Clone, Copy, Default)] +#[derive(Clone, Copy, Default, Debug)] pub struct UseInitiativeInner { info: Signal, actions: Signal, @@ -381,4 +387,277 @@ impl UseInitiativeState { pub fn default(&mut self) { self.inner = UseInitiativeInner::default(); } + pub fn filter_valid_address_add_members(&self) -> Vec { + let add_members_action = self + .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() { + match sp_core::sr25519::Public::from_str(&member.account) { + Ok(_) => Some(member.account), + Err(_) => None, + } + } else { + None + } + }) + .collect::>(), + ), + _ => None, + }) + .collect::>>(); + add_members_action + .into_iter() + .flat_map(|v| v.into_iter()) + .collect::>() + } + pub fn check_add_members(&self) -> bool { + let count = self + .get_actions() + .into_iter() + .filter_map(|action| match action { + ActionItem::AddMembers(add_members_action) => { + Some(add_members_action.members.len()) + } + _ => None, + }) + .reduce(|a, b| a + b); + + let Some(count) = count else { return true }; + + let has_add_members_actions = self + .get_actions() + .iter() + .any(|action| matches!(action, ActionItem::AddMembers(_))); + + self.filter_valid_address_add_members().len() == count + && (has_add_members_actions && count > 0) + } + pub fn filter_valid_treasury(&self) -> Vec { + let treasury_action = self + .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(period) + } else { + None + } + }) + .collect::>(), + ), + _ => None, + }) + .collect::>>(); + treasury_action + .into_iter() + .flat_map(|v| v.into_iter()) + .collect::>() + } + pub fn convert_treasury_to_period( + &self, + current_block: u32, + now_kusama: u64, + ) -> Vec { + self.filter_valid_treasury() + .into_iter() + .map(|period| convert_treasury_to_period(period, current_block, now_kusama)) + .collect::>() + } + pub fn check_treasury(&self) -> bool { + let count = self + .get_actions() + .into_iter() + .filter_map(|action| match action { + ActionItem::KusamaTreasury(period) => Some(period.periods.len()), + _ => None, + }) + .reduce(|a, b| a + b); + + let Some(count) = count else { return true }; + + let has_treasury_actions = self + .get_actions() + .iter() + .any(|action| matches!(action, ActionItem::KusamaTreasury(_))); + + self.filter_valid_treasury().len() == count && (has_treasury_actions && count > 0) + } + pub fn filter_valid_voting_open_gov(&self) -> Vec { + let votiong_open_gov_action = self + .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 { + match &proposal.vote { + VoteType::Standard(standard_vote) => { + if standard_vote.balance > 0 { + Some(proposal) + } else { + None + } + } + } + } else { + None + } + }) + .collect::>(), + ), + _ => None, + }) + .collect::>>(); + votiong_open_gov_action + .into_iter() + .flat_map(|v| v.into_iter()) + .collect::>() + } + pub fn check_voting_open_gov(&self) -> bool { + let count = self + .get_actions() + .into_iter() + .filter_map(|action| match action { + ActionItem::VotingOpenGov(votiong_open_gov_action) => { + Some(votiong_open_gov_action.proposals.len()) + } + _ => None, + }) + .reduce(|a, b| a + b); + + let Some(count) = count else { return true }; + + let has_voting_open_gov_actions = self + .get_actions() + .iter() + .any(|action| matches!(action, ActionItem::VotingOpenGov(_))); + + self.filter_valid_voting_open_gov().len() == count + && (has_voting_open_gov_actions && count > 0) + } + pub fn filter_valid_community_transfer(&self) -> Vec { + let community_transfer_action = self + .get_actions() + .into_iter() + .filter_map(|action| match action { + ActionItem::CommunityTransfer(community_transfer_action) => Some( + community_transfer_action + .transfers + .clone() + .into_iter() + .filter_map(|transfer| { + if transfer.value > 0 { + match sp_core::sr25519::Public::from_str(&transfer.account) { + Ok(_) => Some(transfer), + Err(_) => None, + } + } else { + None + } + }) + .collect::>(), + ), + _ => None, + }) + .collect::>>(); + community_transfer_action + .into_iter() + .flat_map(|v| v.into_iter()) + .collect::>() + } + pub fn check_community_transfer(&self) -> bool { + let count = self + .get_actions() + .into_iter() + .filter_map(|action| match action { + ActionItem::CommunityTransfer(community_transfer_action) => { + Some(community_transfer_action.transfers.len()) + } + _ => None, + }) + .reduce(|a, b| a + b); + + let Some(count) = count else { return true }; + + let has_community_transfer_actions = self + .get_actions() + .iter() + .any(|action| matches!(action, ActionItem::CommunityTransfer(_))); + + self.filter_valid_community_transfer().len() == count + && (has_community_transfer_actions && count > 0) + } + pub fn check(&self) -> bool { + log::info!("{} {}", self.check_add_members(), self.check_treasury()); + (self.check_add_members() + && self.check_treasury() + && self.check_voting_open_gov() + && self.check_community_transfer()) + && (self.filter_valid_address_add_members().len() > 0 + || self.filter_valid_treasury().len() > 0 + || self.filter_valid_voting_open_gov().len() > 0 + || self.filter_valid_community_transfer().len() > 0) + } +} + +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); + KusamaTreasuryPeriod { + blocks: Some(future_block as u64), + amount: treasury.amount, + } + } else { + KusamaTreasuryPeriod { + blocks: None, + amount: treasury.amount, + } + } +} + +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("Invalid future date"); + let future = future_date_naive + .and_hms_opt(0, 0, 0) + .expect("Invalid future date"); + let future_date = DateTime::::from_naive_utc_and_offset(future, Utc); + + let x = DateTime::from_timestamp( + (current_date_millis / 1000).try_into().unwrap(), + ((current_date_millis % 1000) * 1_000_000) as u32, + ) + .expect(""); + + let x = NaiveDateTime::from_str(&x.date_naive().to_string()).expect("Invalid calculated date"); + let current_date = DateTime::from_naive_utc_and_offset(x, 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() } diff --git a/src/pages/initiative.rs b/src/pages/initiative.rs index 244acfa..b12e190 100644 --- a/src/pages/initiative.rs +++ b/src/pages/initiative.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use crate::{ components::{ atoms::{ @@ -9,16 +7,7 @@ use crate::{ molecules::{InitiativeActions, InitiativeInfo}, }, hooks::{ - use_initiative::{ - use_initiative, ActionItem, InitiativeData, InitiativeInfoContent, - InitiativeInitContent, KusamaTreasury, KusamaTreasuryPeriod, TransferItem, - VotingOpenGov, - }, - use_notification::use_notification, - use_our_navigator::use_our_navigator, - use_session::use_session, - use_spaces_client::use_spaces_client, - use_tooltip::{use_tooltip, TooltipItem}, + use_initiative::{use_initiative, InitiativeData, InitiativeInfoContent, InitiativeInitContent}, use_notification::use_notification, use_our_navigator::use_our_navigator, use_session::use_session, use_spaces_client::use_spaces_client, use_tooltip::{use_tooltip, TooltipItem} }, pages::onboarding::convert_to_jsvalue, services::{ @@ -26,7 +15,6 @@ use crate::{ kusama::system::number, }, }; -use chrono::{DateTime, NaiveDate, NaiveDateTime, Utc}; use dioxus::prelude::*; use dioxus_std::{i18n::use_i18, translate}; use futures_util::TryFutureExt; @@ -54,7 +42,7 @@ extern "C" { community_transfers: JsValue, ) -> Result; } -const BLOCK_TIME_IN_SECONDS: i64 = 6; + #[component] pub fn Initiative(id: u16) -> Element { let i18 = use_i18(); @@ -161,6 +149,7 @@ pub fn Initiative(id: u16) -> Element { class: "", text: translate!(i18, "initiative.cta.continue"), size: ElementSize::Small, + disabled: !initiative.check() || initiative.get_info().name.len() == 0, on_click: move |_| { spawn( async move { @@ -199,36 +188,6 @@ pub fn Initiative(id: u16) -> Element { 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::>(); - log::info!("add_members_action: {:?}", add_members_action); let current_block = number() .await .map_err(|_| { @@ -242,101 +201,17 @@ pub fn Initiative(id: u16) -> Element { 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 add_members_action = initiative.filter_valid_address_add_members(); + log::info!("add_members_action: {:?}", add_members_action); + let treasury_action = initiative.convert_treasury_to_period(current_block, now_kusama); 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 = initiative.filter_valid_voting_open_gov(); 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 community_transfer_action = initiative - .get_actions() - .into_iter() - .filter_map(|action| { - match action { - ActionItem::CommunityTransfer(community_transfer_action) => { - Some( - community_transfer_action - .transfers - .clone() - .into_iter() - .filter_map(|transfer| { - if transfer.value > 0 { - Some(transfer) - } else { - None - } - }) - .collect::>(), - ) - } - _ => None, - } - }) - .collect::>>(); - let community_transfer_action = community_transfer_action - .into_iter() - .flat_map(|v| v.into_iter()) - .collect::>(); + let community_transfer_action = initiative.filter_valid_community_transfer(); log::info!("community_transfer_action {:?}", community_transfer_action); let votiong_open_gov_action = convert_to_jsvalue( &votiong_open_gov_action, @@ -411,46 +286,3 @@ pub fn Initiative(id: u16) -> Element { } } } -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("Invalid future date"); - let future = future_date_naive - .and_hms_opt(0, 0, 0) - .expect("Invalid future date"); - let future_date = DateTime::::from_naive_utc_and_offset(future, Utc); - - let x = DateTime::from_timestamp( - (current_date_millis / 1000).try_into().unwrap(), - ((current_date_millis % 1000) * 1_000_000) as u32, - ) - .expect(""); - - let x = NaiveDateTime::from_str(&x.date_naive().to_string()).expect("Invalid calculated date"); - let current_date = DateTime::from_naive_utc_and_offset(x, 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 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); - KusamaTreasuryPeriod { - blocks: Some(future_block as u64), - amount: treasury.amount, - } - } else { - KusamaTreasuryPeriod { - blocks: None, - amount: treasury.amount, - } - } -} From 67a55618f157132a0e4d957cb8cbb0d252522f75 Mon Sep 17 00:00:00 2001 From: ail3n Date: Wed, 23 Oct 2024 13:44:07 -0300 Subject: [PATCH 3/4] translate error messages --- src/components/molecules/actions/members.rs | 2 +- src/components/molecules/actions/transfer.rs | 4 ++-- src/components/molecules/actions/treasury.rs | 2 +- src/components/molecules/actions/voting.rs | 4 ++-- src/locales/en-US.json | 9 +++++++-- src/locales/es-ES.json | 7 +++++++ 6 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/components/molecules/actions/members.rs b/src/components/molecules/actions/members.rs index d95f586..8bc1a6d 100644 --- a/src/components/molecules/actions/members.rs +++ b/src/components/molecules/actions/members.rs @@ -45,7 +45,7 @@ pub fn MembersAction(props: VotingProps) -> Element { error: { match sp_core::sr25519::Public::from_str(&member.account) { Ok(_) => None, - Err(_) => Some("Invalid Address".to_string()) + Err(_) => Some(translate!(i18, "onboard.invite.form.error.invalid_address")), } }, on_change: move |event: ComboInputValue| { diff --git a/src/components/molecules/actions/transfer.rs b/src/components/molecules/actions/transfer.rs index 86a544e..fc13370 100644 --- a/src/components/molecules/actions/transfer.rs +++ b/src/components/molecules/actions/transfer.rs @@ -37,7 +37,7 @@ pub fn TransferAction(props: VotingProps) -> Element { error: { match sp_core::sr25519::Public::from_str(&transfer.account) { Ok(_) => None, - Err(_) => Some("Invalid Address".to_string()) + Err(_) => Some(translate!(i18, "initiative.steps.actions.error.invalid_address")), } }, on_input: move |event: Event| { @@ -57,7 +57,7 @@ pub fn TransferAction(props: VotingProps) -> Element { if transfer.value > 0 { None } else { - Some("Amount should be greater than 0".to_string()) + Some(translate!(i18, "initiative.steps.actions.error.amount")) } }, right_text: { diff --git a/src/components/molecules/actions/treasury.rs b/src/components/molecules/actions/treasury.rs index 4774f4e..021d0c6 100644 --- a/src/components/molecules/actions/treasury.rs +++ b/src/components/molecules/actions/treasury.rs @@ -65,7 +65,7 @@ pub fn TreasuryAction(props: VotingProps) -> Element { if period.amount > 0 { None } else { - Some("Amount should be greater than 0".to_string()) + Some(translate!(i18, "initiative.steps.actions.error.amount")) } }, right_text: { diff --git a/src/components/molecules/actions/voting.rs b/src/components/molecules/actions/voting.rs index 15582da..adae434 100644 --- a/src/components/molecules/actions/voting.rs +++ b/src/components/molecules/actions/voting.rs @@ -37,7 +37,7 @@ pub fn VotingAction(props: VotingProps) -> Element { if proposal.poll_index > 0 { None } else { - Some("Poll index should be greater than 0".to_string()) + Some(translate!(i18, "initiative.steps.actions.error.amount")) } }, label: translate!(i18, "initiative.steps.actions.voting_open_gov.poll_index"), @@ -74,7 +74,7 @@ pub fn VotingAction(props: VotingProps) -> Element { if vote.balance > 0 { None } else { - Some("Amount should be greater than 0".to_string()) + Some(translate!(i18, "initiative.steps.actions.error.amount")) } }, placeholder: translate!(i18, "initiative.steps.actions.voting_open_gov.standard.balance"), diff --git a/src/locales/en-US.json b/src/locales/en-US.json index f1ff8c2..19b4ab0 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -252,6 +252,10 @@ }, "actions": { "label": "Initiative execution setup", + "error": { + "amount": "Must be greater than 0", + "invalid_address":"Oops! ✋ This address is invalid" + }, "add_members": { "title": "Add Members" }, @@ -261,7 +265,6 @@ "period_1": "The delivery of resources from the treasury will be made instantly once the proposal is approved.", "period_n": "\nImportant: The resources for the other periods will be delivered on the dates established for each one." }, - "error": "Must be greater than 0", "placeholder": "Delivery date" }, "community_transfer": { @@ -270,7 +273,6 @@ "placeholder": "Recipient" }, "amount": { - "error": "Must be greater than 0", "placeholder": "Amount" } }, @@ -450,6 +452,9 @@ "phone": { "label": "Telegram", "placeholder": "+57 322 1230000" + }, + "error": { + "invalid_address": "Oops! ✋ This address is invalid" } }, "cta": { diff --git a/src/locales/es-ES.json b/src/locales/es-ES.json index 5f355a8..a89d091 100644 --- a/src/locales/es-ES.json +++ b/src/locales/es-ES.json @@ -247,6 +247,10 @@ }, "actions": { "label": "Configuración de ejecución de iniciativa", + "error": { + "amount": "Debe ser mayor a 0", + "invalid_address":"Oops! ✋ Dirección no válida" + }, "add_members": { "title": "Agregar Miembros" }, @@ -446,6 +450,9 @@ "phone": { "label": "Teléfono", "placeholder": "+57 322 1230000" + }, + "error": { + "invalid_address": "Oops! ✋ Dirección no válida" } }, "cta": { From 744ea2111aa13545285e3a2cfb9415d709fbf666 Mon Sep 17 00:00:00 2001 From: b-avb Date: Wed, 23 Oct 2024 15:18:20 -0500 Subject: [PATCH 4/4] change: use dropdown instead button to create the first action --- .../molecules/initiative/actions.rs | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/components/molecules/initiative/actions.rs b/src/components/molecules/initiative/actions.rs index 5c2a8e5..dda7860 100644 --- a/src/components/molecules/initiative/actions.rs +++ b/src/components/molecules/initiative/actions.rs @@ -1,10 +1,8 @@ -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, TransferAction, TreasuryAction, VotingAction}, }, @@ -12,6 +10,8 @@ use crate::{ use_initiative, ActionItem, AddMembersAction, MediumOptions, MemberItem, }, }; +use dioxus::prelude::*; +use dioxus_std::{i18n::use_i18, translate}; #[component] pub fn InitiativeActions() -> Element { let i18 = use_i18(); @@ -54,9 +54,9 @@ pub fn InitiativeActions() -> Element { 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() @@ -108,14 +108,24 @@ pub fn InitiativeActions() -> Element { placeholder: translate!(i18, "header.cta.account"), size: ElementSize::Small, default: None, - on_change: move |_: usize| {}, + on_change: move |event: usize| { + let options = initiative.get_actions_options(); + + let to_assign = &options[event]; + let action = initiative.to_action_option(to_assign.key.clone()); + + initiative.push_action(action); + }, 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)" }), + disabled: actions_lock.len() == 0, + body: rsx! { + Icon { icon: AddPlus, height: 24, width: 24, fill: "var(--fill-00)" } + }, on_click: move |_| { initiative .push_action(