Add agent driven component.
This commit is contained in:
parent
d19f9051c2
commit
4a2087a94e
4 changed files with 118 additions and 1 deletions
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "bootstrap-rs"
|
||||
version = "0.2.12"
|
||||
version = "0.2.13"
|
||||
authors = ["Thomas Gideon <cmdln@thecommandline.net>"]
|
||||
edition = "2018"
|
||||
|
||||
|
|
61
src/alert/bus.rs
Normal file
61
src/alert/bus.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
use crate::prelude::*;
|
||||
use std::collections::HashSet;
|
||||
use yew::worker::{Agent, AgentLink, Context, HandlerId};
|
||||
|
||||
pub struct Bus {
|
||||
link: AgentLink<Bus>,
|
||||
subscribers: HashSet<HandlerId>,
|
||||
}
|
||||
|
||||
pub enum Request {
|
||||
Primary(String),
|
||||
Secondary(String),
|
||||
Success(String),
|
||||
Danger(String),
|
||||
Warning(String),
|
||||
Info(String),
|
||||
Clear,
|
||||
}
|
||||
|
||||
impl Into<Option<(Color, String)>> for &Request {
|
||||
fn into(self) -> Option<(Color, String)> {
|
||||
use Request::*;
|
||||
match self {
|
||||
Primary(alert) => Some((Color::Primary, alert.clone())),
|
||||
Secondary(alert) => Some((Color::Secondary, alert.clone())),
|
||||
Success(alert) => Some((Color::Success, alert.clone())),
|
||||
Danger(alert) => Some((Color::Danger, alert.clone())),
|
||||
Warning(alert) => Some((Color::Warning, alert.clone())),
|
||||
Info(alert) => Some((Color::Info, alert.clone())),
|
||||
Clear => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Agent for Bus {
|
||||
type Reach = Context<Self>;
|
||||
type Message = ();
|
||||
type Input = Request;
|
||||
type Output = Option<(Color, String)>;
|
||||
|
||||
fn create(link: AgentLink<Self>) -> Self {
|
||||
let subscribers = HashSet::new();
|
||||
Self { link, subscribers }
|
||||
}
|
||||
|
||||
fn update(&mut self, _: Self::Message) {}
|
||||
|
||||
fn handle_input(&mut self, input: Self::Input, _id: HandlerId) {
|
||||
for sub in self.subscribers.iter() {
|
||||
self.link.respond(*sub, (&input).into());
|
||||
}
|
||||
}
|
||||
|
||||
fn connected(&mut self, id: HandlerId) {
|
||||
self.subscribers.insert(id);
|
||||
}
|
||||
|
||||
fn disconnected(&mut self, id: HandlerId) {
|
||||
self.subscribers.remove(&id);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,11 @@
|
|||
mod bus;
|
||||
mod props;
|
||||
mod sub;
|
||||
|
||||
use self::props::Props;
|
||||
use crate::{prelude::*, render};
|
||||
pub use bus::{Bus, Request};
|
||||
pub use sub::AlertSubscriber;
|
||||
use yew::prelude::*;
|
||||
|
||||
pub struct Alert {
|
||||
|
|
52
src/alert/sub.rs
Normal file
52
src/alert/sub.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
use super::{Alert, Bus};
|
||||
use crate::prelude::*;
|
||||
use yew::prelude::*;
|
||||
|
||||
pub struct AlertSubscriber {
|
||||
link: ComponentLink<Self>,
|
||||
alert: Option<(Color, String)>,
|
||||
_producer: Box<dyn Bridge<Bus>>,
|
||||
}
|
||||
|
||||
impl Component for AlertSubscriber {
|
||||
type Message = Option<(Color, String)>;
|
||||
type Properties = ();
|
||||
|
||||
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
|
||||
let _producer = Bus::bridge(link.callback(|msg| msg));
|
||||
let alert = None;
|
||||
Self {
|
||||
link,
|
||||
alert,
|
||||
_producer,
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, msg: Self::Message) -> ShouldRender {
|
||||
if self.alert == msg {
|
||||
false
|
||||
} else {
|
||||
self.alert = msg;
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn change(&mut self, _: Self::Properties) -> ShouldRender {
|
||||
false
|
||||
}
|
||||
|
||||
fn view(&self) -> Html {
|
||||
if let Some((color, message)) = self.alert.as_ref() {
|
||||
html! {
|
||||
<Alert
|
||||
on_close=self.link.callback(|_| None)
|
||||
color=color
|
||||
>
|
||||
{ message }
|
||||
</Alert>
|
||||
}
|
||||
} else {
|
||||
html! {}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue