mirror of
https://github.com/getnora-io/nora.git
synced 2026-04-12 10:20:32 +00:00
Fix code formatting
This commit is contained in:
@@ -119,12 +119,7 @@ async fn download_file(
|
|||||||
"application/octet-stream"
|
"application/octet-stream"
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (StatusCode::OK, [(header::CONTENT_TYPE, content_type)], data).into_response();
|
||||||
StatusCode::OK,
|
|
||||||
[(header::CONTENT_TYPE, content_type)],
|
|
||||||
data,
|
|
||||||
)
|
|
||||||
.into_response();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try proxy if configured
|
// Try proxy if configured
|
||||||
@@ -161,11 +156,7 @@ async fn download_file(
|
|||||||
"application/octet-stream"
|
"application/octet-stream"
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (StatusCode::OK, [(header::CONTENT_TYPE, content_type)], data)
|
||||||
StatusCode::OK,
|
|
||||||
[(header::CONTENT_TYPE, content_type)],
|
|
||||||
data,
|
|
||||||
)
|
|
||||||
.into_response();
|
.into_response();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,20 +158,25 @@ fn sidebar_dark(active_page: Option<&str>, t: &Translations) -> String {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
"#,
|
"#,
|
||||||
nav_html,
|
nav_html, t.nav_registries, VERSION
|
||||||
t.nav_registries,
|
|
||||||
VERSION
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dark theme header with language switcher
|
/// Dark theme header with language switcher
|
||||||
fn header_dark(lang: Lang) -> String {
|
fn header_dark(lang: Lang) -> String {
|
||||||
let (en_class, ru_class) = match lang {
|
let (en_class, ru_class) = match lang {
|
||||||
Lang::En => ("text-white font-semibold", "text-slate-400 hover:text-slate-200"),
|
Lang::En => (
|
||||||
Lang::Ru => ("text-slate-400 hover:text-slate-200", "text-white font-semibold"),
|
"text-white font-semibold",
|
||||||
|
"text-slate-400 hover:text-slate-200",
|
||||||
|
),
|
||||||
|
Lang::Ru => (
|
||||||
|
"text-slate-400 hover:text-slate-200",
|
||||||
|
"text-white font-semibold",
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
format!(r##"
|
format!(
|
||||||
|
r##"
|
||||||
<header class="h-16 bg-[#1e293b] border-b border-slate-700 flex items-center justify-between px-4 md:px-6">
|
<header class="h-16 bg-[#1e293b] border-b border-slate-700 flex items-center justify-between px-4 md:px-6">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<button onclick="toggleSidebar()" class="md:hidden p-2 -ml-2 mr-2 rounded-lg hover:bg-slate-700">
|
<button onclick="toggleSidebar()" class="md:hidden p-2 -ml-2 mr-2 rounded-lg hover:bg-slate-700">
|
||||||
@@ -202,7 +207,9 @@ fn header_dark(lang: Lang) -> String {
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
"##, en_class, ru_class)
|
"##,
|
||||||
|
en_class, ru_class
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render global stats row (5-column grid)
|
/// Render global stats row (5-column grid)
|
||||||
@@ -240,11 +247,16 @@ pub fn render_global_stats(
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
"##,
|
"##,
|
||||||
t.stat_downloads, downloads,
|
t.stat_downloads,
|
||||||
t.stat_uploads, uploads,
|
downloads,
|
||||||
t.stat_artifacts, artifacts,
|
t.stat_uploads,
|
||||||
t.stat_cache_hit, cache_hit_percent,
|
uploads,
|
||||||
t.stat_storage, format_size(storage_bytes)
|
t.stat_artifacts,
|
||||||
|
artifacts,
|
||||||
|
t.stat_cache_hit,
|
||||||
|
cache_hit_percent,
|
||||||
|
t.stat_storage,
|
||||||
|
format_size(storage_bytes)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,15 +306,22 @@ pub fn render_registry_card(
|
|||||||
icon_path,
|
icon_path,
|
||||||
t.active,
|
t.active,
|
||||||
name,
|
name,
|
||||||
t.artifacts, artifact_count,
|
t.artifacts,
|
||||||
t.size, format_size(size_bytes),
|
artifact_count,
|
||||||
t.downloads, downloads,
|
t.size,
|
||||||
t.uploads, uploads
|
format_size(size_bytes),
|
||||||
|
t.downloads,
|
||||||
|
downloads,
|
||||||
|
t.uploads,
|
||||||
|
uploads
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render mount points table
|
/// Render mount points table
|
||||||
pub fn render_mount_points_table(mount_points: &[(String, String, Option<String>)], t: &Translations) -> String {
|
pub fn render_mount_points_table(
|
||||||
|
mount_points: &[(String, String, Option<String>)],
|
||||||
|
t: &Translations,
|
||||||
|
) -> String {
|
||||||
let rows: String = mount_points
|
let rows: String = mount_points
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(registry, mount_path, proxy)| {
|
.map(|(registry, mount_path, proxy)| {
|
||||||
@@ -342,11 +361,7 @@ pub fn render_mount_points_table(mount_points: &[(String, String, Option<String>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
"##,
|
"##,
|
||||||
t.mount_points,
|
t.mount_points, t.registry, t.mount_path, t.proxy_upstream, rows
|
||||||
t.registry,
|
|
||||||
t.mount_path,
|
|
||||||
t.proxy_upstream,
|
|
||||||
rows
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -648,7 +663,8 @@ pub fn html_escape(s: &str) -> String {
|
|||||||
/// Render the "bragging" footer with NORA stats
|
/// Render the "bragging" footer with NORA stats
|
||||||
pub fn render_bragging_footer(lang: Lang) -> String {
|
pub fn render_bragging_footer(lang: Lang) -> String {
|
||||||
let t = get_translations(lang);
|
let t = get_translations(lang);
|
||||||
format!(r##"
|
format!(
|
||||||
|
r##"
|
||||||
<div class="mt-8 bg-gradient-to-r from-slate-800 to-slate-900 rounded-lg border border-slate-700 p-6">
|
<div class="mt-8 bg-gradient-to-r from-slate-800 to-slate-900 rounded-lg border border-slate-700 p-6">
|
||||||
<div class="text-center mb-4">
|
<div class="text-center mb-4">
|
||||||
<span class="text-slate-400 text-sm uppercase tracking-wider">{}</span>
|
<span class="text-slate-400 text-sm uppercase tracking-wider">{}</span>
|
||||||
|
|||||||
@@ -71,7 +71,10 @@ async fn dashboard(
|
|||||||
Query(query): Query<LangQuery>,
|
Query(query): Query<LangQuery>,
|
||||||
headers: axum::http::HeaderMap,
|
headers: axum::http::HeaderMap,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let lang = extract_lang(&Query(query), headers.get("cookie").and_then(|v| v.to_str().ok()));
|
let lang = extract_lang(
|
||||||
|
&Query(query),
|
||||||
|
headers.get("cookie").and_then(|v| v.to_str().ok()),
|
||||||
|
);
|
||||||
let response = api_dashboard(State(state)).await.0;
|
let response = api_dashboard(State(state)).await.0;
|
||||||
Html(render_dashboard(&response, lang))
|
Html(render_dashboard(&response, lang))
|
||||||
}
|
}
|
||||||
@@ -82,9 +85,17 @@ async fn docker_list(
|
|||||||
Query(query): Query<LangQuery>,
|
Query(query): Query<LangQuery>,
|
||||||
headers: axum::http::HeaderMap,
|
headers: axum::http::HeaderMap,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let lang = extract_lang(&Query(query), headers.get("cookie").and_then(|v| v.to_str().ok()));
|
let lang = extract_lang(
|
||||||
|
&Query(query),
|
||||||
|
headers.get("cookie").and_then(|v| v.to_str().ok()),
|
||||||
|
);
|
||||||
let repos = get_docker_repos(&state.storage).await;
|
let repos = get_docker_repos(&state.storage).await;
|
||||||
Html(render_registry_list("docker", "Docker Registry", &repos, lang))
|
Html(render_registry_list(
|
||||||
|
"docker",
|
||||||
|
"Docker Registry",
|
||||||
|
&repos,
|
||||||
|
lang,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn docker_detail(
|
async fn docker_detail(
|
||||||
@@ -93,7 +104,10 @@ async fn docker_detail(
|
|||||||
Query(query): Query<LangQuery>,
|
Query(query): Query<LangQuery>,
|
||||||
headers: axum::http::HeaderMap,
|
headers: axum::http::HeaderMap,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let lang = extract_lang(&Query(query), headers.get("cookie").and_then(|v| v.to_str().ok()));
|
let lang = extract_lang(
|
||||||
|
&Query(query),
|
||||||
|
headers.get("cookie").and_then(|v| v.to_str().ok()),
|
||||||
|
);
|
||||||
let detail = get_docker_detail(&state.storage, &name).await;
|
let detail = get_docker_detail(&state.storage, &name).await;
|
||||||
Html(render_docker_detail(&name, &detail, lang))
|
Html(render_docker_detail(&name, &detail, lang))
|
||||||
}
|
}
|
||||||
@@ -104,9 +118,17 @@ async fn maven_list(
|
|||||||
Query(query): Query<LangQuery>,
|
Query(query): Query<LangQuery>,
|
||||||
headers: axum::http::HeaderMap,
|
headers: axum::http::HeaderMap,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let lang = extract_lang(&Query(query), headers.get("cookie").and_then(|v| v.to_str().ok()));
|
let lang = extract_lang(
|
||||||
|
&Query(query),
|
||||||
|
headers.get("cookie").and_then(|v| v.to_str().ok()),
|
||||||
|
);
|
||||||
let repos = get_maven_repos(&state.storage).await;
|
let repos = get_maven_repos(&state.storage).await;
|
||||||
Html(render_registry_list("maven", "Maven Repository", &repos, lang))
|
Html(render_registry_list(
|
||||||
|
"maven",
|
||||||
|
"Maven Repository",
|
||||||
|
&repos,
|
||||||
|
lang,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn maven_detail(
|
async fn maven_detail(
|
||||||
@@ -115,7 +137,10 @@ async fn maven_detail(
|
|||||||
Query(query): Query<LangQuery>,
|
Query(query): Query<LangQuery>,
|
||||||
headers: axum::http::HeaderMap,
|
headers: axum::http::HeaderMap,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let lang = extract_lang(&Query(query), headers.get("cookie").and_then(|v| v.to_str().ok()));
|
let lang = extract_lang(
|
||||||
|
&Query(query),
|
||||||
|
headers.get("cookie").and_then(|v| v.to_str().ok()),
|
||||||
|
);
|
||||||
let detail = get_maven_detail(&state.storage, &path).await;
|
let detail = get_maven_detail(&state.storage, &path).await;
|
||||||
Html(render_maven_detail(&path, &detail, lang))
|
Html(render_maven_detail(&path, &detail, lang))
|
||||||
}
|
}
|
||||||
@@ -126,7 +151,10 @@ async fn npm_list(
|
|||||||
Query(query): Query<LangQuery>,
|
Query(query): Query<LangQuery>,
|
||||||
headers: axum::http::HeaderMap,
|
headers: axum::http::HeaderMap,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let lang = extract_lang(&Query(query), headers.get("cookie").and_then(|v| v.to_str().ok()));
|
let lang = extract_lang(
|
||||||
|
&Query(query),
|
||||||
|
headers.get("cookie").and_then(|v| v.to_str().ok()),
|
||||||
|
);
|
||||||
let packages = get_npm_packages(&state.storage).await;
|
let packages = get_npm_packages(&state.storage).await;
|
||||||
Html(render_registry_list("npm", "npm Registry", &packages, lang))
|
Html(render_registry_list("npm", "npm Registry", &packages, lang))
|
||||||
}
|
}
|
||||||
@@ -137,7 +165,10 @@ async fn npm_detail(
|
|||||||
Query(query): Query<LangQuery>,
|
Query(query): Query<LangQuery>,
|
||||||
headers: axum::http::HeaderMap,
|
headers: axum::http::HeaderMap,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let lang = extract_lang(&Query(query), headers.get("cookie").and_then(|v| v.to_str().ok()));
|
let lang = extract_lang(
|
||||||
|
&Query(query),
|
||||||
|
headers.get("cookie").and_then(|v| v.to_str().ok()),
|
||||||
|
);
|
||||||
let detail = get_npm_detail(&state.storage, &name).await;
|
let detail = get_npm_detail(&state.storage, &name).await;
|
||||||
Html(render_package_detail("npm", &name, &detail, lang))
|
Html(render_package_detail("npm", &name, &detail, lang))
|
||||||
}
|
}
|
||||||
@@ -148,9 +179,17 @@ async fn cargo_list(
|
|||||||
Query(query): Query<LangQuery>,
|
Query(query): Query<LangQuery>,
|
||||||
headers: axum::http::HeaderMap,
|
headers: axum::http::HeaderMap,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let lang = extract_lang(&Query(query), headers.get("cookie").and_then(|v| v.to_str().ok()));
|
let lang = extract_lang(
|
||||||
|
&Query(query),
|
||||||
|
headers.get("cookie").and_then(|v| v.to_str().ok()),
|
||||||
|
);
|
||||||
let crates = get_cargo_crates(&state.storage).await;
|
let crates = get_cargo_crates(&state.storage).await;
|
||||||
Html(render_registry_list("cargo", "Cargo Registry", &crates, lang))
|
Html(render_registry_list(
|
||||||
|
"cargo",
|
||||||
|
"Cargo Registry",
|
||||||
|
&crates,
|
||||||
|
lang,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn cargo_detail(
|
async fn cargo_detail(
|
||||||
@@ -159,7 +198,10 @@ async fn cargo_detail(
|
|||||||
Query(query): Query<LangQuery>,
|
Query(query): Query<LangQuery>,
|
||||||
headers: axum::http::HeaderMap,
|
headers: axum::http::HeaderMap,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let lang = extract_lang(&Query(query), headers.get("cookie").and_then(|v| v.to_str().ok()));
|
let lang = extract_lang(
|
||||||
|
&Query(query),
|
||||||
|
headers.get("cookie").and_then(|v| v.to_str().ok()),
|
||||||
|
);
|
||||||
let detail = get_cargo_detail(&state.storage, &name).await;
|
let detail = get_cargo_detail(&state.storage, &name).await;
|
||||||
Html(render_package_detail("cargo", &name, &detail, lang))
|
Html(render_package_detail("cargo", &name, &detail, lang))
|
||||||
}
|
}
|
||||||
@@ -170,9 +212,17 @@ async fn pypi_list(
|
|||||||
Query(query): Query<LangQuery>,
|
Query(query): Query<LangQuery>,
|
||||||
headers: axum::http::HeaderMap,
|
headers: axum::http::HeaderMap,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let lang = extract_lang(&Query(query), headers.get("cookie").and_then(|v| v.to_str().ok()));
|
let lang = extract_lang(
|
||||||
|
&Query(query),
|
||||||
|
headers.get("cookie").and_then(|v| v.to_str().ok()),
|
||||||
|
);
|
||||||
let packages = get_pypi_packages(&state.storage).await;
|
let packages = get_pypi_packages(&state.storage).await;
|
||||||
Html(render_registry_list("pypi", "PyPI Repository", &packages, lang))
|
Html(render_registry_list(
|
||||||
|
"pypi",
|
||||||
|
"PyPI Repository",
|
||||||
|
&packages,
|
||||||
|
lang,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn pypi_detail(
|
async fn pypi_detail(
|
||||||
@@ -181,7 +231,10 @@ async fn pypi_detail(
|
|||||||
Query(query): Query<LangQuery>,
|
Query(query): Query<LangQuery>,
|
||||||
headers: axum::http::HeaderMap,
|
headers: axum::http::HeaderMap,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let lang = extract_lang(&Query(query), headers.get("cookie").and_then(|v| v.to_str().ok()));
|
let lang = extract_lang(
|
||||||
|
&Query(query),
|
||||||
|
headers.get("cookie").and_then(|v| v.to_str().ok()),
|
||||||
|
);
|
||||||
let detail = get_pypi_detail(&state.storage, &name).await;
|
let detail = get_pypi_detail(&state.storage, &name).await;
|
||||||
Html(render_package_detail("pypi", &name, &detail, lang))
|
Html(render_package_detail("pypi", &name, &detail, lang))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,10 @@ pub fn render_dashboard(data: &DashboardResponse, lang: Lang) -> String {
|
|||||||
|
|
||||||
// Render activity log
|
// Render activity log
|
||||||
let activity_rows: String = if data.activity.is_empty() {
|
let activity_rows: String = if data.activity.is_empty() {
|
||||||
format!(r##"<tr><td colspan="5" class="py-8 text-center text-slate-500">{}</td></tr>"##, t.no_activity)
|
format!(
|
||||||
|
r##"<tr><td colspan="5" class="py-8 text-center text-slate-500">{}</td></tr>"##,
|
||||||
|
t.no_activity
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
data.activity
|
data.activity
|
||||||
.iter()
|
.iter()
|
||||||
@@ -131,7 +134,13 @@ pub fn render_dashboard(data: &DashboardResponse, lang: Lang) -> String {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let polling_script = render_polling_script();
|
let polling_script = render_polling_script();
|
||||||
layout_dark(t.dashboard_title, &content, Some("dashboard"), &polling_script, lang)
|
layout_dark(
|
||||||
|
t.dashboard_title,
|
||||||
|
&content,
|
||||||
|
Some("dashboard"),
|
||||||
|
&polling_script,
|
||||||
|
lang,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Format timestamp as relative time (e.g., "2 min ago")
|
/// Format timestamp as relative time (e.g., "2 min ago")
|
||||||
@@ -154,16 +163,24 @@ fn format_relative_time(timestamp: &chrono::DateTime<chrono::Utc>) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Renders a registry list page (docker, maven, npm, cargo, pypi)
|
/// Renders a registry list page (docker, maven, npm, cargo, pypi)
|
||||||
pub fn render_registry_list(registry_type: &str, title: &str, repos: &[RepoInfo], lang: Lang) -> String {
|
pub fn render_registry_list(
|
||||||
|
registry_type: &str,
|
||||||
|
title: &str,
|
||||||
|
repos: &[RepoInfo],
|
||||||
|
lang: Lang,
|
||||||
|
) -> String {
|
||||||
let t = get_translations(lang);
|
let t = get_translations(lang);
|
||||||
let icon = get_registry_icon(registry_type);
|
let icon = get_registry_icon(registry_type);
|
||||||
|
|
||||||
let table_rows = if repos.is_empty() {
|
let table_rows = if repos.is_empty() {
|
||||||
format!(r##"<tr><td colspan="4" class="px-6 py-12 text-center text-slate-500">
|
format!(
|
||||||
|
r##"<tr><td colspan="4" class="px-6 py-12 text-center text-slate-500">
|
||||||
<div class="text-4xl mb-2">📭</div>
|
<div class="text-4xl mb-2">📭</div>
|
||||||
<div>{}</div>
|
<div>{}</div>
|
||||||
<div class="text-sm mt-1">{}</div>
|
<div class="text-sm mt-1">{}</div>
|
||||||
</td></tr>"##, t.no_repos_found, t.push_first_artifact)
|
</td></tr>"##,
|
||||||
|
t.no_repos_found, t.push_first_artifact
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
repos
|
repos
|
||||||
.iter()
|
.iter()
|
||||||
@@ -340,11 +357,22 @@ pub fn render_docker_detail(name: &str, detail: &DockerDetail, lang: Lang) -> St
|
|||||||
tags_rows
|
tags_rows
|
||||||
);
|
);
|
||||||
|
|
||||||
layout_dark(&format!("{} - Docker", name), &content, Some("docker"), "", lang)
|
layout_dark(
|
||||||
|
&format!("{} - Docker", name),
|
||||||
|
&content,
|
||||||
|
Some("docker"),
|
||||||
|
"",
|
||||||
|
lang,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Renders package detail page (npm, cargo, pypi)
|
/// Renders package detail page (npm, cargo, pypi)
|
||||||
pub fn render_package_detail(registry_type: &str, name: &str, detail: &PackageDetail, lang: Lang) -> String {
|
pub fn render_package_detail(
|
||||||
|
registry_type: &str,
|
||||||
|
name: &str,
|
||||||
|
detail: &PackageDetail,
|
||||||
|
lang: Lang,
|
||||||
|
) -> String {
|
||||||
let _t = get_translations(lang);
|
let _t = get_translations(lang);
|
||||||
let icon = get_registry_icon(registry_type);
|
let icon = get_registry_icon(registry_type);
|
||||||
let registry_title = get_registry_title(registry_type);
|
let registry_title = get_registry_title(registry_type);
|
||||||
@@ -531,7 +559,13 @@ pub fn render_maven_detail(path: &str, detail: &MavenDetail, lang: Lang) -> Stri
|
|||||||
artifact_rows
|
artifact_rows
|
||||||
);
|
);
|
||||||
|
|
||||||
layout_dark(&format!("{} - Maven", path), &content, Some("maven"), "", lang)
|
layout_dark(
|
||||||
|
&format!("{} - Maven", path),
|
||||||
|
&content,
|
||||||
|
Some("maven"),
|
||||||
|
"",
|
||||||
|
lang,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns SVG icon path for the registry type
|
/// Returns SVG icon path for the registry type
|
||||||
|
|||||||
Reference in New Issue
Block a user