Add link generators to the front page (#167)

Co-authored-by: Rob Ede <robjtede@icloud.com>
Co-authored-by: Paolo Barbolini <paolo.barbolini@m4ss.net>
This commit is contained in:
Felix Suchert 2022-08-29 13:13:12 +02:00 committed by GitHub
parent c2f0b88b02
commit edfdb969c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 168 additions and 1 deletions

39
assets/links.js vendored Normal file
View file

@ -0,0 +1,39 @@
function buildRepoLink() {
let formRef = document.forms["repoSelect"];
let hoster = formRef.elements["hosterSelect"].value.toLowerCase();
let owner = formRef.elements["owner"].value;
let repoName = formRef.elements["repoName"].value;
if (hoster === "gitea") {
let baseUrl = formRef.elements["baseUrl"].value;
// verify that the Base URL is not empty
if(baseUrl.length === 0) {
formRef.elements["baseUrl"].classList.add("is-danger");
document.getElementById("baseUrlHelp").classList.add("is-danger");
let hostName = formRef.elements["hosterSelect"].value;
document.getElementById("baseUrlHelp").textContent = `A Base URL is required for Hosting Provider ${hostName}.`
return;
}
window.location.href = `/repo/${hoster}/${baseUrl}/${owner}/${repoName}`;
} else {
window.location.href = `/repo/${hoster}/${owner}/${repoName}`;
}
}
function buildCrateLink() {
let formRef = document.forms["crateSelect"];
let crate = formRef.elements["crateName"].value;
let crateVer = formRef.elements["crateVersion"].value;
if (crateVer.length == 0) {
// default to latest version
window.location.href = `/crate/${crate}`;
} else {
window.location.href = `/crate/${crate}/${crateVer}`;
}
}

View file

@ -23,13 +23,17 @@ $family-monospace: "Source Serif Pro", monospace
@import "bulma/base/generic" @import "bulma/base/generic"
@import "bulma/elements/box" @import "bulma/elements/box"
@import "bulma/elements/button"
@import "bulma/elements/container" @import "bulma/elements/container"
@import "bulma/elements/content" @import "bulma/elements/content"
@import "bulma/elements/form"
@import "bulma/elements/notification" @import "bulma/elements/notification"
@import "bulma/elements/table" @import "bulma/elements/table"
@import "bulma/elements/tag" @import "bulma/elements/tag"
@import "bulma/elements/title" @import "bulma/elements/title"
@import "bulma/form/_all"
@import "bulma/components/level" @import "bulma/components/level"
@import "bulma/components/message" @import "bulma/components/message"
@import "bulma/components/navbar" @import "bulma/components/navbar"

View file

@ -18,6 +18,7 @@ fn build_style() -> String {
fn main() { fn main() {
let out_dir = env::var("OUT_DIR").unwrap(); let out_dir = env::var("OUT_DIR").unwrap();
// compile the sass files into a single CSS file to be served and cached
let style = build_style(); let style = build_style();
let css_path = Path::new(&out_dir).join("style.css"); let css_path = Path::new(&out_dir).join("style.css");
@ -26,4 +27,13 @@ fn main() {
let hash_path = Path::new(&out_dir).join("style.css.sha1"); let hash_path = Path::new(&out_dir).join("style.css.sha1");
let digest = Sha1::digest(style.as_bytes()); let digest = Sha1::digest(style.as_bytes());
fs::write(hash_path, format!("{:x}", digest)).unwrap(); fs::write(hash_path, format!("{:x}", digest)).unwrap();
// hash and copy the JS file
let js_blob = fs::read("./assets/links.js").unwrap();
let js_path = Path::new(&out_dir).join("links.js");
fs::write(js_path, &js_blob).unwrap();
let js_hash_path = Path::new(&out_dir).join("links.js.sha1");
let js_digest = Sha1::digest(&js_blob);
fs::write(js_hash_path, format!("{:x}", js_digest)).unwrap();
} }

View file

@ -10,3 +10,15 @@ pub const STATIC_STYLE_CSS_ETAG: &str = concat!(
"\"" "\""
); );
pub static STATIC_FAVICON: &[u8] = include_bytes!("../../assets/logo.svg"); pub static STATIC_FAVICON: &[u8] = include_bytes!("../../assets/logo.svg");
pub static STATIC_LINKS_JS: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/links.js"));
pub const STATIC_LINKS_JS_PATH: &str = concat!(
"/static/links.",
include_str!(concat!(env!("OUT_DIR"), "/links.js.sha1")),
".js"
);
pub const STATIC_LINKS_JS_ETAG: &str = concat!(
"\"",
include_str!(concat!(env!("OUT_DIR"), "/links.js.sha1")),
"\""
);

View file

@ -15,7 +15,9 @@ use slog::{error, info, o, Logger};
mod assets; mod assets;
mod views; mod views;
use self::assets::{STATIC_STYLE_CSS_ETAG, STATIC_STYLE_CSS_PATH}; use self::assets::{
STATIC_LINKS_JS_ETAG, STATIC_LINKS_JS_PATH, STATIC_STYLE_CSS_ETAG, STATIC_STYLE_CSS_PATH,
};
use crate::engine::{AnalyzeDependenciesOutcome, Engine}; use crate::engine::{AnalyzeDependenciesOutcome, Engine};
use crate::models::crates::{CrateName, CratePath}; use crate::models::crates::{CrateName, CratePath};
use crate::models::repo::RepoPath; use crate::models::repo::RepoPath;
@ -31,6 +33,7 @@ enum StatusFormat {
enum StaticFile { enum StaticFile {
StyleCss, StyleCss,
FaviconPng, FaviconPng,
LinksJs,
} }
enum Route { enum Route {
@ -56,6 +59,7 @@ impl App {
router.add(STATIC_STYLE_CSS_PATH, Route::Static(StaticFile::StyleCss)); router.add(STATIC_STYLE_CSS_PATH, Route::Static(StaticFile::StyleCss));
router.add("/static/logo.svg", Route::Static(StaticFile::FaviconPng)); router.add("/static/logo.svg", Route::Static(StaticFile::FaviconPng));
router.add(STATIC_LINKS_JS_PATH, Route::Static(StaticFile::LinksJs));
router.add( router.add(
"/repo/*site/:qual/:name", "/repo/*site/:qual/:name",
@ -371,6 +375,12 @@ impl App {
.header(CONTENT_TYPE, "image/svg+xml") .header(CONTENT_TYPE, "image/svg+xml")
.body(Body::from(assets::STATIC_FAVICON)) .body(Body::from(assets::STATIC_FAVICON))
.unwrap(), .unwrap(),
StaticFile::LinksJs => Response::builder()
.header(CONTENT_TYPE, "text/javascript; charset=utf-8")
.header(ETAG, STATIC_LINKS_JS_ETAG)
.header(CACHE_CONTROL, "public, max-age=365000000, immutable")
.body(Body::from(assets::STATIC_LINKS_JS))
.unwrap(),
} }
} }
} }

View file

@ -4,6 +4,94 @@ use maud::{html, Markup};
use crate::models::crates::CratePath; use crate::models::crates::CratePath;
use crate::models::repo::Repository; use crate::models::repo::Repository;
use crate::server::assets::STATIC_LINKS_JS_PATH;
fn link_forms() -> Markup {
html! {
div class="columns" {
div class="column" {
div class="box" {
h2 class="title c is-3" { "Check a Repository" }
form id="repoSelect" action="#" {
div class="field" {
label class="label" { "Hosting Provider" }
div class="control" {
div class="select" {
select id="hosterSelect" {
option { "Github" }
option { "Gitlab" }
option { "Bitbucket" }
option { "Sourcehut" }
option { "Codeberg" }
option { "Gitea" }
}
}
}
}
div class="field" {
label class="label" { "Owner" }
div class="control" {
input class="input" type="text" id="owner" placeholder="rust-lang" required;
}
}
div class="field" {
label class="label" { "Repository Name" }
div class="control" {
input class="input" type="text" id="repoName" placeholder="cargo" required;
}
}
div class="field" {
label class="label" { "Git instance URL" }
div class="control" {
input class="input" type="text" id="baseUrl" placeholder="gitea.com";
}
p class="help" id="baseUrlHelp" { "Base URL of the Git instance the project is hosted on. Only relevant for Gitea Instances." }
}
input type="submit" class="button is-primary" value="Check" onclick="buildRepoLink();";
}
}
}
div class="column" {
div class="box" {
h2 class="title is-3" { "Check a Crate" }
form id="crateSelect" action="#" {
div class="field" {
label class="label" { "Crate Name" }
div class="control" {
input class="input" type="text" id="crateName" placeholder="serde-derive" required;
}
}
div class="field" {
label class="label" { "Version (optional)" }
div class="control" {
input class="input" type="text" id="crateVersion" placeholder="1.0.0";
}
p class="help" { "If left blank, defaults to the latest version." }
}
input type="submit" class="button is-primary" value="Check" onclick="buildCrateLink();";
}
}
}
}
}
}
fn popular_table(popular_repos: Vec<Repository>, popular_crates: Vec<CratePath>) -> Markup { fn popular_table(popular_repos: Vec<Repository>, popular_crates: Vec<CratePath>) -> Markup {
html! { html! {
div class="columns" { div class="columns" {
@ -83,7 +171,11 @@ pub fn render(popular_repos: Vec<Repository>, popular_crates: Vec<CratePath>) ->
section class="section" { section class="section" {
div class="container" { (popular_table(popular_repos, popular_crates)) } div class="container" { (popular_table(popular_repos, popular_crates)) }
} }
section class="section" {
div class="container" { (link_forms()) }
}
(super::render_footer(None)) (super::render_footer(None))
script src=(STATIC_LINKS_JS_PATH) {}
}, },
) )
} }