summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColin Reeder <colin@vpzom.click>2020-08-01 15:27:29 -0600
committerColin Reeder <colin@vpzom.click>2020-08-01 15:29:24 -0600
commit30eb3636cc7ccc968f4244eef7c39a4cf0a317ff (patch)
tree14d54c45ca85651529e6a4f92e753588a8298e84
parente2e37561e002fd7dbf9087a8721198ca335d33d4 (diff)
Add Preview feature for posts (#78)
-rw-r--r--res/lang/en.ftl1
-rw-r--r--res/lang/eo.ftl1
-rw-r--r--res/main.css5
-rw-r--r--src/resp_types.rs5
-rw-r--r--src/routes/communities.rs71
5 files changed, 81 insertions, 2 deletions
diff --git a/res/lang/en.ftl b/res/lang/en.ftl
index e475611..26f4462 100644
--- a/res/lang/en.ftl
+++ b/res/lang/en.ftl
@@ -55,6 +55,7 @@ post_delete_title = Delete Post
post_likes_nothing = Looks like nobody has liked this post yet.
post_new = New Post
post_not_approved = This post has not been approved by the community.
+preview = Preview
register = Register
remote = Remote
reply = reply
diff --git a/res/lang/eo.ftl b/res/lang/eo.ftl
index 3ea23e0..47bfc91 100644
--- a/res/lang/eo.ftl
+++ b/res/lang/eo.ftl
@@ -55,6 +55,7 @@ post_delete_title = Forigi Poŝton
post_likes_nothing = Ŝajnas, ke neniu ankoraŭ ŝatis ĉi tion poŝton.
post_new = Nova Poŝto
post_not_approved = Ĉi tiu poŝto ne estas aprobita per la komunumo.
+preview = Antaŭprezenti
register = Registriĝi
remote = Fora
reply = respondi
diff --git a/res/main.css b/res/main.css
index f036c13..2ff6a0c 100644
--- a/res/main.css
+++ b/res/main.css
@@ -70,6 +70,11 @@ body {
margin-right: .5em;
}
+.preview {
+ margin-top: 1em;
+ border: 1px dashed black;
+}
+
@media (max-width: 768px) {
.communitySidebar {
display: none; /* TODO still show this somewhere */
diff --git a/src/resp_types.rs b/src/resp_types.rs
index b51b26c..96b1626 100644
--- a/src/resp_types.rs
+++ b/src/resp_types.rs
@@ -228,6 +228,11 @@ pub struct JustUser<'a> {
}
#[derive(Deserialize, Debug)]
+pub struct JustContentHTML<'a> {
+ pub content_html: Cow<'a, str>,
+}
+
+#[derive(Deserialize, Debug)]
pub struct RespList<'a, T: std::fmt::Debug + 'a> {
pub items: Vec<T>,
pub next_page: Option<Cow<'a, str>>,
diff --git a/src/routes/communities.rs b/src/routes/communities.rs
index 4ffefce..fc2bb07 100644
--- a/src/routes/communities.rs
+++ b/src/routes/communities.rs
@@ -1,6 +1,7 @@
use crate::components::{CommunityLink, HTPage, MaybeFillInput, MaybeFillTextArea, PostItem};
use crate::resp_types::{
- RespCommunityInfoMaybeYour, RespMinimalCommunityInfo, RespPostListPost, RespYourFollow,
+ JustContentHTML, RespCommunityInfoMaybeYour, RespMinimalCommunityInfo, RespPostListPost,
+ RespYourFollow,
};
use crate::routes::{
fetch_base_data, for_client, get_cookie_map_for_headers, get_cookie_map_for_req, html_response,
@@ -516,7 +517,8 @@ async fn page_community_new_post(
let cookies = get_cookie_map_for_req(&req)?;
- page_community_new_post_inner(community_id, req.headers(), &cookies, ctx, None, None).await
+ page_community_new_post_inner(community_id, req.headers(), &cookies, ctx, None, None, None)
+ .await
}
async fn page_community_new_post_inner(
@@ -526,6 +528,7 @@ async fn page_community_new_post_inner(
ctx: Arc<crate::RouteContext>,
display_error: Option<String>,
prev_values: Option<&HashMap<&str, serde_json::Value>>,
+ display_preview: Option<&str>,
) -> Result<hyper::Response<hyper::Body>, crate::Error> {
let base_data = fetch_base_data(&ctx.backend_host, &ctx.http_client, headers, &cookies).await?;
let lang = crate::get_lang_for_headers(headers);
@@ -534,6 +537,8 @@ async fn page_community_new_post_inner(
let title = lang.tr("post_new", None);
+ let display_preview = display_preview.map(|x| ammonia::clean(&x));
+
Ok(html_response(render::html! {
<HTPage base_data={&base_data} lang={&lang} title={&title}>
<h1>{title.as_ref()}</h1>
@@ -570,8 +575,16 @@ async fn page_community_new_post_inner(
</label>
<div>
<button r#type={"submit"}>{lang.tr("submit", None)}</button>
+ <button r#type={"submit"} name={"preview"}>{lang.tr("preview", None)}</button>
</div>
</form>
+ {
+ display_preview.as_deref().map(|html| {
+ render::rsx! {
+ <div class={"preview"}>{render::raw!(html)}</div>
+ }
+ })
+ }
</HTPage>
}))
}
@@ -588,6 +601,59 @@ async fn handler_communities_new_post_submit(
let body = hyper::body::to_bytes(body).await?;
let mut body: HashMap<&str, serde_json::Value> = serde_urlencoded::from_bytes(&body)?;
+ if body.contains_key("preview") {
+ let md = body
+ .get("content_markdown")
+ .and_then(|x| x.as_str())
+ .unwrap_or("");
+ let preview_res = res_to_error(
+ ctx.http_client
+ .request(for_client(
+ hyper::Request::post(format!(
+ "{}/api/unstable/misc/render_markdown",
+ ctx.backend_host
+ ))
+ .body(
+ serde_json::to_vec(&serde_json::json!({ "content_markdown": md }))?.into(),
+ )?,
+ &req_parts.headers,
+ &cookies,
+ )?)
+ .await?,
+ )
+ .await;
+ return match preview_res {
+ Ok(preview_res) => {
+ let preview_res = hyper::body::to_bytes(preview_res.into_body()).await?;
+ let preview_res: JustContentHTML = serde_json::from_slice(&preview_res)?;
+
+ page_community_new_post_inner(
+ community_id,
+ &req_parts.headers,
+ &cookies,
+ ctx,
+ None,
+ Some(&body),
+ Some(&preview_res.content_html),
+ )
+ .await
+ }
+ Err(crate::Error::RemoteError((_, message))) => {
+ page_community_new_post_inner(
+ community_id,
+ &req_parts.headers,
+ &cookies,
+ ctx,
+ Some(message),
+ Some(&body),
+ None,
+ )
+ .await
+ }
+ Err(other) => Err(other),
+ };
+ }
+
body.insert("community", community_id.into());
if body.get("content_markdown").and_then(|x| x.as_str()) == Some("") {
body.remove("content_markdown");
@@ -631,6 +697,7 @@ async fn handler_communities_new_post_submit(
ctx,
Some(message),
Some(&body),
+ None,
)
.await
}