mirror of
https://github.com/Nutomic/ibis.git
synced 2024-11-25 21:11:10 +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(),
|
hash: self.hash.clone(),
|
||||||
three_way_merge,
|
three_way_merge,
|
||||||
summary: self.summary.clone(),
|
summary: self.summary.clone(),
|
||||||
article_id: original_article.id,
|
article: original_article.clone(),
|
||||||
previous_version_id: original_article
|
previous_version_id: original_article
|
||||||
.latest_edit_version(&data.db_connection)?,
|
.latest_edit_version(&data.db_connection)?,
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -217,7 +217,7 @@ pub struct ApiConflict {
|
||||||
pub hash: EditVersion,
|
pub hash: EditVersion,
|
||||||
pub three_way_merge: String,
|
pub three_way_merge: String,
|
||||||
pub summary: String,
|
pub summary: String,
|
||||||
pub article_id: i32,
|
pub article: DbArticle,
|
||||||
pub previous_version_id: EditVersion,
|
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::history::ArticleHistory;
|
||||||
use crate::frontend::pages::article::list::ListArticles;
|
use crate::frontend::pages::article::list::ListArticles;
|
||||||
use crate::frontend::pages::article::read::ReadArticle;
|
use crate::frontend::pages::article::read::ReadArticle;
|
||||||
|
use crate::frontend::pages::conflicts::Conflicts;
|
||||||
use crate::frontend::pages::diff::EditDiff;
|
use crate::frontend::pages::diff::EditDiff;
|
||||||
use crate::frontend::pages::instance_details::InstanceDetails;
|
use crate::frontend::pages::instance_details::InstanceDetails;
|
||||||
use crate::frontend::pages::login::Login;
|
use crate::frontend::pages::login::Login;
|
||||||
|
@ -94,7 +95,7 @@ pub fn App() -> impl IntoView {
|
||||||
<Route path="/" view=ReadArticle/>
|
<Route path="/" view=ReadArticle/>
|
||||||
<Route path="/article/:title" view=ReadArticle/>
|
<Route path="/article/:title" view=ReadArticle/>
|
||||||
<Route path="/article/:title/history" view=ArticleHistory/>
|
<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/actions" view=ArticleActions/>
|
||||||
<Route path="/article/:title/diff/:hash" view=EditDiff/>
|
<Route path="/article/:title/diff/:hash" view=EditDiff/>
|
||||||
<Route path="/article/create" view=CreateArticle/>
|
<Route path="/article/create" view=CreateArticle/>
|
||||||
|
@ -104,6 +105,7 @@ pub fn App() -> impl IntoView {
|
||||||
<Route path="/login" view=Login/>
|
<Route path="/login" view=Login/>
|
||||||
<Route path="/register" view=Register/>
|
<Route path="/register" view=Register/>
|
||||||
<Route path="/search" view=Search/>
|
<Route path="/search" view=Search/>
|
||||||
|
<Route path="/conflicts" view=Conflicts/>
|
||||||
</Routes>
|
</Routes>
|
||||||
</main>
|
</main>
|
||||||
</Router>
|
</Router>
|
||||||
|
|
|
@ -35,6 +35,9 @@ pub fn Nav() -> impl IntoView {
|
||||||
<li>
|
<li>
|
||||||
<A href="/article/create">"Create Article"</A>
|
<A href="/article/create">"Create Article"</A>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<A href="/conflicts">"Edit Conflicts"</A>
|
||||||
|
</li>
|
||||||
</Show>
|
</Show>
|
||||||
<li>
|
<li>
|
||||||
<form on:submit=move |ev| {
|
<form on:submit=move |ev| {
|
||||||
|
|
|
@ -4,6 +4,7 @@ use crate::frontend::article_title;
|
||||||
use crate::frontend::components::article_nav::ArticleNav;
|
use crate::frontend::components::article_nav::ArticleNav;
|
||||||
use crate::frontend::pages::article_resource;
|
use crate::frontend::pages::article_resource;
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
use leptos_router::use_params_map;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
enum EditResponse {
|
enum EditResponse {
|
||||||
|
@ -12,14 +13,35 @@ enum EditResponse {
|
||||||
Conflict(ApiConflict),
|
Conflict(ApiConflict),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CONFLICT_MESSAGE: &str = "There was an edit conflict. Resolve it manually and resubmit.";
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn EditArticle() -> impl IntoView {
|
pub fn EditArticle() -> impl IntoView {
|
||||||
let article = article_resource();
|
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 (text, set_text) = create_signal(String::new());
|
||||||
let (summary, set_summary) = 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 (wait_for_response, set_wait_for_response) = create_signal(false);
|
||||||
let button_is_disabled =
|
let button_is_disabled =
|
||||||
Signal::derive(move || wait_for_response.get() || summary.get().is_empty());
|
Signal::derive(move || wait_for_response.get() || summary.get().is_empty());
|
||||||
|
@ -58,12 +80,7 @@ pub fn EditArticle() -> impl IntoView {
|
||||||
match res {
|
match res {
|
||||||
Ok(Some(conflict)) => {
|
Ok(Some(conflict)) => {
|
||||||
set_edit_response.update(|v| *v = EditResponse::Conflict(conflict));
|
set_edit_response.update(|v| *v = EditResponse::Conflict(conflict));
|
||||||
set_edit_error.update(|e| {
|
set_edit_error.set(Some(CONFLICT_MESSAGE.to_string()));
|
||||||
*e = Some(
|
|
||||||
"There was an edit conflict. Resolve it manually and resubmit."
|
|
||||||
.to_string(),
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
set_edit_response.update(|v| *v = EditResponse::Success);
|
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;
|
use leptos_router::use_params_map;
|
||||||
|
|
||||||
pub(crate) mod article;
|
pub(crate) mod article;
|
||||||
|
pub(crate) mod conflicts;
|
||||||
pub(crate) mod diff;
|
pub(crate) mod diff;
|
||||||
pub(crate) mod instance_details;
|
pub(crate) mod instance_details;
|
||||||
pub(crate) mod login;
|
pub(crate) mod login;
|
||||||
|
|
Loading…
Reference in a new issue