feat(kanban): persist local reorder commands
req: local/001\nreq: local/002\nreq: local/003\nreq: local/004\nreq: sync/009
This commit is contained in:
+75
-10
@@ -1,25 +1,90 @@
|
||||
#[hemx::surface]
|
||||
pub mod ui {}
|
||||
|
||||
#[cfg(feature = "client")]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
struct CardId(String);
|
||||
|
||||
#[cfg(feature = "client")]
|
||||
struct ReorderCommand {
|
||||
card: CardId,
|
||||
input_kind: String,
|
||||
}
|
||||
|
||||
#[cfg(feature = "client")]
|
||||
struct CardReordered {
|
||||
card: CardId,
|
||||
input_kind: String,
|
||||
}
|
||||
|
||||
#[cfg(feature = "client")]
|
||||
struct BoardProjection {
|
||||
first: CardId,
|
||||
}
|
||||
|
||||
#[cfg(feature = "client")]
|
||||
struct ProjectedReorder {
|
||||
card: CardId,
|
||||
before: Option<CardId>,
|
||||
input_kind: String,
|
||||
}
|
||||
|
||||
#[cfg(feature = "client")]
|
||||
impl ReorderCommand {
|
||||
fn from_client(event: hemx::wasm::ClientEvent) -> Self {
|
||||
Self {
|
||||
card: CardId(
|
||||
event
|
||||
.value
|
||||
.filter(|card| !card.is_empty())
|
||||
.unwrap_or_else(|| "1".into()),
|
||||
),
|
||||
input_kind: event.kind,
|
||||
}
|
||||
}
|
||||
|
||||
fn decide(self) -> CardReordered {
|
||||
CardReordered {
|
||||
card: self.card,
|
||||
input_kind: self.input_kind,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "client")]
|
||||
impl BoardProjection {
|
||||
fn restore(state: hemx::wasm::ClientState) -> Self {
|
||||
Self {
|
||||
first: CardId(state.encoded.split('|').next().unwrap_or("1").to_owned()),
|
||||
}
|
||||
}
|
||||
|
||||
fn apply(self, event: CardReordered) -> ProjectedReorder {
|
||||
let before = (event.card != self.first).then_some(self.first);
|
||||
ProjectedReorder {
|
||||
card: event.card,
|
||||
before,
|
||||
input_kind: event.input_kind,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "client")]
|
||||
#[hemx::handler(client)]
|
||||
pub fn reorder_card(
|
||||
event: hemx::wasm::ClientEvent,
|
||||
state: hemx::wasm::ClientState,
|
||||
) -> impl hemx::IntoEffect {
|
||||
let card = event.value.unwrap_or_else(|| "1".to_owned());
|
||||
let order = state.encoded.split('|').collect::<Vec<_>>();
|
||||
let move_effect = if card == order.first().copied().unwrap_or("1") {
|
||||
ui::client_board::client_cards.move_to_end(card.clone())
|
||||
} else {
|
||||
ui::client_board::client_cards.move_before(
|
||||
card.clone(),
|
||||
order.first().copied().unwrap_or("1").to_owned(),
|
||||
)
|
||||
let projected =
|
||||
BoardProjection::restore(state).apply(ReorderCommand::from_client(event).decide());
|
||||
let card = projected.card.0;
|
||||
let move_effect = match projected.before {
|
||||
Some(before) => ui::client_board::client_cards.move_before(card.clone(), before.0),
|
||||
None => ui::client_board::client_cards.move_to_end(card.clone()),
|
||||
};
|
||||
vec![
|
||||
move_effect,
|
||||
ui::client_board::client_notice.text(format!("Moved {card} with {}", event.kind)),
|
||||
ui::client_board::client_notice.text(format!("Moved {card} with {}", projected.input_kind)),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user