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]
|
[package]
|
||||||
name = "bootstrap-rs"
|
name = "bootstrap-rs"
|
||||||
version = "0.2.12"
|
version = "0.2.13"
|
||||||
authors = ["Thomas Gideon <cmdln@thecommandline.net>"]
|
authors = ["Thomas Gideon <cmdln@thecommandline.net>"]
|
||||||
edition = "2018"
|
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 props;
|
||||||
|
mod sub;
|
||||||
|
|
||||||
use self::props::Props;
|
use self::props::Props;
|
||||||
use crate::{prelude::*, render};
|
use crate::{prelude::*, render};
|
||||||
|
pub use bus::{Bus, Request};
|
||||||
|
pub use sub::AlertSubscriber;
|
||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
|
|
||||||
pub struct Alert {
|
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