Content-Length: 85095 | pFad | http://github.com/postgresml/postgresml/pull/966.patch

thub.com From 2c046577a096f2e828961dae0e681f7b9dee8036 Mon Sep 17 00:00:00 2001 From: Lev Kokotov Date: Wed, 30 Aug 2023 21:40:53 -0700 Subject: [PATCH 1/6] More components --- pgml-apps/cargo-pgml-components/.gitignore | 1 + pgml-apps/cargo-pgml-components/Cargo.lock | 16 +- pgml-apps/cargo-pgml-components/Cargo.toml | 2 + .../cargo-pgml-components/src/frontend/mod.rs | 2 + .../src/frontend/sass.rs | 102 ++++++++++++ .../src/frontend/tools.rs | 22 +++ pgml-apps/cargo-pgml-components/src/main.rs | 155 ++++-------------- pgml-apps/cargo-pgml-components/src/util.rs | 60 +++++++ 8 files changed, 235 insertions(+), 125 deletions(-) create mode 100644 pgml-apps/cargo-pgml-components/.gitignore create mode 100644 pgml-apps/cargo-pgml-components/src/frontend/mod.rs create mode 100644 pgml-apps/cargo-pgml-components/src/frontend/sass.rs create mode 100644 pgml-apps/cargo-pgml-components/src/frontend/tools.rs create mode 100644 pgml-apps/cargo-pgml-components/src/util.rs diff --git a/pgml-apps/cargo-pgml-components/.gitignore b/pgml-apps/cargo-pgml-components/.gitignore new file mode 100644 index 000000000..608af9905 --- /dev/null +++ b/pgml-apps/cargo-pgml-components/.gitignore @@ -0,0 +1 @@ +/static diff --git a/pgml-apps/cargo-pgml-components/Cargo.lock b/pgml-apps/cargo-pgml-components/Cargo.lock index 3c5ee69e9..d5c28af99 100644 --- a/pgml-apps/cargo-pgml-components/Cargo.lock +++ b/pgml-apps/cargo-pgml-components/Cargo.lock @@ -59,6 +59,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + [[package]] name = "bitflags" version = "2.4.0" @@ -67,14 +73,16 @@ checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "cargo-pgml-components" -version = "0.1.5" +version = "0.1.6" dependencies = [ + "anyhow", "clap", "convert_case", "env_logger", "glob", "log", "md5", + "owo-colors", ] [[package]] @@ -247,6 +255,12 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + [[package]] name = "proc-macro2" version = "1.0.66" diff --git a/pgml-apps/cargo-pgml-components/Cargo.toml b/pgml-apps/cargo-pgml-components/Cargo.toml index dcb4cdd23..b20af4f81 100644 --- a/pgml-apps/cargo-pgml-components/Cargo.toml +++ b/pgml-apps/cargo-pgml-components/Cargo.toml @@ -15,3 +15,5 @@ clap = { version = "4", features = ["derive"] } md5 = "0.7" log = "0.4" env_logger = "0.10" +anyhow = "1" +owo-colors = "3" diff --git a/pgml-apps/cargo-pgml-components/src/frontend/mod.rs b/pgml-apps/cargo-pgml-components/src/frontend/mod.rs new file mode 100644 index 000000000..db41d484a --- /dev/null +++ b/pgml-apps/cargo-pgml-components/src/frontend/mod.rs @@ -0,0 +1,2 @@ +pub mod sass; +pub mod tools; diff --git a/pgml-apps/cargo-pgml-components/src/frontend/sass.rs b/pgml-apps/cargo-pgml-components/src/frontend/sass.rs new file mode 100644 index 000000000..dc74cd5d2 --- /dev/null +++ b/pgml-apps/cargo-pgml-components/src/frontend/sass.rs @@ -0,0 +1,102 @@ +//! Collect and compile SASS files to produce CSS stylesheets. + +use glob::glob; +use std::fs::{copy, read_to_string, remove_file, File}; +use std::io::Write; +use std::process::Command; + +use crate::util::{execute_command, info, unwrap_or_exit, warn}; + +//github.com/ The name of the SASS file that imports all other SASS files +//github.com/ created in the modules. +static MODULES_FILE: &'static str = "static/css/modules.scss"; + +//github.com/ The SASS file assembling all other files. +static SASS_FILE: &'static str = "static/css/bootstrap-theme.scss"; + +//github.com/ The CSS bundle. +static CSS_FILE: &'static str = "static/css/style.css"; +static CSS_FILE_HASHED: &'static str = "static/css/style.{}.css"; +static CSS_HASH_FILE: &'static str = "static/css/.pgml-bundle"; + +//github.com/ Finds all the SASS files we have generated or the user has created. +static MODULES_GLOB: &'static str = "src/components/**/*.scss"; + +//github.com/ Finds old CSS bundles we created. +static OLD_BUNLDES_GLOB: &'static str = "static/css/style.*.css"; + +//github.com/ Sass compiler +static SASS_COMPILER: &'static str = "sass"; + +//github.com/ Find Sass files and register them with modules.scss. +fn assemble_modules() { + // Assemble SCSS. + let scss = unwrap_or_exit!(glob(MODULES_GLOB)); + + let mut modules = unwrap_or_exit!(File::create(MODULES_FILE)); + + unwrap_or_exit!(writeln!( + &mut modules, + "// This file is automatically generated." + )); + unwrap_or_exit!(writeln!( + &mut modules, + "// There is no need to edit it manually." + )); + unwrap_or_exit!(writeln!(&mut modules, "")); + + for stylesheet in scss { + let stylesheet = unwrap_or_exit!(stylesheet); + + debug!("Adding '{}' to SCSS bundle", stylesheet.display()); + + let line = format!(r#"@import "../../{}";"#, stylesheet.display()); + + unwrap_or_exit!(writeln!(&mut modules, "{}", line)); + } + + info(&format!("written {}", MODULES_FILE)); +} + +//github.com/ Delete old bundles we may have created. +fn cleanup_old_bundles() { + // Clean up old bundles + for file in unwrap_or_exit!(glob(OLD_BUNLDES_GLOB)) { + let file = unwrap_or_exit!(file); + debug!("removing {}", file.display()); + unwrap_or_exit!(remove_file(file.clone())); + warn(&format!("deleted {}", file.display())); + } +} + +//github.com/ Entrypoint. +pub fn bundle() { + crate::frontend::tools::install(); + + assemble_modules(); + cleanup_old_bundles(); + + // Build Sass. + unwrap_or_exit!(execute_command( + Command::new(SASS_COMPILER).arg(SASS_FILE).arg(CSS_FILE), + )); + + info(&format!("written {}", CSS_FILE)); + + // Hash the bundle to bust all caches. + let bundle = read_to_string(CSS_FILE).expect("failed to read bundle.css"); + let hash = format!("{:x}", md5::compute(bundle)) + .chars() + .take(8) + .collect::(); + + let hash_file = CSS_FILE_HASHED.replace("{}", &hash); + + unwrap_or_exit!(copy(CSS_FILE, &hash_file)); + info(&format!("written {}", hash_file)); + + let mut hash_file = unwrap_or_exit!(File::create(CSS_HASH_FILE)); + unwrap_or_exit!(writeln!(&mut hash_file, "{}", hash)); + + info(&format!("written {}", CSS_HASH_FILE)); +} diff --git a/pgml-apps/cargo-pgml-components/src/frontend/tools.rs b/pgml-apps/cargo-pgml-components/src/frontend/tools.rs new file mode 100644 index 000000000..494499935 --- /dev/null +++ b/pgml-apps/cargo-pgml-components/src/frontend/tools.rs @@ -0,0 +1,22 @@ +//! Tools required by us to build stuff. + +use crate::util::{execute_command, info, unwrap_or_exit, warn}; +use std::process::Command; + +//github.com/ Required tools. +static TOOLS: &[&str] = &["sass", "rollup"]; + +//github.com/ Install any missing tools. +pub fn install() { + for tool in TOOLS { + match execute_command(Command::new(tool).arg("--version")) { + Ok(_) => (), + Err(err) => { + warn(&format!("installing {}", tool)); + unwrap_or_exit!(execute_command( + Command::new("npm").arg("install").arg("-g").arg(tool) + )); + } + } + } +} diff --git a/pgml-apps/cargo-pgml-components/src/main.rs b/pgml-apps/cargo-pgml-components/src/main.rs index 4ed3305d8..fc804e2a6 100644 --- a/pgml-apps/cargo-pgml-components/src/main.rs +++ b/pgml-apps/cargo-pgml-components/src/main.rs @@ -4,7 +4,7 @@ use clap::{Args, Parser, Subcommand}; use convert_case::{Case, Casing}; use glob::glob; use std::env::{current_dir, set_current_dir}; -use std::fs::{create_dir_all, read_to_string, remove_file, File, read_dir}; +use std::fs::{create_dir_all, read_dir, read_to_string, remove_file, File}; use std::io::Write; use std::path::Path; use std::process::{exit, Command}; @@ -12,12 +12,13 @@ use std::process::{exit, Command}; #[macro_use] extern crate log; +mod frontend; +mod util; +use util::{execute_command, unwrap_or_exit}; + //github.com/ These paths are exepcted to exist in the project directory. static PROJECT_PATHS: &[&str] = &["src", "static/js", "static/css"]; -//github.com// These executables are required to be installed globally. -static REQUIRED_EXECUTABLES: &[&str] = &["sass", "rollup"]; - static COMPONENT_TEMPLATE_RS: &'static str = r#" use sailfish::TemplateOnce; use crate::components::component; @@ -106,66 +107,12 @@ fn main() { Commands::Bundle {} => bundle(pgml_commands.project_path), Commands::AddComponent { name, overwrite } => add_component(name, overwrite), Commands::UpdateComponents {} => update_components(), - }, } } -fn execute_command(command: &mut Command) -> std::io::Result { - let output = match command.output() { - Ok(output) => output, - Err(err) => { - return Err(err); - } - }; - - let stderr = String::from_utf8_lossy(&output.stderr).to_string(); - let stdout = String::from_utf8_lossy(&output.stderr).to_string(); - - if !output.status.success() { - error!( - "{} failed: {}", - command.get_program().to_str().unwrap(), - String::from_utf8_lossy(&output.stderr).to_string(), - ); - exit(1); - } - - if !stderr.is_empty() { - warn!("{}", stderr); - } - - if !stdout.is_empty() { - info!("{}", stdout); - } - - Ok(stdout) -} - -fn check_executables() { - for executable in REQUIRED_EXECUTABLES { - match execute_command(Command::new(executable).arg("--version")) { - Ok(_) => (), - Err(err) => { - error!( - "'{}' is not installed. Install it with 'npm install -g {}'", - executable, executable - ); - debug!( - "Failed to execute '{} --version': {}", - executable, - err.to_string() - ); - exit(1); - } - } - } -} - //github.com/ Bundle SASS and JavaScript into neat bundle files. fn bundle(project_path: Option) { - check_executables(); - // Validate that the required project paths exist. let cwd = if let Some(project_path) = project_path { project_path @@ -179,71 +126,12 @@ fn bundle(project_path: Option) { let check = path.join(project_path); if !check.exists() { - error!( - "Project path '{}/{}' does not exist but is required", - path.display(), - project_path - ); - exit(1); + unwrap_or_exit!(create_dir_all(check)); } } set_current_dir(path).expect("failed to change paths"); - - // Assemble SCSS. - let scss = glob("src/components/**/*.scss").expect("failed to glob scss files"); - - let mut modules = - File::create("static/css/modules.scss").expect("failed to create modules.scss"); - - for stylesheet in scss { - let stylesheet = stylesheet.expect("failed to glob stylesheet"); - - debug!("Adding '{}' to SCSS bundle", stylesheet.display()); - - let line = format!(r#"@import "../../{}";"#, stylesheet.display()); - - writeln!(&mut modules, "{}", line).expect("failed to write line to modules.scss"); - } - - drop(modules); - - // Clean up old bundles - for file in glob("static/css/style.*.css").expect("failed to glob") { - let file = file.expect("failed to glob file"); - debug!("Removing '{}'", file.display()); - let _ = remove_file(file); - } - - // Bundle SCSS. - // Build Bootstrap - execute_command( - Command::new("sass") - .arg("static/css/bootstrap-theme.scss") - .arg("static/css/style.css"), - ) - .unwrap(); - - // Hash the bundle. - let bundle = read_to_string("static/css/style.css").expect("failed to read bundle.css"); - let hash = format!("{:x}", md5::compute(bundle)) - .chars() - .take(8) - .collect::(); - - execute_command( - Command::new("cp") - .arg("static/css/style.css") - .arg(format!("static/css/style.{}.css", hash)), - ) - .unwrap(); - - let mut hash_file = - File::create("static/css/.pgml-bundle").expect("failed to create .pgml-bundle"); - writeln!(&mut hash_file, "{}", hash).expect("failed to write hash to .pgml-bundle"); - drop(hash_file); - - debug!("Created css .pgml-bundle with hash {}", hash); + frontend::sass::bundle(); // Assemble JavaScript. @@ -404,10 +292,18 @@ fn add_component(name: String, overwrite: bool) { fn update_components() { let mut file = File::create("src/components/mod.rs").expect("failed to create mod.rs"); - writeln!(&mut file, "// This file is automatically generated by cargo-pgml-components.").expect("failed to write to mod.rs"); + writeln!( + &mut file, + "// This file is automatically generated by cargo-pgml-components." + ) + .expect("failed to write to mod.rs"); writeln!(&mut file, "// Do not modify it directly.").expect("failed to write to mod.rs"); writeln!(&mut file, "mod component;").expect("failed to write to mod.rs"); - writeln!(&mut file, "pub(crate) use component::{{component, Component}};").expect("failed to write to mod.rs"); + writeln!( + &mut file, + "pub(crate) use component::{{component, Component}};" + ) + .expect("failed to write to mod.rs"); for component in read_dir("src/components").expect("failed to read components directory") { let path = component.expect("dir entry").path(); @@ -417,12 +313,23 @@ fn update_components() { } let components = path.components(); - let component_name = components.clone().last().expect("component_name").as_os_str().to_str().unwrap(); - let module = components.skip(2).map(|c| c.as_os_str().to_str().unwrap()).collect::>().join("::"); + let component_name = components + .clone() + .last() + .expect("component_name") + .as_os_str() + .to_str() + .unwrap(); + let module = components + .skip(2) + .map(|c| c.as_os_str().to_str().unwrap()) + .collect::>() + .join("::"); // let module = format!("crate::{}", module); let component_name = component_name.to_case(Case::UpperCamel); writeln!(&mut file, "pub mod {};", module).expect("failed to write to mod.rs"); - writeln!(&mut file, "pub use {}::{};", module, component_name).expect("failed to write to mod.rs"); + writeln!(&mut file, "pub use {}::{};", module, component_name) + .expect("failed to write to mod.rs"); } } diff --git a/pgml-apps/cargo-pgml-components/src/util.rs b/pgml-apps/cargo-pgml-components/src/util.rs new file mode 100644 index 000000000..4eebab0c3 --- /dev/null +++ b/pgml-apps/cargo-pgml-components/src/util.rs @@ -0,0 +1,60 @@ +use owo_colors::OwoColorize; +use std::process::{exit, Command}; + +macro_rules! unwrap_or_exit { + ($i:expr) => { + match $i { + Ok(v) => v, + Err(e) => { + error!("{}:{}:{} {e}", file!(), line!(), column!()); + + std::process::exit(1); + } + } + }; +} + +pub(crate) use unwrap_or_exit; + +pub fn info(value: &str) { + println!("{}", value.green()); +} + +pub fn error(value: &str) { + println!("{}", value.red()); +} + +pub fn warn(value: &str) { + println!("{}", value.yellow()); +} + +pub fn execute_command(command: &mut Command) -> std::io::Result { + let output = match command.output() { + Ok(output) => output, + Err(err) => { + return Err(err); + } + }; + + let stderr = String::from_utf8_lossy(&output.stderr).to_string(); + let stdout = String::from_utf8_lossy(&output.stderr).to_string(); + + if !output.status.success() { + error!( + "{} failed: {}", + command.get_program().to_str().unwrap(), + String::from_utf8_lossy(&output.stderr).to_string(), + ); + exit(1); + } + + if !stderr.is_empty() { + warn!("{}", stderr); + } + + if !stdout.is_empty() { + info!("{}", stdout); + } + + Ok(stdout) +} From aee19b7d3e520b9a9c6a910e107ef29dc974021d Mon Sep 17 00:00:00 2001 From: Lev Kokotov Date: Wed, 30 Aug 2023 23:09:05 -0700 Subject: [PATCH 2/6] templates --- pgml-apps/cargo-pgml-components/Cargo.lock | 195 ++++++++++++++- pgml-apps/cargo-pgml-components/Cargo.toml | 1 + pgml-apps/cargo-pgml-components/sailfish.toml | 1 + .../src/frontend/components.rs | 130 ++++++++++ .../cargo-pgml-components/src/frontend/mod.rs | 2 + .../src/frontend/templates/bundle.js.tpl | 0 .../src/frontend/templates/component.rs.tpl | 16 ++ .../src/frontend/templates/mod.rs | 54 ++++ .../src/frontend/templates/mod.rs.tpl | 10 + .../src/frontend/templates/stimulus.js.tpl | 14 ++ .../src/frontend/templates/template.html.tpl | 3 + .../src/frontend/tools.rs | 10 +- pgml-apps/cargo-pgml-components/src/main.rs | 236 +++++++++--------- pgml-apps/cargo-pgml-components/src/util.rs | 11 + 14 files changed, 568 insertions(+), 115 deletions(-) create mode 100644 pgml-apps/cargo-pgml-components/sailfish.toml create mode 100644 pgml-apps/cargo-pgml-components/src/frontend/components.rs create mode 100644 pgml-apps/cargo-pgml-components/src/frontend/templates/bundle.js.tpl create mode 100644 pgml-apps/cargo-pgml-components/src/frontend/templates/component.rs.tpl create mode 100644 pgml-apps/cargo-pgml-components/src/frontend/templates/mod.rs create mode 100644 pgml-apps/cargo-pgml-components/src/frontend/templates/mod.rs.tpl create mode 100644 pgml-apps/cargo-pgml-components/src/frontend/templates/stimulus.js.tpl create mode 100644 pgml-apps/cargo-pgml-components/src/frontend/templates/template.html.tpl diff --git a/pgml-apps/cargo-pgml-components/Cargo.lock b/pgml-apps/cargo-pgml-components/Cargo.lock index d5c28af99..e4720f160 100644 --- a/pgml-apps/cargo-pgml-components/Cargo.lock +++ b/pgml-apps/cargo-pgml-components/Cargo.lock @@ -65,6 +65,12 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.4.0" @@ -83,6 +89,7 @@ dependencies = [ "log", "md5", "owo-colors", + "sailfish", ] [[package]] @@ -94,6 +101,12 @@ dependencies = [ "libc", ] +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "clap" version = "4.4.1" @@ -163,6 +176,12 @@ dependencies = [ "termcolor", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "errno" version = "0.3.3" @@ -184,12 +203,30 @@ dependencies = [ "libc", ] +[[package]] +name = "filetime" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "windows-sys", +] + [[package]] name = "glob" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + [[package]] name = "heck" version = "0.4.1" @@ -202,12 +239,31 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys", +] + [[package]] name = "humantime" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "is-terminal" version = "0.4.9" @@ -219,6 +275,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "itoap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9028f49264629065d057f340a86acb84867925865f73bbf8d47b4d149a7e88b8" + [[package]] name = "libc" version = "0.2.147" @@ -279,6 +341,15 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "regex" version = "1.9.4" @@ -314,13 +385,86 @@ version = "0.38.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed6248e1caa625eb708e266e06159f135e8c26f2bb7ceb72dc4b2766d0340964" dependencies = [ - "bitflags", + "bitflags 2.4.0", "errno", "libc", "linux-raw-sys", "windows-sys", ] +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "sailfish" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7519b7521780097b0183bb4b0c7c2165b924f5f1d44c3ef765bde8c2f8008fd1" +dependencies = [ + "itoap", + "ryu", + "sailfish-macros", + "version_check", +] + +[[package]] +name = "sailfish-compiler" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "535500faca492ee8054fbffdfca6447ca97fa495e0ede9f28fa473e1a44f9d5c" +dependencies = [ + "filetime", + "home", + "memchr", + "proc-macro2", + "quote", + "serde", + "syn", + "toml", +] + +[[package]] +name = "sailfish-macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06a95a6b8a0f59bf66f430a4ed37ece23fcefcd26898399573043e56fb202be2" +dependencies = [ + "proc-macro2", + "sailfish-compiler", +] + +[[package]] +name = "serde" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_spanned" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +dependencies = [ + "serde", +] + [[package]] name = "strsim" version = "0.10.0" @@ -347,6 +491,40 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "toml" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "unicode-ident" version = "1.0.11" @@ -365,6 +543,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "winapi" version = "0.3.9" @@ -461,3 +645,12 @@ name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "winnow" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" +dependencies = [ + "memchr", +] diff --git a/pgml-apps/cargo-pgml-components/Cargo.toml b/pgml-apps/cargo-pgml-components/Cargo.toml index b20af4f81..017b41fee 100644 --- a/pgml-apps/cargo-pgml-components/Cargo.toml +++ b/pgml-apps/cargo-pgml-components/Cargo.toml @@ -17,3 +17,4 @@ log = "0.4" env_logger = "0.10" anyhow = "1" owo-colors = "3" +sailfish = "0.8" diff --git a/pgml-apps/cargo-pgml-components/sailfish.toml b/pgml-apps/cargo-pgml-components/sailfish.toml new file mode 100644 index 000000000..2d804e09e --- /dev/null +++ b/pgml-apps/cargo-pgml-components/sailfish.toml @@ -0,0 +1 @@ +template_dirs = ["src"] diff --git a/pgml-apps/cargo-pgml-components/src/frontend/components.rs b/pgml-apps/cargo-pgml-components/src/frontend/components.rs new file mode 100644 index 000000000..13f4ac062 --- /dev/null +++ b/pgml-apps/cargo-pgml-components/src/frontend/components.rs @@ -0,0 +1,130 @@ +use convert_case::{Case, Casing}; +use sailfish::TemplateOnce; +use std::collections::HashMap; +use std::fs::{create_dir_all, read_dir}; +use std::path::Path; +use std::process::exit; + +use crate::frontend::templates; +use crate::util::{error, info, unwrap_or_exit, write_to_file}; + +static COMPONENT_DIRECTORY: &'static str = "src/components"; +static COMPONENT_MOD: &'static str = "src/components/mod.rs"; + +pub struct Component { + name: String, +} + +impl Component { + pub fn new(name: &str) -> Component { + Component { + name: name.to_string(), + } + } + + pub fn path(&self) -> String { + self.name.to_case(Case::Snake).to_string() + } + + pub fn name(&self) -> String { + self.name.to_case(Case::UpperCamel).to_string() + } + + pub fn full_path(&self) -> String { + Path::new(COMPONENT_DIRECTORY) + .join(&self.path()) + .display() + .to_string() + } + + pub fn controller_name(&self) -> String { + self.path().replace("_", "-") + } + + pub fn rust_module(&self) -> String { + let full_path = self.full_path(); + let path = Path::new(&full_path); + let components = path.components(); + + components + .skip(2) // skip src/components + .map(|c| c.as_os_str().to_str().unwrap()) + .collect::>() + .join("::") + .to_string() + } +} + +impl From<&Path> for Component { + fn from(path: &Path) -> Self { + assert!(path.is_dir()); + + let components = path.components(); + let name = components + .clone() + .last() + .unwrap() + .as_os_str() + .to_str() + .unwrap(); + Component::new(name) + } +} + +//github.com/ Add a new component. +pub fn add(name: &str, overwrite: bool) { + let component = Component::new(name); + let path = Path::new(COMPONENT_DIRECTORY).join(component.path()); + + if path.exists() && !overwrite { + error(&format!("component {} already exists", component.path())); + exit(1); + } else { + unwrap_or_exit!(create_dir_all(&path)); + info(&format!("created directory {}", path.display())); + } + + let rust = unwrap_or_exit!(templates::Component::new(&component).render_once()); + let stimulus = unwrap_or_exit!(templates::Stimulus::new(&component).render_once()); + let html = unwrap_or_exit!(templates::Html::new(&component).render_once()); + let scss = String::new(); + + let html_path = path.join("template.html"); + unwrap_or_exit!(write_to_file(&html_path, &html)); + info(&format!("written {}", html_path.display())); + + let stimulus_path = path.join(&format!("{}_controller.js", component.path())); + unwrap_or_exit!(write_to_file(&stimulus_path, &stimulus)); + info(&format!("written {}", stimulus_path.display())); + + let rust_path = path.join("mod.rs"); + unwrap_or_exit!(write_to_file(&rust_path, &rust)); + info(&format!("written {}", rust_path.display())); + + let scss_path = path.join(&format!("{}.scss", component.path())); + unwrap_or_exit!(write_to_file(&scss_path, &scss)); + info(&format!("written {}", scss_path.display())); + + update_modules(); +} + +//github.com/ Update `mod.rs` with all the components in `src/components`. +pub fn update_modules() { + let mut modules = Vec::new(); + + for path in unwrap_or_exit!(read_dir(COMPONENT_DIRECTORY)) { + let path = unwrap_or_exit!(path).path(); + + if path.is_file() { + continue; + } + + let component = Component::from(Path::new(&path)); + modules.push(component); + } + + let modules = unwrap_or_exit!(templates::Mod { modules }.render_once()); + + unwrap_or_exit!(write_to_file(&Path::new(COMPONENT_MOD), &modules)); + info(&format!("written {}", COMPONENT_MOD)); +} diff --git a/pgml-apps/cargo-pgml-components/src/frontend/mod.rs b/pgml-apps/cargo-pgml-components/src/frontend/mod.rs index db41d484a..273192bc6 100644 --- a/pgml-apps/cargo-pgml-components/src/frontend/mod.rs +++ b/pgml-apps/cargo-pgml-components/src/frontend/mod.rs @@ -1,2 +1,4 @@ +pub mod components; pub mod sass; +pub mod templates; pub mod tools; diff --git a/pgml-apps/cargo-pgml-components/src/frontend/templates/bundle.js.tpl b/pgml-apps/cargo-pgml-components/src/frontend/templates/bundle.js.tpl new file mode 100644 index 000000000..e69de29bb diff --git a/pgml-apps/cargo-pgml-components/src/frontend/templates/component.rs.tpl b/pgml-apps/cargo-pgml-components/src/frontend/templates/component.rs.tpl new file mode 100644 index 000000000..483ccea1d --- /dev/null +++ b/pgml-apps/cargo-pgml-components/src/frontend/templates/component.rs.tpl @@ -0,0 +1,16 @@ +use sailfish::TemplateOnce; +use crate::components::component; + +#[derive(TemplateOnce, Default)] +#[template(path = "<%= component_path %>/template.html")] +pub struct <%= component_name %> { + value: String, +} + +impl <%= component_name %> { + pub fn new() -> <%= component_name %> { + <%= component_name %>::default() + } +} + +component!(<%= component_name %>); diff --git a/pgml-apps/cargo-pgml-components/src/frontend/templates/mod.rs b/pgml-apps/cargo-pgml-components/src/frontend/templates/mod.rs new file mode 100644 index 000000000..affd7b564 --- /dev/null +++ b/pgml-apps/cargo-pgml-components/src/frontend/templates/mod.rs @@ -0,0 +1,54 @@ +use sailfish::TemplateOnce; +use std::collections::HashMap; + +use crate::frontend::components::Component as ComponentModel; + +#[derive(TemplateOnce)] +#[template(path = "frontend/templates/component.rs.tpl")] +pub struct Component { + pub component_name: String, + pub component_path: String, +} + +impl Component { + pub fn new(component: &ComponentModel) -> Self { + Self { + component_name: component.name(), + component_path: component.path(), + } + } +} + +#[derive(TemplateOnce)] +#[template(path = "frontend/templates/template.html.tpl")] +pub struct Html { + pub controller_name: String, +} + +impl Html { + pub fn new(component: &ComponentModel) -> Self { + Self { + controller_name: component.path().replace("_", "-"), + } + } +} + +#[derive(TemplateOnce)] +#[template(path = "frontend/templates/stimulus.js.tpl")] +pub struct Stimulus { + pub controller_name: String, +} + +impl Stimulus { + pub fn new(component: &ComponentModel) -> Self { + Self { + controller_name: component.path().replace("_", "-"), + } + } +} + +#[derive(TemplateOnce)] +#[template(path = "frontend/templates/mod.rs.tpl")] +pub struct Mod { + pub modules: Vec, +} diff --git a/pgml-apps/cargo-pgml-components/src/frontend/templates/mod.rs.tpl b/pgml-apps/cargo-pgml-components/src/frontend/templates/mod.rs.tpl new file mode 100644 index 000000000..0d86a20f2 --- /dev/null +++ b/pgml-apps/cargo-pgml-components/src/frontend/templates/mod.rs.tpl @@ -0,0 +1,10 @@ +// This file is automatically generated. +// You shouldn't modify it manually. + +mod component; +pub(crate) use component::{component, Component}; + +<% for component in modules.iter() { %> +pub mod <%= component.path() %>; +pub use <%= component.rust_module() %>::<%= component.name() %>; +<% } %> diff --git a/pgml-apps/cargo-pgml-components/src/frontend/templates/stimulus.js.tpl b/pgml-apps/cargo-pgml-components/src/frontend/templates/stimulus.js.tpl new file mode 100644 index 000000000..ea0564b98 --- /dev/null +++ b/pgml-apps/cargo-pgml-components/src/frontend/templates/stimulus.js.tpl @@ -0,0 +1,14 @@ +import { Controller } from '@hotwired/stimulus' + +export default class extends Controller { + static targets = [] + static outlets = [] + + initialize() { + console.log('Initialized <%= controller_name %>') + } + + connect() {} + + disconnect() {} +} diff --git a/pgml-apps/cargo-pgml-components/src/frontend/templates/template.html.tpl b/pgml-apps/cargo-pgml-components/src/frontend/templates/template.html.tpl new file mode 100644 index 000000000..a5cf6b8ea --- /dev/null +++ b/pgml-apps/cargo-pgml-components/src/frontend/templates/template.html.tpl @@ -0,0 +1,3 @@ +
+ <%%= value %> +
diff --git a/pgml-apps/cargo-pgml-components/src/frontend/tools.rs b/pgml-apps/cargo-pgml-components/src/frontend/tools.rs index 494499935..0477ec8b2 100644 --- a/pgml-apps/cargo-pgml-components/src/frontend/tools.rs +++ b/pgml-apps/cargo-pgml-components/src/frontend/tools.rs @@ -1,13 +1,19 @@ //! Tools required by us to build stuff. -use crate::util::{execute_command, info, unwrap_or_exit, warn}; -use std::process::Command; +use crate::util::{error, execute_command, unwrap_or_exit, warn}; +use std::process::{exit, Command}; //github.com/ Required tools. static TOOLS: &[&str] = &["sass", "rollup"]; //github.com/ Install any missing tools. pub fn install() { + if let Err(err) = execute_command(Command::new("node").arg("--version")) { + error("Node is not installed. Install it with nvm or your system package manager."); + debug!("{}", err); + exit(1); + } + for tool in TOOLS { match execute_command(Command::new(tool).arg("--version")) { Ok(_) => (), diff --git a/pgml-apps/cargo-pgml-components/src/main.rs b/pgml-apps/cargo-pgml-components/src/main.rs index fc804e2a6..19d457131 100644 --- a/pgml-apps/cargo-pgml-components/src/main.rs +++ b/pgml-apps/cargo-pgml-components/src/main.rs @@ -78,8 +78,13 @@ struct PgmlCommands { #[command(subcommand)] command: Commands, + //github.com/ Specify project path (default: current directory) #[arg(short, long)] project_path: Option, + + //github.com/ Overwrite existing files (default: false) + #[arg(short, long, default_value = "false")] + overwrite: bool, } #[derive(Subcommand, Debug)] @@ -87,17 +92,19 @@ enum Commands { //github.com/ Bundle SASS and JavaScript into neat bundle files. Bundle {}, - //github.com/ Add a new component. - AddComponent { - name: String, - - #[arg(short, long, default_value = "false")] - overwrite: bool, - }, + //github.com/ Add new elements to the project. + #[command(subcommand)] + Add(AddCommands), UpdateComponents {}, } +#[derive(Subcommand, Debug)] +enum AddCommands { + //github.com/ Add a new component. + Component { name: String }, +} + fn main() { env_logger::init(); let cli = Cli::parse(); @@ -105,8 +112,11 @@ fn main() { match cli.subcomand { CargoSubcommands::PgmlComponents(pgml_commands) => match pgml_commands.command { Commands::Bundle {} => bundle(pgml_commands.project_path), - Commands::AddComponent { name, overwrite } => add_component(name, overwrite), + Commands::Add(command) => match command { + AddCommands::Component { name } => add_component(name, pgml_commands.overwrite), + }, Commands::UpdateComponents {} => update_components(), + _ => (), }, } } @@ -225,111 +235,113 @@ fn bundle(project_path: Option) { } fn add_component(name: String, overwrite: bool) { - let component_name = name.as_str().to_case(Case::UpperCamel); - let component_path = name.as_str().to_case(Case::Snake); - let folder = Path::new("src/components").join(&component_path); - - if !folder.exists() { - match create_dir_all(folder.clone()) { - Ok(_) => (), - Err(err) => { - error!( - "Failed to create path '{}' for component '{}': {}", - folder.display(), - name, - err - ); - exit(1); - } - } - } else if !overwrite { - error!("Component '{}' already exists", folder.display()); - exit(1); - } - - // Create mod.rs - let mod_file = format!( - "{}", - COMPONENT_TEMPLATE_RS - .replace("{component_name}", &component_name) - .replace("{component_path}", &component_path) - ); - - let mod_path = folder.join("mod.rs"); - - let mut mod_file_fd = File::create(mod_path).expect("failed to create mod.rs"); - writeln!(&mut mod_file_fd, "{}", mod_file.trim()).expect("failed to write mod.rs"); - drop(mod_file_fd); - - // Create template.html - let template_path = folder.join("template.html"); - let mut template_file = File::create(template_path).expect("failed to create template.html"); - let template_source = - COMPONENT_HTML.replace("{controller_name}", &component_path.replace("_", "-")); - writeln!(&mut template_file, "{}", template_source.trim(),) - .expect("failed to write template.html"); - drop(template_file); - - // Create Stimulus controller - let stimulus_path = folder.join(&format!("{}_controller.js", component_path)); - let mut template_file = - File::create(stimulus_path).expect("failed to create stimulus controller"); - let controller_source = - COMPONENT_STIMULUS_JS.replace("{controller_name}", &component_path.replace("_", "-")); - writeln!(&mut template_file, "{}", controller_source.trim()) - .expect("failed to write stimulus controller"); - drop(template_file); - - // Create SASS file - let sass_path = folder.join(&format!("{}.scss", component_path)); - let sass_file = File::create(sass_path).expect("failed to create sass file"); - drop(sass_file); - - println!("Component '{}' created successfully", folder.display()); - update_components(); + crate::frontend::components::add(&name, overwrite); + // let component_name = name.as_str().to_case(Case::UpperCamel); + // let component_path = name.as_str().to_case(Case::Snake); + // let folder = Path::new("src/components").join(&component_path); + + // if !folder.exists() { + // match create_dir_all(folder.clone()) { + // Ok(_) => (), + // Err(err) => { + // error!( + // "Failed to create path '{}' for component '{}': {}", + // folder.display(), + // name, + // err + // ); + // exit(1); + // } + // } + // } else if !overwrite { + // error!("Component '{}' already exists", folder.display()); + // exit(1); + // } + + // // Create mod.rs + // let mod_file = format!( + // "{}", + // COMPONENT_TEMPLATE_RS + // .replace("{component_name}", &component_name) + // .replace("{component_path}", &component_path) + // ); + + // let mod_path = folder.join("mod.rs"); + + // let mut mod_file_fd = File::create(mod_path).expect("failed to create mod.rs"); + // writeln!(&mut mod_file_fd, "{}", mod_file.trim()).expect("failed to write mod.rs"); + // drop(mod_file_fd); + + // // Create template.html + // let template_path = folder.join("template.html"); + // let mut template_file = File::create(template_path).expect("failed to create template.html"); + // let template_source = + // COMPONENT_HTML.replace("{controller_name}", &component_path.replace("_", "-")); + // writeln!(&mut template_file, "{}", template_source.trim(),) + // .expect("failed to write template.html"); + // drop(template_file); + + // // Create Stimulus controller + // let stimulus_path = folder.join(&format!("{}_controller.js", component_path)); + // let mut template_file = + // File::create(stimulus_path).expect("failed to create stimulus controller"); + // let controller_source = + // COMPONENT_STIMULUS_JS.replace("{controller_name}", &component_path.replace("_", "-")); + // writeln!(&mut template_file, "{}", controller_source.trim()) + // .expect("failed to write stimulus controller"); + // drop(template_file); + + // // Create SASS file + // let sass_path = folder.join(&format!("{}.scss", component_path)); + // let sass_file = File::create(sass_path).expect("failed to create sass file"); + // drop(sass_file); + + // println!("Component '{}' created successfully", folder.display()); + // update_components(); } fn update_components() { - let mut file = File::create("src/components/mod.rs").expect("failed to create mod.rs"); - - writeln!( - &mut file, - "// This file is automatically generated by cargo-pgml-components." - ) - .expect("failed to write to mod.rs"); - writeln!(&mut file, "// Do not modify it directly.").expect("failed to write to mod.rs"); - writeln!(&mut file, "mod component;").expect("failed to write to mod.rs"); - writeln!( - &mut file, - "pub(crate) use component::{{component, Component}};" - ) - .expect("failed to write to mod.rs"); - - for component in read_dir("src/components").expect("failed to read components directory") { - let path = component.expect("dir entry").path(); - - if path.is_file() { - continue; - } - - let components = path.components(); - let component_name = components - .clone() - .last() - .expect("component_name") - .as_os_str() - .to_str() - .unwrap(); - let module = components - .skip(2) - .map(|c| c.as_os_str().to_str().unwrap()) - .collect::>() - .join("::"); - // let module = format!("crate::{}", module); - let component_name = component_name.to_case(Case::UpperCamel); - - writeln!(&mut file, "pub mod {};", module).expect("failed to write to mod.rs"); - writeln!(&mut file, "pub use {}::{};", module, component_name) - .expect("failed to write to mod.rs"); - } + crate::frontend::components::update_modules(); + // let mut file = File::create("src/components/mod.rs").expect("failed to create mod.rs"); + + // writeln!( + // &mut file, + // "// This file is automatically generated by cargo-pgml-components." + // ) + // .expect("failed to write to mod.rs"); + // writeln!(&mut file, "// Do not modify it directly.").expect("failed to write to mod.rs"); + // writeln!(&mut file, "mod component;").expect("failed to write to mod.rs"); + // writeln!( + // &mut file, + // "pub(crate) use component::{{component, Component}};" + // ) + // .expect("failed to write to mod.rs"); + + // for component in read_dir("src/components").expect("failed to read components directory") { + // let path = component.expect("dir entry").path(); + + // if path.is_file() { + // continue; + // } + + // let components = path.components(); + // let component_name = components + // .clone() + // .last() + // .expect("component_name") + // .as_os_str() + // .to_str() + // .unwrap(); + // let module = components + // .skip(2) + // .map(|c| c.as_os_str().to_str().unwrap()) + // .collect::>() + // .join("::"); + // // let module = format!("crate::{}", module); + // let component_name = component_name.to_case(Case::UpperCamel); + + // writeln!(&mut file, "pub mod {};", module).expect("failed to write to mod.rs"); + // writeln!(&mut file, "pub use {}::{};", module, component_name) + // .expect("failed to write to mod.rs"); + // } } diff --git a/pgml-apps/cargo-pgml-components/src/util.rs b/pgml-apps/cargo-pgml-components/src/util.rs index 4eebab0c3..7205c4a9b 100644 --- a/pgml-apps/cargo-pgml-components/src/util.rs +++ b/pgml-apps/cargo-pgml-components/src/util.rs @@ -1,4 +1,7 @@ use owo_colors::OwoColorize; +use std::fs::File; +use std::io::Write; +use std::path::Path; use std::process::{exit, Command}; macro_rules! unwrap_or_exit { @@ -58,3 +61,11 @@ pub fn execute_command(command: &mut Command) -> std::io::Result { Ok(stdout) } + +pub fn write_to_file(path: &Path, content: &str) -> std::io::Result<()> { + let mut file = File::create(path)?; + + file.write_all(content.as_bytes())?; + + Ok(()) +} From 2f6795ab3186d74a1441991b1f6564d979ae6df5 Mon Sep 17 00:00:00 2001 From: Lev Kokotov Date: Wed, 30 Aug 2023 23:14:40 -0700 Subject: [PATCH 3/6] cleanup --- pgml-apps/cargo-pgml-components/src/main.rs | 146 -------------------- 1 file changed, 146 deletions(-) diff --git a/pgml-apps/cargo-pgml-components/src/main.rs b/pgml-apps/cargo-pgml-components/src/main.rs index 19d457131..5ae78a6f9 100644 --- a/pgml-apps/cargo-pgml-components/src/main.rs +++ b/pgml-apps/cargo-pgml-components/src/main.rs @@ -19,48 +19,6 @@ use util::{execute_command, unwrap_or_exit}; //github.com/ These paths are exepcted to exist in the project directory. static PROJECT_PATHS: &[&str] = &["src", "static/js", "static/css"]; -static COMPONENT_TEMPLATE_RS: &'static str = r#" -use sailfish::TemplateOnce; -use crate::components::component; - -#[derive(TemplateOnce, Default)] -#[template(path = "{component_path}/template.html")] -pub struct {component_name} { - value: String, -} - -impl {component_name} { - pub fn new() -> {component_name} { - {component_name}::default() - } -} - -component!({component_name}); -"#; - -static COMPONENT_STIMULUS_JS: &'static str = r#" -import { Controller } from '@hotwired/stimulus' - -export default class extends Controller { - static targets = [] - static outlets = [] - - initialize() { - console.log('Initialized {controller_name}') - } - - connect() {} - - disconnect() {} -} -"#; - -static COMPONENT_HTML: &'static str = r#" -
- <%= value %> -
-"#; - #[derive(Parser, Debug)] #[command(author, version, about, long_about = None, propagate_version = true, bin_name = "cargo", name = "cargo")] struct Cli { @@ -236,112 +194,8 @@ fn bundle(project_path: Option) { fn add_component(name: String, overwrite: bool) { crate::frontend::components::add(&name, overwrite); - // let component_name = name.as_str().to_case(Case::UpperCamel); - // let component_path = name.as_str().to_case(Case::Snake); - // let folder = Path::new("src/components").join(&component_path); - - // if !folder.exists() { - // match create_dir_all(folder.clone()) { - // Ok(_) => (), - // Err(err) => { - // error!( - // "Failed to create path '{}' for component '{}': {}", - // folder.display(), - // name, - // err - // ); - // exit(1); - // } - // } - // } else if !overwrite { - // error!("Component '{}' already exists", folder.display()); - // exit(1); - // } - - // // Create mod.rs - // let mod_file = format!( - // "{}", - // COMPONENT_TEMPLATE_RS - // .replace("{component_name}", &component_name) - // .replace("{component_path}", &component_path) - // ); - - // let mod_path = folder.join("mod.rs"); - - // let mut mod_file_fd = File::create(mod_path).expect("failed to create mod.rs"); - // writeln!(&mut mod_file_fd, "{}", mod_file.trim()).expect("failed to write mod.rs"); - // drop(mod_file_fd); - - // // Create template.html - // let template_path = folder.join("template.html"); - // let mut template_file = File::create(template_path).expect("failed to create template.html"); - // let template_source = - // COMPONENT_HTML.replace("{controller_name}", &component_path.replace("_", "-")); - // writeln!(&mut template_file, "{}", template_source.trim(),) - // .expect("failed to write template.html"); - // drop(template_file); - - // // Create Stimulus controller - // let stimulus_path = folder.join(&format!("{}_controller.js", component_path)); - // let mut template_file = - // File::create(stimulus_path).expect("failed to create stimulus controller"); - // let controller_source = - // COMPONENT_STIMULUS_JS.replace("{controller_name}", &component_path.replace("_", "-")); - // writeln!(&mut template_file, "{}", controller_source.trim()) - // .expect("failed to write stimulus controller"); - // drop(template_file); - - // // Create SASS file - // let sass_path = folder.join(&format!("{}.scss", component_path)); - // let sass_file = File::create(sass_path).expect("failed to create sass file"); - // drop(sass_file); - - // println!("Component '{}' created successfully", folder.display()); - // update_components(); } fn update_components() { crate::frontend::components::update_modules(); - // let mut file = File::create("src/components/mod.rs").expect("failed to create mod.rs"); - - // writeln!( - // &mut file, - // "// This file is automatically generated by cargo-pgml-components." - // ) - // .expect("failed to write to mod.rs"); - // writeln!(&mut file, "// Do not modify it directly.").expect("failed to write to mod.rs"); - // writeln!(&mut file, "mod component;").expect("failed to write to mod.rs"); - // writeln!( - // &mut file, - // "pub(crate) use component::{{component, Component}};" - // ) - // .expect("failed to write to mod.rs"); - - // for component in read_dir("src/components").expect("failed to read components directory") { - // let path = component.expect("dir entry").path(); - - // if path.is_file() { - // continue; - // } - - // let components = path.components(); - // let component_name = components - // .clone() - // .last() - // .expect("component_name") - // .as_os_str() - // .to_str() - // .unwrap(); - // let module = components - // .skip(2) - // .map(|c| c.as_os_str().to_str().unwrap()) - // .collect::>() - // .join("::"); - // // let module = format!("crate::{}", module); - // let component_name = component_name.to_case(Case::UpperCamel); - - // writeln!(&mut file, "pub mod {};", module).expect("failed to write to mod.rs"); - // writeln!(&mut file, "pub use {}::{};", module, component_name) - // .expect("failed to write to mod.rs"); - // } } From b9136bd5c99571297cb472b05cd112ff9d4f8ae7 Mon Sep 17 00:00:00 2001 From: Lev Kokotov Date: Thu, 31 Aug 2023 07:38:08 -0700 Subject: [PATCH 4/6] Fix nomodules --- .../src/frontend/components.rs | 4 + .../src/frontend/javascript.rs | 138 ++++++++++++++++++ .../cargo-pgml-components/src/frontend/mod.rs | 1 + .../src/frontend/templates/bundle.js.tpl | 7 + pgml-apps/cargo-pgml-components/src/main.rs | 95 +----------- pgml-dashboard/static/css/modules.scss | 3 + .../content/dashboard/panels/model.html | 2 +- .../content/dashboard/panels/models.html | 2 +- .../content/dashboard/panels/project.html | 2 +- .../content/dashboard/panels/snapshot.html | 2 +- pgml-dashboard/templates/layout/head.html | 42 +++--- 11 files changed, 185 insertions(+), 113 deletions(-) create mode 100644 pgml-apps/cargo-pgml-components/src/frontend/javascript.rs diff --git a/pgml-apps/cargo-pgml-components/src/frontend/components.rs b/pgml-apps/cargo-pgml-components/src/frontend/components.rs index 13f4ac062..025a9932c 100644 --- a/pgml-apps/cargo-pgml-components/src/frontend/components.rs +++ b/pgml-apps/cargo-pgml-components/src/frontend/components.rs @@ -41,6 +41,10 @@ impl Component { self.path().replace("_", "-") } + pub fn controller_path(&self) -> String { + format!("{}_controller.js", self.path()) + } + pub fn rust_module(&self) -> String { let full_path = self.full_path(); let path = Path::new(&full_path); diff --git a/pgml-apps/cargo-pgml-components/src/frontend/javascript.rs b/pgml-apps/cargo-pgml-components/src/frontend/javascript.rs new file mode 100644 index 000000000..8fdf26e30 --- /dev/null +++ b/pgml-apps/cargo-pgml-components/src/frontend/javascript.rs @@ -0,0 +1,138 @@ +//! Javascript bundling. + +use glob::glob; +use std::fs::{copy, read_to_string, remove_file, File}; +use std::io::Write; +use std::path::Path; +use std::process::Command; + +use convert_case::{Case, Casing}; + +use crate::util::{execute_command, info, unwrap_or_exit, warn}; + +//github.com/ The name of the JS file that imports all other JS files +//github.com/ created in the modules. +static MODULES_FILE: &'static str = "static/js/modules.js"; + +//github.com/ The JS bundle. +static JS_FILE: &'static str = "static/js/bundle.js"; +static JS_FILE_HASHED: &'static str = "static/js/bundle.{}.js"; +static JS_HASH_FILE: &'static str = "static/js/.pgml-bundle"; + +//github.com/ Finds all the JS files we have generated or the user has created. +static MODULES_GLOB: &'static str = "src/components/**/*.js"; +static STATIC_JS_GLOB: &'static str = "static/js/*.js"; + +//github.com/ Finds old JS bundles we created. +static OLD_BUNLDES_GLOB: &'static str = "static/js/*.*.js"; + +//github.com/ JS compiler +static JS_COMPILER: &'static str = "rollup"; + +//github.com/ Delete old bundles we may have created. +fn cleanup_old_bundles() { + // Clean up old bundles + for file in unwrap_or_exit!(glob(OLD_BUNLDES_GLOB)) { + let file = unwrap_or_exit!(file); + debug!("removing {}", file.display()); + unwrap_or_exit!(remove_file(file.clone())); + warn(&format!("deleted {}", file.display())); + } +} + +fn assemble_modules() { + let js = unwrap_or_exit!(glob(MODULES_GLOB)); + let js = js.chain(unwrap_or_exit!(glob(STATIC_JS_GLOB))); + + // Don't bundle artifacts we produce. + let js = js.filter(|path| { + let path = path.as_ref().unwrap(); + let path = path.display().to_string(); + + !path.contains("main.js") && !path.contains("bundle.js") && !path.contains("modules.js") + }); + + let mut modules = unwrap_or_exit!(File::create(MODULES_FILE)); + + unwrap_or_exit!(writeln!(&mut modules, "// Build with --bin components")); + unwrap_or_exit!(writeln!( + &mut modules, + "import {{ Application }} from '@hotwired/stimulus'" + )); + unwrap_or_exit!(writeln!( + &mut modules, + "const application = Application.start()" + )); + + for source in js { + let source = unwrap_or_exit!(source); + + let full_path = source.display(); + let stem = source.file_stem().unwrap().to_str().unwrap(); + let upper_camel = stem.to_case(Case::UpperCamel); + + let mut controller_name = stem.split("_").collect::>(); + + if stem.contains("controller") { + let _ = controller_name.pop().unwrap(); + } + + let controller_name = controller_name.join("-"); + + unwrap_or_exit!(writeln!( + &mut modules, + "import {{ default as {} }} from '../../{}'", + upper_camel, full_path + )); + + unwrap_or_exit!(writeln!( + &mut modules, + "application.register('{}', {})", + controller_name, upper_camel + )); + } + + info(&format!("written {}", MODULES_FILE)); +} + +pub fn bundle() { + cleanup_old_bundles(); + assemble_modules(); + + // Bundle JavaScript. + unwrap_or_exit!(execute_command( + Command::new(JS_COMPILER) + .arg(MODULES_FILE) + .arg("--file") + .arg(JS_FILE) + .arg("--format") + .arg("es"), + )); + + info(&format!("written {}", JS_FILE)); + + // Hash the bundle. + let bundle = unwrap_or_exit!(read_to_string(JS_FILE)); + let hash = format!("{:x}", md5::compute(bundle)) + .chars() + .take(8) + .collect::(); + + unwrap_or_exit!(copy(JS_FILE, &JS_FILE_HASHED.replace("{}", &hash))); + info(&format!("written {}", JS_FILE_HASHED.replace("{}", &hash))); + + // Legacy, remove code from main.js into respective modules. + unwrap_or_exit!(copy( + "static/js/main.js", + &format!("static/js/main.{}.js", &hash) + )); + info(&format!( + "written {}", + format!("static/js/main.{}.js", &hash) + )); + + let mut hash_file = unwrap_or_exit!(File::create(JS_HASH_FILE)); + unwrap_or_exit!(writeln!(&mut hash_file, "{}", hash)); + + info(&format!("written {}", JS_HASH_FILE)); +} diff --git a/pgml-apps/cargo-pgml-components/src/frontend/mod.rs b/pgml-apps/cargo-pgml-components/src/frontend/mod.rs index 273192bc6..55790107f 100644 --- a/pgml-apps/cargo-pgml-components/src/frontend/mod.rs +++ b/pgml-apps/cargo-pgml-components/src/frontend/mod.rs @@ -1,4 +1,5 @@ pub mod components; +pub mod javascript; pub mod sass; pub mod templates; pub mod tools; diff --git a/pgml-apps/cargo-pgml-components/src/frontend/templates/bundle.js.tpl b/pgml-apps/cargo-pgml-components/src/frontend/templates/bundle.js.tpl index e69de29bb..37c5c346c 100644 --- a/pgml-apps/cargo-pgml-components/src/frontend/templates/bundle.js.tpl +++ b/pgml-apps/cargo-pgml-components/src/frontend/templates/bundle.js.tpl @@ -0,0 +1,7 @@ +import { Application } from '@hotwired/stimulus' +const application = Application.start() + +<% for component in components { +import { default as <%= component.name() %> } from '../../<%= component.controller_path() %>'" +application.register('<%= component.controller_name() %>') +<% } %> diff --git a/pgml-apps/cargo-pgml-components/src/main.rs b/pgml-apps/cargo-pgml-components/src/main.rs index 5ae78a6f9..bcd53c5af 100644 --- a/pgml-apps/cargo-pgml-components/src/main.rs +++ b/pgml-apps/cargo-pgml-components/src/main.rs @@ -14,7 +14,7 @@ extern crate log; mod frontend; mod util; -use util::{execute_command, unwrap_or_exit}; +use util::{execute_command, info, unwrap_or_exit}; //github.com/ These paths are exepcted to exist in the project directory. static PROJECT_PATHS: &[&str] = &["src", "static/js", "static/css"]; @@ -98,98 +98,11 @@ fn bundle(project_path: Option) { } } - set_current_dir(path).expect("failed to change paths"); + unwrap_or_exit!(set_current_dir(path)); frontend::sass::bundle(); + frontend::javascript::bundle(); - // Assemble JavaScript. - - // Remove prebuilt files. - for file in glob::glob("static/js/*.*.js").expect("failed to glob") { - let _ = remove_file(file.expect("failed to glob file")); - } - - let js = glob("src/components/**/*.js").expect("failed to glob js files"); - let js = js.chain(glob("static/js/*.js").expect("failed to glob static/js/*.js")); - let js = js.filter(|path| { - let path = path.as_ref().unwrap(); - let path = path.display().to_string(); - - !path.contains("main.js") && !path.contains("bundle.js") && !path.contains("modules.js") - }); - - let mut modules = File::create("static/js/modules.js").expect("failed to create modules.js"); - - writeln!(&mut modules, "// Build with --bin components").unwrap(); - writeln!( - &mut modules, - "import {{ Application }} from '@hotwired/stimulus'" - ) - .expect("failed to write to modules.js"); - writeln!(&mut modules, "const application = Application.start()") - .expect("failed to write to modules.js"); - - for source in js { - let source = source.expect("failed to glob js file"); - - let full_path = source.display(); - let stem = source.file_stem().unwrap().to_str().unwrap(); - let upper_camel = stem.to_case(Case::UpperCamel); - - let mut controller_name = stem.split("_").collect::>(); - - if stem.contains("controller") { - let _ = controller_name.pop().unwrap(); - } - - let controller_name = controller_name.join("-"); - - writeln!( - &mut modules, - "import {{ default as {} }} from '../../{}'", - upper_camel, full_path - ) - .unwrap(); - writeln!( - &mut modules, - "application.register('{}', {})", - controller_name, upper_camel - ) - .unwrap(); - } - - drop(modules); - - // Bundle JavaScript. - execute_command( - Command::new("rollup") - .arg("static/js/modules.js") - .arg("--file") - .arg("static/js/bundle.js") - .arg("--format") - .arg("es"), - ) - .unwrap(); - - // Hash the bundle. - let bundle = read_to_string("static/js/bundle.js").expect("failed to read bundle.js"); - let hash = format!("{:x}", md5::compute(bundle)) - .chars() - .take(8) - .collect::(); - - execute_command( - Command::new("cp") - .arg("static/js/bundle.js") - .arg(format!("static/js/bundle.{}.js", hash)), - ) - .unwrap(); - - let mut hash_file = - File::create("static/js/.pgml-bundle").expect("failed to create .pgml-bundle"); - writeln!(&mut hash_file, "{}", hash).expect("failed to write hash to .pgml-bundle"); - drop(hash_file); - - println!("Finished bundling CSS and JavaScript successfully"); + info("Bundle complete"); } fn add_component(name: String, overwrite: bool) { diff --git a/pgml-dashboard/static/css/modules.scss b/pgml-dashboard/static/css/modules.scss index e15d16010..c038c5029 100644 --- a/pgml-dashboard/static/css/modules.scss +++ b/pgml-dashboard/static/css/modules.scss @@ -1,3 +1,6 @@ +// This file is automatically generated. +// There is no need to edit it manually. + @import "../../src/components/left_nav_menu/left_nav_menu.scss"; @import "../../src/components/left_nav_web_app/left_nav_web_app.scss"; @import "../../src/components/modal/modal.scss"; diff --git a/pgml-dashboard/templates/content/dashboard/panels/model.html b/pgml-dashboard/templates/content/dashboard/panels/model.html index dc1b392d0..fbe188d2e 100644 --- a/pgml-dashboard/templates/content/dashboard/panels/model.html +++ b/pgml-dashboard/templates/content/dashboard/panels/model.html @@ -59,7 +59,7 @@

