use topcoat::{context::Cx, router::error::see_other, view::BoxView};
use super::gate::landing_url;
use crate::{
notification::{Notification, notify_write_failure, set_notification},
resource::{Committed, Mounted, Resource},
};
pub(crate) async fn commit_write<'a, R: Resource, T>(
cx: &'a Cx,
resource: &Mounted<R>,
tx: toasty::Transaction<'_>,
written: Result<T, topcoat::Error>,
committed: impl FnOnce(T) -> Committed<R::Model>,
note: impl Into<String>,
failure: &'static str,
) -> Result<BoxView<'a>, topcoat::Error> {
match written {
Ok(value) => match tx.commit().await {
Ok(()) => {
crate::resource::run_after_commit::<R>(cx, committed(value)).await;
Err(redirect_after_write(cx, &resource.url, note))
}
Err(error) => {
notify_write_failure(cx, failure);
Err(crate::error::unavailable(error))
}
},
Err(error) => {
notify_write_failure(cx, failure);
Err(crate::error::driver_failure(
error,
crate::error::DATABASE_UNAVAILABLE,
))
}
}
}
fn redirect_after_write(cx: &Cx, list_url: &str, note: impl Into<String>) -> topcoat::Error {
set_notification(cx, Notification::success(note));
see_other(landing_url(cx, list_url)).into()
}