diff --git a/Cargo.lock b/Cargo.lock index 4530c42..97d66c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -518,6 +518,7 @@ dependencies = [ "rusqlite", "serde", "serde_json", + "uuid 1.3.0", ] [[package]] @@ -2431,6 +2432,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" dependencies = [ "getrandom", + "rand", "serde", ] diff --git a/Cargo.toml b/Cargo.toml index fc5bc06..5ab8a72 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,8 @@ edition = "2021" clap = { version = "4.0.18", features = ["derive"] } +uuid = {version = "1.3.0", features=["v4", "fast-rng"]} + actix-web = "4" actix-files = "0.6.2" actix-session = { version = "0.7.2", features = ["cookie-session"] } diff --git a/db/db.sql b/db/db.sql index b1e54c7..b5a5f3e 100644 --- a/db/db.sql +++ b/db/db.sql @@ -4,4 +4,8 @@ create table pages ( page_text text, active boolean default true not null, primary key (domain, page_name) +); + +create table pages_histo ( + ); \ No newline at end of file diff --git a/db/db.sqlite3 b/db/db.sqlite3 index 16d71f0..b5a0d8c 100644 Binary files a/db/db.sqlite3 and b/db/db.sqlite3 differ diff --git a/src/commons.rs b/src/commons.rs index 041edc2..6e86091 100644 --- a/src/commons.rs +++ b/src/commons.rs @@ -29,7 +29,7 @@ impl Arguments { #[derive(Clone)] pub struct AppData { - pub name: String, - pub root: String, - pub pool: Pool, + pub app_name: String, + pub base_url: String, + pub db_pool: Pool, } diff --git a/src/db.rs b/src/db.rs index 11a91a4..e1c6a2c 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,9 +1,16 @@ use actix_web::{error, web, Error}; use serde::{Deserialize, Serialize}; +use uuid::Uuid; pub type Pool = r2d2::Pool; pub type Connection = r2d2::PooledConnection; +#[allow(unused)] +fn uuid4() -> String { + let id = Uuid::new_v4(); + id.to_string() +} + #[derive(Debug, Serialize, Deserialize)] pub struct Page { pub domain: String, @@ -11,7 +18,38 @@ pub struct Page { pub page_text: String, } -pub async fn get_page_by_name(pool: &Pool, domain: String, pagename: String) -> Result, Error> { +pub struct Domain { + pub domain: String, + pub domain_name: String, +} + +pub async fn get_domains(pool: &Pool) -> Result, Error> { + let pool = pool.clone(); + + let conn = web::block(move || pool.get()) + .await? + .map_err(error::ErrorInternalServerError)?; + web::block(move || { + let mut stmt = conn + .prepare("SELECT distinct domain, REPLACE(domain, '_', ' ') from pages WHERE active=true order by domain")?; + + stmt.query_map([], |row| { + Ok(Domain { + domain: row.get(0)?, + domain_name: row.get(1)?, + }) + }) + .and_then(Iterator::collect) + }) + .await? + .map_err(error::ErrorInternalServerError) +} + +pub async fn get_page_by_name( + pool: &Pool, + domain: String, + pagename: String, +) -> Result, Error> { let pool = pool.clone(); let conn = web::block(move || pool.get()) @@ -35,7 +73,12 @@ pub async fn get_page_by_name(pool: &Pool, domain: String, pagename: String) -> .map_err(error::ErrorInternalServerError) } -pub async fn update_page(pool: &Pool, domain: String, page_name: String, page_text: String) -> Result { +pub async fn update_page( + pool: &Pool, + domain: String, + page_name: String, + page_text: String, +) -> Result { let pool = pool.clone(); let conn = web::block(move || pool.get()) diff --git a/src/index.rs b/src/index.rs index cd073d7..c52fff5 100644 --- a/src/index.rs +++ b/src/index.rs @@ -5,17 +5,23 @@ use askama_actix::Template; use askama_actix::TemplateToResponse; use crate::commons::AppData; +use crate::db; +use crate::db::Domain; #[derive(Template)] #[template(path = "index.html")] pub struct PageTemplate { - pub name: String, - pub root: String, + pub app_name: String, + pub base_url: String, + pub domains: Vec, } #[get("/")] async fn index(data: web::Data) -> impl Responder { - let name = data.name.to_owned(); - let root = data.root.to_owned(); - PageTemplate { name, root }.to_response() + let app_name = data.app_name.to_owned(); + let base_url = data.base_url.to_owned(); + + let domains = db::get_domains(&data.db_pool).await.unwrap(); + + PageTemplate { app_name, base_url, domains }.to_response() } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 208237c..9a14f11 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,16 +14,16 @@ async fn main() -> std::io::Result<()> { let ip = args.ip; let port = args.port; - let root = args.root; + let base_url = args.root; let db = args.db; let manager = SqliteConnectionManager::file(db); let pool = Pool::new(manager).unwrap(); let appdata = AppData { - name: String::from("CheezeNotes"), - root, - pool: pool.clone(), + app_name: String::from("CheezeNotes"), + base_url, + db_pool: pool.clone(), }; HttpServer::new(move || { diff --git a/src/page.rs b/src/page.rs index 9f59d74..95dd73f 100644 --- a/src/page.rs +++ b/src/page.rs @@ -1,4 +1,5 @@ use actix_web::http::header::ContentType; +use actix_web::web::Query; use actix_web::{get, put, Responder}; use actix_web::{web, HttpResponse}; use serde::Deserialize; @@ -12,36 +13,49 @@ use crate::db; #[derive(Template)] #[template(path = "page.html")] pub struct PageTemplate { - pub name: String, - pub root: String, + pub app_name: String, + pub base_url: String, pub md: String, pub init: String, } #[derive(Debug, Deserialize)] +#[allow(non_snake_case)] struct QueryParams { pub data: Option, + pub fromDomain: Option, + pub fromPage: Option, } -async fn get_data(data: & web::Data, domain: String, page_name: String) -> String { - let fut_page_datas = db::get_page_by_name(&data.pool, domain.to_owned(), page_name.to_owned()); +fn new_page_text(page_name: String, domain_from: &Option, page_from: &Option) -> String { + let mut retour = String::from(""); + if let Some(domain_f) = domain_from { + if let Some(page_f) = page_from { + retour = format!("[retour](/{}/{})\n", domain_f, page_f); + } + } + retour + "# " + page_name.replace("_", " ").as_str() +} + +async fn get_data(data: &web::Data, domain: String, page_name: String, params: &Query) -> String { + let fut_page_datas = db::get_page_by_name(&data.db_pool, domain.to_owned(), page_name.to_owned()); let page_datas = fut_page_datas.await.unwrap(); match page_datas.first() { - None => String::from("# ") + page_name.replace("_", " ").as_str(), + None => new_page_text(page_name, ¶ms.fromDomain, ¶ms.fromPage), Some(dat) => (*dat.page_text).to_string(), } } #[get("/{domain}/{page}")] async fn page( - path: web::Path<(String, String,)>, + path: web::Path<(String, String)>, data: web::Data, params: web::Query, ) -> impl Responder { let domain = &path.0; let page_name = &path.1; - let md = get_data(&data, domain.to_owned(), page_name.to_owned()).await; + let md = get_data(&data, domain.to_owned(), page_name.to_owned(), ¶ms).await; match ¶ms.data { Some(_) => { @@ -52,13 +66,13 @@ async fn page( None => {} } - let name = data.name.to_owned() + " - " + page_name.as_str(); - let root = data.root.to_owned(); + let app_name = data.app_name.to_owned() + " - " + page_name.as_str(); + let base_url = data.base_url.to_owned(); //let init = String::from("init();"); - let init = format!("init();"); + let init = format!("init({:?}, {:?});", domain, page_name); PageTemplate { - name, - root, + app_name, + base_url, md, init, } @@ -76,7 +90,7 @@ async fn save_page( if pagename == "index" { return HttpResponse::Ok(); } - db::update_page(&data.pool, domain.to_owned(), pagename.to_owned(), body) + db::update_page(&data.db_pool, domain.to_owned(), pagename.to_owned(), body) .await .unwrap(); HttpResponse::Ok() diff --git a/static/cheezenotes.css b/static/cheezenotes.css index 0b1d64a..1ec4f7f 100644 --- a/static/cheezenotes.css +++ b/static/cheezenotes.css @@ -35,6 +35,11 @@ body { background-color: #dddddd; } +p.domain { + padding-left: 2rem; + font-size: 2rem; +} + div#content { position: absolute; margin: 0; @@ -47,9 +52,11 @@ div#content { } div#margindiv { - max-width: 1200px; + /*max-width: 1600px; margin-left: auto; - margin-right: auto; + margin-right: auto;*/ + margin-left: .5rem; + margin-right: .5rem; top: 0; bottom: 0; } @@ -60,8 +67,8 @@ div#cheezenotes { margin-top: 0; margin-bottom: 3rem; padding-top: 1rem; - padding-left: 3rem; - padding-right: 3rem; + padding-left: 1rem; + padding-right: 1rem; padding-bottom: 1rem; background-color: #ffffff; min-height: 100%; @@ -79,9 +86,11 @@ div#buttons { top: 0; left: 0; right: 0; + /*margin-left: .5rem; + margin-right: .5rem; margin-left: auto; margin-right: auto; - max-width: 1200px; + max-width: 1600px;*/ } div#buttons button.button { @@ -142,9 +151,11 @@ div#buttons #lockButtonLabel { } div.ta { - margin-left: auto; + margin-left: .5rem; + margin-right: .5rem; + /*margin-left: auto; margin-right: auto; - max-width: 1200px; + max-width: 1600px;*/ } textarea#ta { @@ -171,6 +182,10 @@ div#cheezenotes:focus { outline: none; } +div#cheezenotes input.checkbox { + vertical-align: bottom; +} + div#cheezenotes div.line { border-bottom: 1px solid #dddddd; padding-top: 0rem; diff --git a/static/modules/cheezenotes.js b/static/modules/cheezenotes.js index 1afb227..b81f16f 100644 --- a/static/modules/cheezenotes.js +++ b/static/modules/cheezenotes.js @@ -356,8 +356,10 @@ function onpopstate(e) { }).catch((error) => { alert(error); }); } -function init() { +function init(domain, page) { let cheezenotes = document.getElementById('cheezenotes'); + window.domain = domain; + window.page = page; dpwidth(cheezenotes); diff --git a/static/modules/md.js b/static/modules/md.js index 833704f..f7b5529 100644 --- a/static/modules/md.js +++ b/static/modules/md.js @@ -104,7 +104,7 @@ function onlink(e) { if (link.host !== document.location.host) { open(link.href); } else { - fetch(link.href + "?data=").then((response) => { + fetch(link.href + '?data=&fromDomain=' + window.domain + '&fromPage=' + window.page).then((response) => { let ta = document.getElementById('ta'); response.text().then((data) => { let content = document.getElementById('content'); @@ -114,6 +114,15 @@ function onlink(e) { window.history.pushState({}, "", link.href); document.title = 'CheezeNotes - ' + link.getAttribute('data-href'); ta.value = data; + let url = link.getAttribute('data-href').split('/'); + let page = url[0]; + let domain = window.domain; + if (url.length == 3) { + domain = url[1]; + page = url[2]; + } + window.domain = domain; + window.page = page; load(document.getElementById('ta'), cheezenotes); /*let editModeButton = document.getElementById('editModeButton'); @@ -198,6 +207,14 @@ function formatLine(line) { token = /^(\s*>(\s|$))/i; elem.classList.add('bq1'); elem.classList.add('bq'); + } else if (line.match(/^\s*\[[xXvV]?\]\s+/i)) { + //token = /^(\s*\[[xXvV]?\]\s+)/i; + let checked = ''; + if (line.match(/^\s*\[[xXvV]\]\s+/i)) { + checked = ' checked="checked"'; + } + line = line.replace(/^(\s*\[[xXvV]?\]\s+)/i, '$1') + elem.classList.add('checkbox'); } else { elem.classList.add('body'); } @@ -534,12 +551,37 @@ function addLink(line, listLink) { return line; } -function formatLink(line) { - line = line.replace(/(\[!([^\]]*?)\]\(([^\)]+?)\))/ig, '[!$2]($3)'); - line = line.replace(/(\[([^\]]+?)\]\(([^\)]+?)\))/ig, '[$2]($3)'); - line = line.replace(/(\[([^\]]+?)\]\(\))/ig, '[$2]()'); - line = line.replace(/(\[\]\(([^\)]+?)\))/ig, '[]($2)'); - return line; +/*function formatLink(link) { + link = link.replace(/(\[!([^\]]*?)\]\(([^\)]+?)\))/i, '[!$2]($3)'); + link = link.replace(/(\[([^\]]+?)\]\(([^\)]+?)\))/i, '[$2]($3)'); + link = link.replace(/(\[([^\]]+?)\]\(\))/i, '[$2]()'); + link = link.replace(/(\[\]\(([^\)]+?)\))/i, '[]($2)'); + return link; +}*/ + +function formatLink(link) { + let matches = link.match(/\[(.*)\]\((.*)\)/); + let libelle = matches[1]; + let url = matches[2]; + if (url == '' && libelle == '') { + return link; + } + let href = url; + if (href == '') { + href = libelle; + } + if (href.match(/^[^\:\/]+\/.*$/)) { + href = '/' + href; + } + if (libelle == '') { + return '[](' + url + ')'; + } else { + if (libelle.startsWith('!')) { + return '[' + libelle + '](' + url + ')'; + } else { + return '[' + libelle + '](' + url + ')'; + } + } } function addBold(line) { diff --git a/templates/index.html b/templates/index.html index de55b3f..c2448ee 100644 --- a/templates/index.html +++ b/templates/index.html @@ -7,10 +7,13 @@ - {{name}} - + {{app_name}} + -

+

{{app_name}}

+ {% for domain in domains %} +

{{ domain.domain_name }}

+ {% endfor %} diff --git a/templates/page.html b/templates/page.html index 618ccc3..57d124e 100644 --- a/templates/page.html +++ b/templates/page.html @@ -9,9 +9,9 @@ - {{name}} - - + {{app_name}} + + @@ -23,7 +23,7 @@