<%= param %>

- + + + + + + + + + + + + - - - - + + + @@ -60,17 +76,7 @@ - - - + <% if config::dev_mode() { %> From 20f6cfa2b0ebff8eaa7d635fcec045376e6ebc41 Mon Sep 17 00:00:00 2001 From: Lev Kokotov Date: Thu, 31 Aug 2023 07:54:29 -0700 Subject: [PATCH 5/6] ok --- pgml-apps/cargo-pgml-components/Cargo.lock | 2 +- pgml-apps/cargo-pgml-components/Cargo.toml | 2 +- .../src/frontend/components.rs | 2 +- .../src/frontend/javascript.rs | 1 - .../src/frontend/templates/mod.rs | 3 +- .../src/frontend/templates/mod.rs.tpl | 1 + .../src/frontend/tools.rs | 1 + pgml-apps/cargo-pgml-components/src/main.rs | 26 ++++---------- pgml-dashboard/src/components/mod.rs | 34 +++++++++++++++++-- 9 files changed, 44 insertions(+), 28 deletions(-) diff --git a/pgml-apps/cargo-pgml-components/Cargo.lock b/pgml-apps/cargo-pgml-components/Cargo.lock index e4720f160..fa54e9722 100644 --- a/pgml-apps/cargo-pgml-components/Cargo.lock +++ b/pgml-apps/cargo-pgml-components/Cargo.lock @@ -79,7 +79,7 @@ checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "cargo-pgml-components" -version = "0.1.6" +version = "0.1.7" dependencies = [ "anyhow", "clap", diff --git a/pgml-apps/cargo-pgml-components/Cargo.toml b/pgml-apps/cargo-pgml-components/Cargo.toml index 017b41fee..84be9f5b5 100644 --- a/pgml-apps/cargo-pgml-components/Cargo.toml +++ b/pgml-apps/cargo-pgml-components/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cargo-pgml-components" -version = "0.1.6" +version = "0.1.7" edition = "2021" authors = ["PostgresML "] license = "MIT" diff --git a/pgml-apps/cargo-pgml-components/src/frontend/components.rs b/pgml-apps/cargo-pgml-components/src/frontend/components.rs index 025a9932c..e4bf2b6b0 100644 --- a/pgml-apps/cargo-pgml-components/src/frontend/components.rs +++ b/pgml-apps/cargo-pgml-components/src/frontend/components.rs @@ -1,6 +1,5 @@ use convert_case::{Case, Casing}; use sailfish::TemplateOnce; -use std::collections::HashMap; use std::fs::{create_dir_all, read_dir}; use std::path::Path; use std::process::exit; @@ -41,6 +40,7 @@ impl Component { self.path().replace("_", "-") } + #[allow(dead_code)] pub fn controller_path(&self) -> String { format!("{}_controller.js", self.path()) } diff --git a/pgml-apps/cargo-pgml-components/src/frontend/javascript.rs b/pgml-apps/cargo-pgml-components/src/frontend/javascript.rs index 8fdf26e30..90b733122 100644 --- a/pgml-apps/cargo-pgml-components/src/frontend/javascript.rs +++ b/pgml-apps/cargo-pgml-components/src/frontend/javascript.rs @@ -3,7 +3,6 @@ use glob::glob; use std::fs::{copy, read_to_string, remove_file, File}; use std::io::Write; -use std::path::Path; use std::process::Command; use convert_case::{Case, Casing}; diff --git a/pgml-apps/cargo-pgml-components/src/frontend/templates/mod.rs b/pgml-apps/cargo-pgml-components/src/frontend/templates/mod.rs index affd7b564..2b78f9f64 100644 --- a/pgml-apps/cargo-pgml-components/src/frontend/templates/mod.rs +++ b/pgml-apps/cargo-pgml-components/src/frontend/templates/mod.rs @@ -1,5 +1,4 @@ use sailfish::TemplateOnce; -use std::collections::HashMap; use crate::frontend::components::Component as ComponentModel; @@ -42,7 +41,7 @@ pub struct Stimulus { impl Stimulus { pub fn new(component: &ComponentModel) -> Self { Self { - controller_name: component.path().replace("_", "-"), + controller_name: component.controller_name(), } } } diff --git a/pgml-apps/cargo-pgml-components/src/frontend/templates/mod.rs.tpl b/pgml-apps/cargo-pgml-components/src/frontend/templates/mod.rs.tpl index 0d86a20f2..2458898bd 100644 --- a/pgml-apps/cargo-pgml-components/src/frontend/templates/mod.rs.tpl +++ b/pgml-apps/cargo-pgml-components/src/frontend/templates/mod.rs.tpl @@ -5,6 +5,7 @@ mod component; pub(crate) use component::{component, Component}; <% for component in modules.iter() { %> +// <%= component.full_path() %> pub mod <%= component.path() %>; pub use <%= component.rust_module() %>::<%= component.name() %>; <% } %> diff --git a/pgml-apps/cargo-pgml-components/src/frontend/tools.rs b/pgml-apps/cargo-pgml-components/src/frontend/tools.rs index 0477ec8b2..b6b2e785c 100644 --- a/pgml-apps/cargo-pgml-components/src/frontend/tools.rs +++ b/pgml-apps/cargo-pgml-components/src/frontend/tools.rs @@ -18,6 +18,7 @@ pub fn install() { match execute_command(Command::new(tool).arg("--version")) { Ok(_) => (), Err(err) => { + debug!("{}", err); warn(&format!("installing {}", tool)); unwrap_or_exit!(execute_command( Command::new("npm").arg("install").arg("-g").arg(tool) diff --git a/pgml-apps/cargo-pgml-components/src/main.rs b/pgml-apps/cargo-pgml-components/src/main.rs index bcd53c5af..6f2a57a6d 100644 --- a/pgml-apps/cargo-pgml-components/src/main.rs +++ b/pgml-apps/cargo-pgml-components/src/main.rs @@ -1,20 +1,16 @@ //! A tool to assemble and bundle our frontend components. use clap::{Args, Parser, Subcommand}; -use convert_case::{Case, Casing}; -use glob::glob; use std::env::{current_dir, set_current_dir}; -use std::fs::{create_dir_all, read_dir, read_to_string, remove_file, File}; -use std::io::Write; +use std::fs::{create_dir_all}; use std::path::Path; -use std::process::{exit, Command}; #[macro_use] extern crate log; mod frontend; mod util; -use util::{execute_command, info, unwrap_or_exit}; +use util::{info, unwrap_or_exit}; //github.com/ These paths are exepcted to exist in the project directory. static PROJECT_PATHS: &[&str] = &["src", "static/js", "static/css"]; @@ -53,8 +49,6 @@ enum Commands { //github.com/ Add new elements to the project. #[command(subcommand)] Add(AddCommands), - - UpdateComponents {}, } #[derive(Subcommand, Debug)] @@ -71,10 +65,8 @@ fn main() { CargoSubcommands::PgmlComponents(pgml_commands) => match pgml_commands.command { Commands::Bundle {} => bundle(pgml_commands.project_path), Commands::Add(command) => match command { - AddCommands::Component { name } => add_component(name, pgml_commands.overwrite), + AddCommands::Component { name } => crate::frontend::components::add(&name, pgml_commands.overwrite), }, - Commands::UpdateComponents {} => update_components(), - _ => (), }, } } @@ -94,21 +86,15 @@ fn bundle(project_path: Option) { let check = path.join(project_path); if !check.exists() { - unwrap_or_exit!(create_dir_all(check)); + unwrap_or_exit!(create_dir_all(&check)); + info(&format!("created {} directory", check.display())); } } unwrap_or_exit!(set_current_dir(path)); frontend::sass::bundle(); frontend::javascript::bundle(); + frontend::components::update_modules(); info("Bundle complete"); } - -fn add_component(name: String, overwrite: bool) { - crate::frontend::components::add(&name, overwrite); -} - -fn update_components() { - crate::frontend::components::update_modules(); -} diff --git a/pgml-dashboard/src/components/mod.rs b/pgml-dashboard/src/components/mod.rs index 1c5737be0..64af15f8a 100644 --- a/pgml-dashboard/src/components/mod.rs +++ b/pgml-dashboard/src/components/mod.rs @@ -1,32 +1,62 @@ -// This file is automatically generated by cargo-pgml-components. -// Do not modify it directly. +// This file is automatically generated. +// You shouldn't modify it manually. + mod component; pub(crate) use component::{component, Component}; + + +// src/components/navbar_web_app pub mod navbar_web_app; pub use navbar_web_app::NavbarWebApp; + +// src/components/navbar pub mod navbar; pub use navbar::Navbar; + +// src/components/postgres_logo pub mod postgres_logo; pub use postgres_logo::PostgresLogo; + +// src/components/static_nav_link pub mod static_nav_link; pub use static_nav_link::StaticNavLink; + +// src/components/modal pub mod modal; pub use modal::Modal; + +// src/components/static_nav pub mod static_nav; pub use static_nav::StaticNav; + +// src/components/test_component pub mod test_component; pub use test_component::TestComponent; + +// src/components/nav pub mod nav; pub use nav::Nav; + +// src/components/left_nav_web_app pub mod left_nav_web_app; pub use left_nav_web_app::LeftNavWebApp; + +// src/components/github_icon pub mod github_icon; pub use github_icon::GithubIcon; + +// src/components/confirm_modal pub mod confirm_modal; pub use confirm_modal::ConfirmModal; + +// src/components/left_nav_menu pub mod left_nav_menu; pub use left_nav_menu::LeftNavMenu; + +// src/components/nav_link pub mod nav_link; pub use nav_link::NavLink; + +// src/components/breadcrumbs pub mod breadcrumbs; pub use breadcrumbs::Breadcrumbs; From 112d8aa12a3ba837ddb2c4a7a00f364928e20559 Mon Sep 17 00:00:00 2001 From: Lev Kokotov Date: Thu, 31 Aug 2023 08:06:28 -0700 Subject: [PATCH 6/6] hmm --- pgml-dashboard/templates/layout/head.html | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/pgml-dashboard/templates/layout/head.html b/pgml-dashboard/templates/layout/head.html index 43c5bbd0d..2e3c6b098 100644 --- a/pgml-dashboard/templates/layout/head.html +++ b/pgml-dashboard/templates/layout/head.html @@ -36,8 +36,6 @@ - - - - - - - - - + - - + + + - - - + + + +








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/postgresml/postgresml/pull/966.patch

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy