From 3feed530ff77e7be9708a95ef0bf93c53968f357 Mon Sep 17 00:00:00 2001 From: Magnus Hoff Date: Thu, 21 Sep 2017 10:09:57 +0200 Subject: [PATCH] Implement support for editing page title --- assets/script.js | 26 ++++++++++++----- assets/style.css | 11 +++++++- src/article_resource.rs | 21 ++++++++++++-- src/state.rs | 10 ++++--- templates/article_revision.html | 36 ++++++++++++++---------- templates/article_revision_contents.html | 7 +++++ 6 files changed, 82 insertions(+), 29 deletions(-) create mode 100644 templates/article_revision_contents.html diff --git a/assets/script.js b/assets/script.js index 964a319..4e28959 100644 --- a/assets/script.js +++ b/assets/script.js @@ -15,9 +15,9 @@ function queryArgsFromForm(form) { let hasBeenOpen = false; function openEditor() { - const article = document.querySelector("article"); - const rendered = article.querySelector(".rendered"); - const editor = article.querySelector(".editor"); + const container = document.querySelector(".container"); + const rendered = container.querySelector(".rendered"); + const editor = container.querySelector(".editor"); const textarea = editor.querySelector('textarea[name="body"]'); const shadow = editor.querySelector('textarea.shadow-control'); const form = editor.querySelector("form"); @@ -29,7 +29,7 @@ function openEditor() { textarea.style.height = rendered.clientHeight + "px"; - article.classList.add('edit'); + container.classList.add('edit'); autosizeTextarea(textarea, shadow); @@ -63,11 +63,23 @@ function openEditor() { if (!response.ok) throw new Error("Unexpected status code (" + response.status + ")"); const result = await response.json(); - form.elements.base_revision.value = result.revision; + + // Update url-bar, page title and footer + window.history.replaceState(null, result.title, result.slug); + document.querySelector("title").textContent = result.title; revision.textContent = result.revision; lastUpdated.textContent = result.created; + + // Update body: rendered.innerHTML = result.rendered; - article.classList.remove('edit'); + + // Update form: + form.elements.base_revision.value = result.revision; + for (const element of form.elements) { + element.defaultValue = element.value; + } + + container.classList.remove('edit'); textarea.disabled = false; }() @@ -82,7 +94,7 @@ function openEditor() { ev.preventDefault(); ev.stopPropagation(); - article.classList.remove('edit'); + container.classList.remove('edit'); form.reset(); }); } diff --git a/assets/style.css b/assets/style.css index f8c538b..35ca092 100644 --- a/assets/style.css +++ b/assets/style.css @@ -91,7 +91,7 @@ body { display: flex; flex-direction: column; } -article { +.container { flex: 1; } @@ -146,6 +146,15 @@ textarea { overflow: hidden; } +h1>input { + font: inherit; + border: none; + background: none; + padding: 0; + + width: 100%; +} + .shadow-control { visibility: hidden; position: fixed; diff --git a/src/article_resource.rs b/src/article_resource.rs index 9edfcd1..d065e54 100644 --- a/src/article_resource.rs +++ b/src/article_resource.rs @@ -86,6 +86,7 @@ impl Resource for ArticleResource { revision: i32, created: &'a chrono::DateTime, + slug: &'a str, title: &'a str, raw: &'a str, rendered: String, @@ -106,6 +107,7 @@ impl Resource for ArticleResource { article_id: data.article_id, revision: data.revision, created: &Local.from_utc_datetime(&data.created), + slug: &data.slug, title: &data.title, raw: &data.body, rendered: render_markdown(&data.body), @@ -125,12 +127,22 @@ impl Resource for ArticleResource { #[derive(Deserialize)] struct UpdateArticle { base_revision: i32, + title: String, body: String, } + #[derive(BartDisplay)] + #[template="templates/article_revision_contents.html"] + struct Template<'a> { + title: &'a str, + rendered: String, + } + #[derive(Serialize)] struct PutResponse<'a> { + slug: &'a str, revision: i32, + title: &'a str, rendered: &'a str, created: &'a str, } @@ -143,15 +155,20 @@ impl Resource for ArticleResource { .map_err(Into::into) }) .and_then(move |update: UpdateArticle| { - self.state.update_article(self.article_id, update.base_revision, update.body) + self.state.update_article(self.article_id, update.base_revision, update.title, update.body) }) .and_then(|updated| { futures::finished(Response::new() .with_status(hyper::StatusCode::Ok) .with_header(ContentType(APPLICATION_JSON.clone())) .with_body(serde_json::to_string(&PutResponse { + slug: &updated.slug, revision: updated.revision, - rendered: &render_markdown(&updated.body), + title: &updated.title, + rendered: &Template { + title: &updated.title, + rendered: render_markdown(&updated.body), + }.to_string(), created: &Local.from_utc_datetime(&updated.created).to_string(), }).expect("Should never fail")) ) diff --git a/src/state.rs b/src/state.rs index 61494eb..3551bff 100644 --- a/src/state.rs +++ b/src/state.rs @@ -26,7 +26,7 @@ pub enum SlugLookup { Redirect(String), } -fn decide_slug(conn: &SqliteConnection, prev_title: &str, title: &str, prev_slug: &str) -> Result { +fn decide_slug(conn: &SqliteConnection, article_id: i32, prev_title: &str, title: &str, prev_slug: &str) -> Result { if title == prev_title { return Ok(prev_slug.to_owned()); } @@ -44,6 +44,7 @@ fn decide_slug(conn: &SqliteConnection, prev_title: &str, title: &str, prev_slug loop { let slug_in_use = article_revisions::table + .filter(article_revisions::article_id.ne(article_id)) .filter(article_revisions::slug.eq(&slug)) .filter(article_revisions::latest.eq(true)) .count() @@ -124,7 +125,9 @@ impl State { }) } - pub fn update_article(&self, article_id: i32, base_revision: i32, body: String) -> CpuFuture { + pub fn update_article(&self, article_id: i32, base_revision: i32, title: String, body: String) + -> CpuFuture + { let connection_pool = self.connection_pool.clone(); self.cpu_pool.spawn_fn(move || { @@ -150,8 +153,7 @@ impl State { } let new_revision = base_revision + 1; - let title = prev_title.clone(); // TODO Have title be a parameter to this function - let slug = decide_slug(&*conn, &prev_title, &title, &prev_slug)?; + let slug = decide_slug(&*conn, article_id, &prev_title, &title, &prev_slug)?; #[derive(Insertable)] #[table_name="article_revisions"] diff --git a/templates/article_revision.html b/templates/article_revision.html index b931400..0658dab 100644 --- a/templates/article_revision.html +++ b/templates/article_revision.html @@ -1,26 +1,32 @@ +
+
+{{>article_revision_contents.html}} +
+ +
+
+
-

{{title}}

+

-
-{{{rendered}}} -
-
- - - - -
- Cancel - -
- -
+ + +
+
+ Cancel + +
+ + +
+
+