use topcoat::{
context::Cx,
router::{Body, error::forbidden},
view::{BoxView, ViewExt, attributes, view},
};
use super::super::gate::gate;
use crate::{Ability, resource::Resource, schema::OptionSource, t, topcoat_compat::async_page};
pub(crate) fn resource_picked<R: Resource>(cx: &Cx, _body: Body) -> BoxView<'_> {
async_page(async move {
let resource = gate::<R>(cx)?;
if !resource.can(cx, Ability::ViewAny) {
return Err(forbidden().into());
}
let _ = crate::flash::take_notification(cx);
let key = picked_key(cx);
let option = chosen::<R>(cx, &key).await?.map(|label| (key, label));
Ok(render_picked(cx, option))
})
}
async fn chosen<R: Resource>(cx: &Cx, key: &str) -> topcoat::Result<Option<String>> {
let Some(expr) = crate::toasty_compat::pk::pk_eq_expr::<R::Model>(key.trim()) else {
return Ok(None);
};
let record = <R as OptionSource>::scoped_query(cx)?
.filter(expr)
.first()
.exec(&mut crate::db::db(cx)?)
.await
.map_err(crate::error::unavailable)?;
Ok(record.map(|record| <R as OptionSource>::label(cx, &record)))
}
fn picked_key(cx: &Cx) -> String {
let query = topcoat::router::request::uri(cx)
.query()
.unwrap_or_default();
form_urlencoded::parse(query.as_bytes())
.find(|(name, _)| name == "key")
.map(|(_, value)| value.into_owned())
.unwrap_or_default()
}
fn render_picked(cx: &Cx, option: Option<(String, String)>) -> BoxView<'_> {
match option {
Some((value, label)) => view! {
tablo_ui::alert(
attrs: attributes! {
data-picked=""
data-picked-value=(value)
data-picked-label=(label.clone())
},
tablo_ui::alert_title(
(t!(cx, "tablo-field-option-created", label = label))
)
)
}
.boxed(),
None => view! {
<div class="flex flex-col gap-4">
tablo_ui::alert(
attrs: attributes! { data-picked-hidden="" },
tablo_ui::alert_title((t!(cx, "tablo-field-option-unchoosable")))
tablo_ui::alert_description(
(t!(cx, "tablo-field-option-unchoosable-description"))
)
)
<div>
tablo_ui::button(
variant: tablo_ui::ButtonVariant::Outline,
attrs: attributes! { type="button" data-pick-cancel="" },
(t!(cx, "tablo-close"))
)
</div>
</div>
}
.boxed(),
}
}