mirror of
https://github.com/Nutomic/ibis.git
synced 2024-11-22 09:31:09 +00:00
Also allow resolving federated edit conflicts
This commit is contained in:
parent
a15a42b977
commit
e325de6352
7 changed files with 60 additions and 11 deletions
|
@ -99,7 +99,7 @@ impl DbConflict {
|
|||
hash: self.hash.clone(),
|
||||
three_way_merge,
|
||||
summary: self.summary.clone(),
|
||||
article_id: original_article.id,
|
||||
article: original_article.clone(),
|
||||
previous_version_id: original_article
|
||||
.latest_edit_version(&data.db_connection)?,
|
||||
}))
|
||||
|
|
|
@ -217,7 +217,7 @@ pub struct ApiConflict {
|
|||
pub hash: EditVersion,
|
||||
pub three_way_merge: String,
|
||||
pub summary: String,
|
||||
pub article_id: i32,
|
||||
pub article: DbArticle,
|
||||
pub previous_version_id: EditVersion,
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ use crate::frontend::pages::article::edit::EditArticle;
|
|||
use crate::frontend::pages::article::history::ArticleHistory;
|
||||
use crate::frontend::pages::article::list::ListArticles;
|
||||
use crate::frontend::pages::article::read::ReadArticle;
|
||||
use crate::frontend::pages::conflicts::Conflicts;
|
||||
use crate::frontend::pages::diff::EditDiff;
|
||||
use crate::frontend::pages::instance_details::InstanceDetails;
|
||||
use crate::frontend::pages::login::Login;
|
||||
|
@ -94,7 +95,7 @@ pub fn App() -> impl IntoView {
|
|||
<Route path="/" view=ReadArticle/>
|
||||
<Route path="/article/:title" view=ReadArticle/>
|
||||
<Route path="/article/:title/history" view=ArticleHistory/>
|
||||
<Route path="/article/:title/edit" view=EditArticle/>
|
||||
<Route path="/article/:title/edit/:conflict_id?" view=EditArticle/>
|
||||
<Route path="/article/:title/actions" view=ArticleActions/>
|
||||
<Route path="/article/:title/diff/:hash" view=EditDiff/>
|
||||
<Route path="/article/create" view=CreateArticle/>
|
||||
|
@ -104,6 +105,7 @@ pub fn App() -> impl IntoView {
|
|||
<Route path="/login" view=Login/>
|
||||
<Route path="/register" view=Register/>
|
||||
<Route path="/search" view=Search/>
|
||||
<Route path="/conflicts" view=Conflicts/>
|
||||
</Routes>
|
||||
</main>
|
||||
</Router>
|
||||
|
|
|
@ -35,6 +35,9 @@ pub fn Nav() -> impl IntoView {
|
|||
<li>
|
||||
<A href="/article/create">"Create Article"</A>
|
||||
</li>
|
||||
<li>
|
||||
<A href="/conflicts">"Edit Conflicts"</A>
|
||||
</li>
|
||||
</Show>
|
||||
<li>
|
||||
<form on:submit=move |ev| {
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::frontend::article_title;
|
|||
use crate::frontend::components::article_nav::ArticleNav;
|
||||
use crate::frontend::pages::article_resource;
|
||||
use leptos::*;
|
||||
use leptos_router::use_params_map;
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
enum EditResponse {
|
||||
|
@ -12,14 +13,35 @@ enum EditResponse {
|
|||
Conflict(ApiConflict),
|
||||
}
|
||||
|
||||
const CONFLICT_MESSAGE: &str = "There was an edit conflict. Resolve it manually and resubmit.";
|
||||
|
||||
#[component]
|
||||
pub fn EditArticle() -> impl IntoView {
|
||||
let article = article_resource();
|
||||
let (edit_response, set_edit_response) = create_signal(EditResponse::None);
|
||||
let (edit_error, set_edit_error) = create_signal(None::<String>);
|
||||
|
||||
let conflict_id = move || use_params_map().get().get("conflict_id").cloned();
|
||||
if let Some(conflict_id) = conflict_id() {
|
||||
create_action(move |conflict_id: &String| {
|
||||
let conflict_id: i32 = conflict_id.parse().unwrap();
|
||||
async move {
|
||||
let conflict = GlobalState::api_client()
|
||||
.get_conflicts()
|
||||
.await
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.find(|c| c.id == conflict_id)
|
||||
.unwrap();
|
||||
set_edit_response.set(EditResponse::Conflict(conflict));
|
||||
set_edit_error.set(Some(CONFLICT_MESSAGE.to_string()));
|
||||
}
|
||||
})
|
||||
.dispatch(conflict_id);
|
||||
}
|
||||
|
||||
let (text, set_text) = create_signal(String::new());
|
||||
let (summary, set_summary) = create_signal(String::new());
|
||||
let (edit_response, set_edit_response) = create_signal(EditResponse::None);
|
||||
let (edit_error, set_edit_error) = create_signal(None::<String>);
|
||||
let (wait_for_response, set_wait_for_response) = create_signal(false);
|
||||
let button_is_disabled =
|
||||
Signal::derive(move || wait_for_response.get() || summary.get().is_empty());
|
||||
|
@ -58,12 +80,7 @@ pub fn EditArticle() -> impl IntoView {
|
|||
match res {
|
||||
Ok(Some(conflict)) => {
|
||||
set_edit_response.update(|v| *v = EditResponse::Conflict(conflict));
|
||||
set_edit_error.update(|e| {
|
||||
*e = Some(
|
||||
"There was an edit conflict. Resolve it manually and resubmit."
|
||||
.to_string(),
|
||||
)
|
||||
});
|
||||
set_edit_error.set(Some(CONFLICT_MESSAGE.to_string()));
|
||||
}
|
||||
Ok(None) => {
|
||||
set_edit_response.update(|v| *v = EditResponse::Success);
|
||||
|
|
26
src/frontend/pages/conflicts.rs
Normal file
26
src/frontend/pages/conflicts.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
use crate::frontend::app::GlobalState;
|
||||
use crate::frontend::article_link;
|
||||
use crate::frontend::article_title;
|
||||
use leptos::*;
|
||||
|
||||
#[component]
|
||||
pub fn Conflicts() -> impl IntoView {
|
||||
let conflicts = create_resource(
|
||||
move || {},
|
||||
|_| async move { GlobalState::api_client().get_conflicts().await.unwrap() },
|
||||
);
|
||||
|
||||
view! {
|
||||
<h1>Your unresolved edit conflicts</h1>
|
||||
<Suspense fallback=|| view! { "Loading..." }>
|
||||
<ul> {
|
||||
move || conflicts.get().map(|c|
|
||||
c.into_iter().map(|c| {
|
||||
let link = format!("{}/edit/{}", article_link(&c.article), c.id);
|
||||
view! {
|
||||
<li><a href=link>{article_title(&c.article)}" - "{c.summary}</a></li>
|
||||
}}).collect::<Vec<_>>())
|
||||
} </ul>
|
||||
</Suspense>
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ use leptos::{create_resource, Resource, SignalGet};
|
|||
use leptos_router::use_params_map;
|
||||
|
||||
pub(crate) mod article;
|
||||
pub(crate) mod conflicts;
|
||||
pub(crate) mod diff;
|
||||
pub(crate) mod instance_details;
|
||||
pub(crate) mod login;
|
||||
|
|
Loading…
Reference in a new issue