140 lines
4.1 KiB
Rust
140 lines
4.1 KiB
Rust
// Copyright (C) 2025-2026 Emilis Bliūdžius
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
use web_sys::Element;
|
|
use yew::prelude::*;
|
|
|
|
use crate::components::Button;
|
|
|
|
#[derive(Debug, Clone, PartialEq, Properties)]
|
|
pub struct DialogProps {
|
|
#[prop_or_default]
|
|
pub children: Html,
|
|
pub options: Box<[String]>,
|
|
#[prop_or_default]
|
|
pub cancel_callback: Option<Callback<()>>,
|
|
pub callback: Callback<String>,
|
|
}
|
|
|
|
#[function_component]
|
|
pub fn Dialog(
|
|
DialogProps {
|
|
children,
|
|
options,
|
|
cancel_callback,
|
|
callback,
|
|
}: &DialogProps,
|
|
) -> Html {
|
|
let options = options
|
|
.iter()
|
|
.map(|opt| {
|
|
let callback = callback.clone();
|
|
let option = opt.clone();
|
|
let cb = Callback::from(move |_| {
|
|
callback.emit(option.clone());
|
|
});
|
|
html! {
|
|
<Button on_click={cb}>{opt.clone()}</Button>
|
|
}
|
|
})
|
|
.collect::<Html>();
|
|
let backdrop_click = cancel_callback.clone().map(|cancel_callback| {
|
|
Callback::from(move |ev: MouseEvent| {
|
|
if let Some(div) = ev.target_dyn_into::<Element>()
|
|
&& div.class_name() == "dialog"
|
|
{
|
|
ev.stop_propagation();
|
|
cancel_callback.emit(());
|
|
}
|
|
})
|
|
});
|
|
|
|
html! {
|
|
<div class="click-backdrop" onclick={backdrop_click}>
|
|
<div class="dialog">
|
|
<div class="dialog-box">
|
|
<div class="message">
|
|
{children.clone()}
|
|
</div>
|
|
<div class="options">
|
|
{options}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Properties)]
|
|
pub struct WithConfirmationProps {
|
|
pub state: UseStateHandle<bool>,
|
|
#[prop_or_default]
|
|
pub children: Html,
|
|
pub confirm_callback: Callback<()>,
|
|
pub message: Html,
|
|
}
|
|
|
|
#[function_component]
|
|
pub fn WithConfirmation(
|
|
WithConfirmationProps {
|
|
state,
|
|
children,
|
|
confirm_callback,
|
|
message,
|
|
}: &WithConfirmationProps,
|
|
) -> Html {
|
|
let about_dialog_state = state.clone();
|
|
let confirmation_dialog = about_dialog_state.then(|| {
|
|
let cancel_signout = {
|
|
let dialog = about_dialog_state.clone();
|
|
Callback::from(move |_| {
|
|
dialog.set(false);
|
|
})
|
|
};
|
|
let confirm_callback = confirm_callback.clone();
|
|
let callback = {
|
|
let dialog = about_dialog_state.clone();
|
|
Callback::from(move |opt: String| {
|
|
if opt == "ok" {
|
|
confirm_callback.emit(());
|
|
} else {
|
|
dialog.set(false);
|
|
}
|
|
})
|
|
};
|
|
let options: Box<[String]> = Box::new([String::from("ok"), String::from("take me back")]);
|
|
html! {
|
|
<Dialog
|
|
options={options}
|
|
cancel_callback={Some(cancel_signout)}
|
|
callback={callback}
|
|
>
|
|
{message.clone()}
|
|
</Dialog>
|
|
}
|
|
});
|
|
let confirmation_click = {
|
|
let dialog_set = about_dialog_state.setter();
|
|
move |_| {
|
|
dialog_set.set(true);
|
|
}
|
|
};
|
|
html! {
|
|
<>
|
|
<span class="has-confirm" onclick={confirmation_click}>{children.clone()}</span>
|
|
{confirmation_dialog}
|
|
</>
|
|
}
|
|
}
|