Commit f492f9e2c3b89302e7f0882e0cc7bd939d6e9b03
1 parent
c179a4f8
Add crate for common types and code
Showing
8 changed files
with
224 additions
and
40 deletions
common/Cargo.toml
0 → 100644
| 1 | +# This is from the webpage: | |
| 2 | +# https://www.developer.com/languages/creating-an-api-with-rust-and-sqlite/ | |
| 3 | +# I have fixed some things manually as the code on that page did not compile | |
| 4 | +# without. | |
| 5 | + | |
| 6 | +# Additional informations at https://actix.rs/docs/databases/ assume one | |
| 7 | +# should use web::block to access the database... | |
| 8 | +# TODO check what is the difference to this approach. | |
| 9 | +# - well, we use web::block already for write actions. | |
| 10 | + | |
| 11 | +# Introduction to rust async: | |
| 12 | +# https://gruberbastian.com/posts/rust_async/ | |
| 13 | +# https://blog.logrocket.com/a-practical-guide-to-async-in-rust/ | |
| 14 | +# https://os.phil-opp.com/async-await/ | |
| 15 | + | |
| 16 | +# Simple explanation on technical terms synchronous, asynchronous, concurrent | |
| 17 | +# and parallel. | |
| 18 | +# https://medium.com/plain-and-simple/synchronous-vs-asynchronous-vs-concurrent-vs-parallel-4342bfb8b9f2 | |
| 19 | + | |
| 20 | +[package] | |
| 21 | +name = "artshop-common" | |
| 22 | +version = "0.1.0" | |
| 23 | +workspace = ".." | |
| 24 | +edition = "2018" | |
| 25 | + | |
| 26 | +[dependencies] | |
| 27 | +serde = "^1.0" | ... | ... |
common/src/lib.rs
0 → 100644
| 1 | +pub mod types; | ... | ... |
common/src/types.rs
0 → 100644
| 1 | +use serde::{Deserialize, Serialize}; | |
| 2 | + | |
| 3 | +#[derive(Debug, Clone, Deserialize, Serialize)] | |
| 4 | +pub enum Either<L, R> { | |
| 5 | + Left(L), | |
| 6 | + Reight(R) | |
| 7 | +} | |
| 8 | + | |
| 9 | +#[derive(Clone, Debug, Serialize, Deserialize)] | |
| 10 | +pub struct MarkdownJson { | |
| 11 | + pub name: String, | |
| 12 | + pub content: String, | |
| 13 | + pub number_of_versions: i32, | |
| 14 | + pub date_created: String, | |
| 15 | + pub date_updated: String, | |
| 16 | +} | ... | ... |
| ... | ... | @@ -2,6 +2,7 @@ use std::sync::Arc; |
| 2 | 2 | use crate::schema::*; |
| 3 | 3 | use crate::error::Error; |
| 4 | 4 | use crate::Pool; |
| 5 | +use artshop_common::types::MarkdownJson; | |
| 5 | 6 | use diesel::prelude::*; |
| 6 | 7 | use diesel::{ |
| 7 | 8 | dsl::{delete, insert_into, update}, |
| ... | ... | @@ -14,7 +15,7 @@ use flate2::Compression; |
| 14 | 15 | use flate2::write::{DeflateEncoder, DeflateDecoder}; |
| 15 | 16 | |
| 16 | 17 | |
| 17 | -#[derive(Debug, Serialize, Deserialize, Queryable, Identifiable)] | |
| 18 | +#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable)] | |
| 18 | 19 | pub struct Markdown { |
| 19 | 20 | pub id: i32, |
| 20 | 21 | pub name: String, |
| ... | ... | @@ -55,12 +56,23 @@ pub struct MarkdownDiffNew<'a> { |
| 55 | 56 | |
| 56 | 57 | #[derive(Debug, Serialize, Deserialize, AsChangeset)] |
| 57 | 58 | #[table_name="markdowns"] |
| 58 | -pub struct MarkdownJson { | |
| 59 | - pub name: String, | |
| 60 | - pub content: String, | |
| 59 | +struct MarkdownChange<'a> { | |
| 60 | + pub name: &'a str, | |
| 61 | + pub content: &'a str, | |
| 61 | 62 | pub number_of_versions: i32, |
| 62 | - pub date_created: String, | |
| 63 | - pub date_updated: String, | |
| 63 | + pub date_created: &'a str, | |
| 64 | + pub date_updated: &'a str, | |
| 65 | +} | |
| 66 | + | |
| 67 | +impl<'a> From<&'a MarkdownJson> for MarkdownChange<'a> { | |
| 68 | + fn from(md: &'a MarkdownJson) -> Self { | |
| 69 | + Self { name: md.name.as_str() | |
| 70 | + , content: md.content.as_str() | |
| 71 | + , number_of_versions: md.number_of_versions | |
| 72 | + , date_created: md.date_created.as_str() | |
| 73 | + , date_updated: md.date_updated.as_str() | |
| 74 | + } | |
| 75 | + } | |
| 64 | 76 | } |
| 65 | 77 | |
| 66 | 78 | pub(crate) enum Action { |
| ... | ... | @@ -108,7 +120,7 @@ pub(crate) fn get_markdowns(pool: Arc<Pool>) -> Result<Vec<Markdown>, Error> |
| 108 | 120 | |
| 109 | 121 | pub(crate) fn get_markdown( pool: Arc<Pool> |
| 110 | 122 | , ident: &str |
| 111 | - , patch: Option<i32> ) -> Result<Markdown, Error> | |
| 123 | + , patch: Option<i32> ) -> Result<Vec<Markdown>, Error> | |
| 112 | 124 | { |
| 113 | 125 | use crate::schema::markdowns::dsl::*; |
| 114 | 126 | use crate::schema::markdown_diffs::dsl::*; |
| ... | ... | @@ -118,6 +130,8 @@ pub(crate) fn get_markdown( pool: Arc<Pool> |
| 118 | 130 | . filter(name.eq(ident)) |
| 119 | 131 | . first::<Markdown>(&db_connection)?; |
| 120 | 132 | |
| 133 | + let mut mds = vec![markdown.clone()]; | |
| 134 | + | |
| 121 | 135 | if let Some(patch) = patch { |
| 122 | 136 | let result = markdown_diffs . filter(markdown_id.eq(markdown.id)) |
| 123 | 137 | . filter(diff_id.ge(patch)) |
| ... | ... | @@ -130,11 +144,13 @@ pub(crate) fn get_markdown( pool: Arc<Pool> |
| 130 | 144 | let decomp = decoder.reset(Vec::new()).unwrap(); |
| 131 | 145 | let decomp = Patch::from_str( |
| 132 | 146 | std::str::from_utf8(decomp.as_ref()).unwrap()).unwrap(); |
| 133 | - markdown.content = apply(&mut markdown.content, &decomp).unwrap(); | |
| 147 | + markdown.content = apply(&markdown.content, &decomp).unwrap(); | |
| 148 | + markdown.date_updated = patch.date_created; | |
| 149 | + mds.push(markdown.clone()); | |
| 134 | 150 | } |
| 135 | 151 | }; |
| 136 | 152 | |
| 137 | - Ok(markdown) | |
| 153 | + Ok(mds) | |
| 138 | 154 | } |
| 139 | 155 | |
| 140 | 156 | pub(crate) fn delete_markdown( pool: Arc<Pool> |
| ... | ... | @@ -185,7 +201,7 @@ pub(crate) fn update_markdown( pool: Arc<Pool> |
| 185 | 201 | insert_into(markdown_diffs) . values(&new_markdown_diff) |
| 186 | 202 | . execute(&db_connection)?; |
| 187 | 203 | |
| 188 | - update(&markdown).set(&item).execute(&db_connection)?; | |
| 204 | + update(&markdown).set(MarkdownChange::from(&item)).execute(&db_connection)?; | |
| 189 | 205 | |
| 190 | 206 | Ok(()) |
| 191 | 207 | }).unwrap(); | ... | ... |
| ... | ... | @@ -3,6 +3,7 @@ use crate::Pool; |
| 3 | 3 | |
| 4 | 4 | use actix_web::{Error, HttpResponse, web}; |
| 5 | 5 | use anyhow::Result; |
| 6 | +use artshop_common::types::MarkdownJson; | |
| 6 | 7 | use serde::Deserialize; |
| 7 | 8 | |
| 8 | 9 | #[derive(Debug, Deserialize)] |
| ... | ... | @@ -38,7 +39,7 @@ pub async fn get_markdown( pool: web::Data<Pool> |
| 38 | 39 | |
| 39 | 40 | pub async fn update_markdown( pool: web::Data<Pool> |
| 40 | 41 | , name: web::Path<String> |
| 41 | - , item: web::Json<markdown::MarkdownJson> ) | |
| 42 | + , item: web::Json<MarkdownJson> ) | |
| 42 | 43 | -> Result<HttpResponse, Error> |
| 43 | 44 | { |
| 44 | 45 | let pool = pool.into_inner(); | ... | ... |
| ... | ... | @@ -12,6 +12,7 @@ crate-type = ["cdylib", "rlib"] |
| 12 | 12 | default = ["console_error_panic_hook"] |
| 13 | 13 | |
| 14 | 14 | [dependencies] |
| 15 | +artshop-common = { path = "../common" } | |
| 15 | 16 | katex = { version = "0.4", default-features = false, features = ["wasm-js"] } |
| 16 | 17 | pulldown-cmark = "0.9" |
| 17 | 18 | console_log = "^0.1" | ... | ... |
| 1 | 1 | mod data; |
| 2 | 2 | |
| 3 | +use artshop_common::types::MarkdownJson; | |
| 3 | 4 | use js_sys::JsString; |
| 4 | 5 | use log::Level; |
| 5 | 6 | use mogwai::prelude::*; |
| ... | ... | @@ -25,22 +26,13 @@ fn md_to_html(source: &str) -> String { |
| 25 | 26 | html_output |
| 26 | 27 | } |
| 27 | 28 | |
| 28 | -#[derive(Clone, Debug, Serialize, Deserialize)] | |
| 29 | -pub struct MarkdownJson { | |
| 30 | - pub name: String, | |
| 31 | - pub content: String, | |
| 32 | - pub number_of_versions: i32, | |
| 33 | - pub date_created: String, | |
| 34 | - pub date_updated: String, | |
| 35 | -} | |
| 36 | - | |
| 37 | -async fn md_from_db() -> MarkdownJson { | |
| 29 | +async fn md_from_db() -> Vec<MarkdownJson> { | |
| 38 | 30 | let window = web_sys::window().unwrap(); |
| 39 | 31 | let mut opts = RequestInit::new(); |
| 40 | 32 | opts.method("GET").mode(RequestMode::Cors); |
| 41 | 33 | |
| 42 | 34 | let request = Request::new_with_str_and_init( |
| 43 | - "/api/v0/markdowns/md-example?patch=3" | |
| 35 | + "/api/v0/markdowns/md-example?patch=1" // patch=1 always gets all patches. | |
| 44 | 36 | , &opts ).unwrap(); |
| 45 | 37 | request.headers().set("Accept", "application/json").unwrap(); |
| 46 | 38 | |
| ... | ... | @@ -51,9 +43,9 @@ async fn md_from_db() -> MarkdownJson { |
| 51 | 43 | . await.unwrap() |
| 52 | 44 | . dyn_into::<JsString>().unwrap() |
| 53 | 45 | ); |
| 54 | - let data :MarkdownJson = serde_json::from_str(data.as_str()).unwrap(); | |
| 46 | + let data :Vec<MarkdownJson> = serde_json::from_str(data.as_str()).unwrap(); | |
| 55 | 47 | |
| 56 | - data.clone() | |
| 48 | + data | |
| 57 | 49 | } |
| 58 | 50 | |
| 59 | 51 | async fn md_to_db(md :MarkdownJson) { |
| ... | ... | @@ -80,7 +72,7 @@ async fn md_to_db(md :MarkdownJson) { |
| 80 | 72 | async fn editor_logic( mut rx_logic: broadcast::Receiver<AppLogic> |
| 81 | 73 | , tx_view: broadcast::Sender<String> |
| 82 | 74 | , mut rx_dom: broadcast::Receiver<Dom> |
| 83 | - , md :MarkdownJson ) { | |
| 75 | + , md :Vec<MarkdownJson> ) { | |
| 84 | 76 | let dom = rx_dom.next().await.unwrap(); |
| 85 | 77 | let mut show_edit = false; |
| 86 | 78 | |
| ... | ... | @@ -98,11 +90,11 @@ async fn editor_logic( mut rx_logic: broadcast::Receiver<AppLogic> |
| 98 | 90 | fn update(dom: &Dom) { |
| 99 | 91 | if let Either::Left(dom_js) = dom.inner_read() { |
| 100 | 92 | dom_js . to_owned() |
| 101 | - . dyn_into::<Node>().unwrap() | |
| 102 | - . child_nodes().get(1).unwrap() | |
| 103 | - . child_nodes().get(1).unwrap() | |
| 104 | - . dyn_into::<HtmlElement>().unwrap() | |
| 105 | - . set_inner_html(md_to_html(get_md(dom).as_str()).as_str()) | |
| 93 | + . dyn_into::<Node>().unwrap() | |
| 94 | + . child_nodes().get(1).unwrap() | |
| 95 | + . child_nodes().get(1).unwrap() | |
| 96 | + . dyn_into::<HtmlElement>().unwrap() | |
| 97 | + . set_inner_html(md_to_html(get_md(dom).as_str()).as_str()) | |
| 106 | 98 | }; |
| 107 | 99 | } |
| 108 | 100 | |
| ... | ... | @@ -137,7 +129,7 @@ async fn editor_logic( mut rx_logic: broadcast::Receiver<AppLogic> |
| 137 | 129 | while let Some(msg) = rx_logic.next().await { |
| 138 | 130 | match msg { |
| 139 | 131 | AppLogic::Store => { |
| 140 | - let mut new_md = md.clone(); | |
| 132 | + let mut new_md = md[0].clone(); | |
| 141 | 133 | new_md.content = get_md(&dom); |
| 142 | 134 | md_to_db(new_md).await; |
| 143 | 135 | }, |
| ... | ... | @@ -158,7 +150,7 @@ async fn editor_logic( mut rx_logic: broadcast::Receiver<AppLogic> |
| 158 | 150 | fn editor_view( tx_logic: broadcast::Sender<AppLogic> |
| 159 | 151 | , rx_view: broadcast::Receiver<String> |
| 160 | 152 | , tx_dom: broadcast::Sender<Dom> |
| 161 | - , md: &MarkdownJson | |
| 153 | + , md: &Vec<MarkdownJson> | |
| 162 | 154 | ) -> ViewBuilder<Dom> { |
| 163 | 155 | let ns = "http://www.w3.org/2000/svg"; |
| 164 | 156 | |
| ... | ... | @@ -190,22 +182,151 @@ fn editor_view( tx_logic: broadcast::Sender<AppLogic> |
| 190 | 182 | <div contenteditable="true" |
| 191 | 183 | style:cursor="text" |
| 192 | 184 | style:display=("none", rx_view)> |
| 193 | - <pre on:click=store_filter>{md.content.clone()}</pre> | |
| 185 | + <pre on:click=store_filter>{md[0].content.clone()}</pre> | |
| 194 | 186 | </div> |
| 195 | 187 | <div> |
| 188 | + <div> | |
| 189 | + <button> | |
| 190 | + <svg xmlns=ns viewBox="0 -1 24 24" | |
| 191 | + style:width="1.5em" style:height="1.5em" | |
| 192 | + style:fill="none"> | |
| 193 | + <path xmlns=ns | |
| 194 | + style:fill="black" | |
| 195 | + d="M9.17154 11.508 | |
| 196 | + L7.75732 10.0938 | |
| 197 | + L12 5.85113 | |
| 198 | + L16.2426 10.0938 | |
| 199 | + L14.8284 11.508 | |
| 200 | + L12 8.67956 | |
| 201 | + L9.17154 11.508Z"/> | |
| 202 | + <path xmlns=ns | |
| 203 | + style:fill="black" | |
| 204 | + d="M9.17154 12.492 | |
| 205 | + L7.75732 13.9062 | |
| 206 | + L12 18.1489 | |
| 207 | + L16.2426 13.9062 | |
| 208 | + L14.8284 12.492 | |
| 209 | + L12 15.3204 | |
| 210 | + L9.17154 12.492Z"/> | |
| 211 | + <path xmlns=ns | |
| 212 | + style:fill="black" | |
| 213 | + style:fill_rule="evenodd" | |
| 214 | + style:clip_rule="evenodd" | |
| 215 | + d="M1 5 | |
| 216 | + C1 2.79086 2.79086 1 5 1 | |
| 217 | + H19 | |
| 218 | + C21.2091 1 23 2.79086 23 5 | |
| 219 | + V19 | |
| 220 | + C23 21.2091 21.2091 23 19 23 | |
| 221 | + H5 | |
| 222 | + C2.79086 23 1 21.2091 1 19 | |
| 223 | + V5Z | |
| 224 | + M5 3 | |
| 225 | + H19 | |
| 226 | + C20.1046 3 21 3.89543 21 5 | |
| 227 | + V19 | |
| 228 | + C21 20.1046 20.1046 21 19 21 | |
| 229 | + H5 | |
| 230 | + C3.89543 21 3 20.1046 3 19 | |
| 231 | + V5 | |
| 232 | + C3 3.89543 3.89543 3 5 3Z"/> | |
| 233 | + </svg> | |
| 234 | + </button> | |
| 235 | + <button> | |
| 236 | + <svg xmlns=ns viewBox="0 -1 32 32" | |
| 237 | + style:width="1.5em" style:height="1.5em" | |
| 238 | + style:enable_background="new 0 0 32 32" | |
| 239 | + style:fill="none" | |
| 240 | + style:stroke="#000" | |
| 241 | + style:stroke_width="2" | |
| 242 | + style:stroke_linecap="round" | |
| 243 | + style:stroke_linejoin="round" | |
| 244 | + style:stroke_miterlimit="10"> | |
| 245 | + <ellipse xmlns=ns | |
| 246 | + cx="14" cy="8" rx="10" ry="5"/> | |
| 247 | + <line xmlns=ns | |
| 248 | + x1="24" y1="16" x2="24" y2="8"/> | |
| 249 | + <path xmlns=ns | |
| 250 | + d="M4,8 v8 c0,2.8,4.5,5,10,5 | |
| 251 | + c1.2,0,2.3-0.1,3.4-0.3"/> | |
| 252 | + <path xmlns=ns | |
| 253 | + d="M4,16 v8 c0,2.8,4.5,5,10,5 | |
| 254 | + c2,0,3.8-0.3,5.3-0.8"/> | |
| 255 | + <circle xmlns=ns | |
| 256 | + cx="24" cy="23" r="7"/> | |
| 257 | + <line xmlns=ns | |
| 258 | + x1="24" y1="16" x2="24" y2="26"/> | |
| 259 | + <polyline xmlns=ns | |
| 260 | + points="21,23 24,26 27,23"/> | |
| 261 | + </svg> | |
| 262 | + </button> | |
| 263 | + <button> | |
| 264 | + <svg xmlns=ns viewBox="10.3 3.8 76.2 88.7" | |
| 265 | + style:width="1.5em" style:height="1.5em"> | |
| 266 | + <g xmlns=ns id="_x37_0"> | |
| 267 | + <polygon xmlns=ns | |
| 268 | + points="35.4,18.1 31.1,4.3 31.1,16.3 | |
| 269 | + 24.5,16.3 24.5,10.9 18.3,18.9 | |
| 270 | + 13.8,23.7 17,23.7 19.8,31.8 | |
| 271 | + 27.9,34.1 27.9,37.8 38.7,41.8 | |
| 272 | + 38.7,34.1 38.7,30.4 38.7,25.2 | |
| 273 | + 46.8,25.2 "/> | |
| 274 | + <path xmlns=ns | |
| 275 | + d="M75.7,39.9 h-8.3 h-40.5 h-8.3 h-3 v9.5 | |
| 276 | + v2 h4.7 c2.2,13.3,6.8,42.2,6.8,42.2 h40 | |
| 277 | + c0,0,4.6-27.6,7-42.2 h4.7 v-2 v-9.5 | |
| 278 | + H75.7z | |
| 279 | + M67.7,51.4 l-2.6,15.6 l-6.1-6.9 l8-8.7 | |
| 280 | + H67.7z | |
| 281 | + M63.7,75.6 l-1.3,7.9 l-2.9-3.2 | |
| 282 | + L63.7,75.6z | |
| 283 | + M56.6,77.2 | |
| 284 | + L50,70 l6.2-6.7 l6.4,7.3 | |
| 285 | + L56.6,77.2z | |
| 286 | + M52.4,51.4 h8.9 l-5.1,5.5 l-4.8-5.4 | |
| 287 | + C51.8,51.4,52.1,51.4,52.4,51.4z | |
| 288 | + M53.3,60 l-6.2,6.8 l-6.6-7.2 l6.4-6.9 | |
| 289 | + L53.3,60z | |
| 290 | + M30.5,74.9 l4.6,5 l-3.2,3.5 | |
| 291 | + L30.5,74.9z | |
| 292 | + M31.4,69.6 l6.2-6.8 l6.6,7.2 l-6.2,6.8 | |
| 293 | + L31.4,69.6z | |
| 294 | + M41.9,51.4 c0.1,0,0.2,0,0.3,0 l-4.7,5.1 | |
| 295 | + l-4.7-5.1 | |
| 296 | + H41.9z | |
| 297 | + M27.1,51.4 l7.6,8.3 l-5.7,6.2l-2.3-14.5 | |
| 298 | + H27.1z | |
| 299 | + M34.6,86.7 l3.3-3.6 l3.3,3.6 | |
| 300 | + H34.6z | |
| 301 | + M47.1,86.7 l-6.2-6.8 l6.2-6.8 l6.6,7.2 | |
| 302 | + l-5.8,6.4 | |
| 303 | + H47.1z | |
| 304 | + M53.7,86.7 l2.9-3.2 l3,3.2 | |
| 305 | + H53.7z"/> | |
| 306 | + </g> | |
| 307 | + </svg> | |
| 308 | + </button> | |
| 196 | 309 | <button on:click=toggle_filter> |
| 197 | - <svg version="1.1" id="Capa_1" xmlns=ns | |
| 198 | - x="0px" y="0px" viewBox="0 0 220.001 220.001" | |
| 310 | + <svg xmlns=ns viewBox="0 0 220.001 220.001" | |
| 199 | 311 | style:width="1.5em" style:height="1.5em"> |
| 200 | 312 | <g xmlns=ns> |
| 201 | - <polygon xmlns=ns points="0,220 59.34,213.86 6.143,160.661"></polygon> | |
| 202 | - <path xmlns=ns d="M132.018,34.787l53.197,53.197L69.568,203.631L16.37, | |
| 203 | - 150.434L132.018,34.787z M212.696,60.502c9.738-9.738,9.742-25.527, | |
| 204 | - 0-35.268l-17.93-17.93c-9.738-9.74-25.529-9.738-35.268,0l-17.346, | |
| 205 | - 17.347l53.199,53.196L212.696,60.502z"></path> | |
| 313 | + <polygon xmlns=ns | |
| 314 | + points="0,220 59.34,213.86 6.143,160.661"/> | |
| 315 | + <path xmlns=ns | |
| 316 | + d="M132.018,34.787 l53.197,53.197 | |
| 317 | + L69.568,203.631 | |
| 318 | + L16.37,150.434 | |
| 319 | + L132.018,34.787z | |
| 320 | + M212.696,60.502 | |
| 321 | + c9.738,-9.738,9.742,-25.527,0,-35.268 | |
| 322 | + l-17.93,-17.93 | |
| 323 | + c-9.738,-9.74,-25.529,-9.738,-35.268,0 | |
| 324 | + l-17.346,17.347 l53.199,53.196 | |
| 325 | + L212.696,60.502z"/> | |
| 206 | 326 | </g> |
| 207 | 327 | </svg> |
| 208 | 328 | </button> |
| 329 | + </div> | |
| 209 | 330 | <div></div> |
| 210 | 331 | <div></div> |
| 211 | 332 | <div></div> | ... | ... |
Please
register
or
login
to post a comment