feat(repo): return ssh/https clone URLs from backend
Some checks are pending
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run

Add ssh_clone_url and https_clone_url to ProjectRepositoryItem,
constructed from config.ssh_domain() and config.git_http_domain().
Update frontend RepoInfo interface and header.tsx to use the
server-provided URLs instead of hardcoded values.
This commit is contained in:
ZhenYi 2026-04-16 18:20:48 +08:00
parent b1e93a7cfc
commit 8b433c9169
3 changed files with 35 additions and 17 deletions

View File

@ -1,7 +1,7 @@
use crate::AppService;
use crate::error::AppError; use crate::error::AppError;
use crate::AppService;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use models::projects::{Project, project_members}; use models::projects::{project_members, Project};
use models::repos::repo::{ use models::repos::repo::{
ActiveModel as RepoActiveModel, Column as RepoColumn, Entity as RepoEntity, ActiveModel as RepoActiveModel, Column as RepoColumn, Entity as RepoEntity,
}; };
@ -34,6 +34,8 @@ pub struct ProjectRepositoryItem {
pub star_count: i64, pub star_count: i64,
pub watch_count: i64, pub watch_count: i64,
pub last_commit_at: Option<DateTime<Utc>>, pub last_commit_at: Option<DateTime<Utc>>,
pub ssh_clone_url: String,
pub https_clone_url: String,
} }
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, ToSchema)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize, ToSchema)]
@ -200,9 +202,16 @@ impl AppService {
map map
}; };
let ssh_domain = self
.config
.ssh_domain()
.unwrap_or_else(|_| "code".to_string());
let items: Vec<ProjectRepositoryItem> = repo_list let items: Vec<ProjectRepositoryItem> = repo_list
.into_iter() .into_iter()
.map(|r| ProjectRepositoryItem { .map(|r| {
let path = format!("{}/{}", project.name, r.repo_name);
ProjectRepositoryItem {
uid: r.id, uid: r.id,
repo_name: r.repo_name, repo_name: r.repo_name,
description: r.description, description: r.description,
@ -215,6 +224,9 @@ impl AppService {
star_count: *star_counts.get(&r.id).unwrap_or(&0), star_count: *star_counts.get(&r.id).unwrap_or(&0),
watch_count: *watch_counts.get(&r.id).unwrap_or(&0), watch_count: *watch_counts.get(&r.id).unwrap_or(&0),
last_commit_at: last_commit_times.get(&r.id).and_then(|t| *t), last_commit_at: last_commit_times.get(&r.id).and_then(|t| *t),
ssh_clone_url: format!("git@{}:{}", ssh_domain, path),
https_clone_url: format!("https://{}/{}", ssh_domain, path),
}
}) })
.collect(); .collect();

View File

@ -61,8 +61,8 @@ export const RepoHeader = () => {
}, },
}); });
const cloneUrl = `git@code:${namespace}/${repo_name}.git`; const cloneUrl = repo.ssh_clone_url;
const httpUrl = `${window.location.origin}/${namespace}/${repo_name}`; const httpUrl = repo.https_clone_url;
const copyUrl = (url: string, label: string) => { const copyUrl = (url: string, label: string) => {
navigator.clipboard.writeText(url); navigator.clipboard.writeText(url);

View File

@ -25,6 +25,10 @@ export interface RepoInfo {
is_star: boolean; is_star: boolean;
/** Whether the current user is watching this repo */ /** Whether the current user is watching this repo */
is_watch: boolean; is_watch: boolean;
/** SSH clone URL */
ssh_clone_url: string;
/** HTTPS clone URL */
https_clone_url: string;
} }
export const RepositoryContext = React.createContext<RepoInfo | null>(null); export const RepositoryContext = React.createContext<RepoInfo | null>(null);
@ -95,6 +99,8 @@ export const RepositoryContextProvider = ({
last_commit_at: repoItem.last_commit_at, last_commit_at: repoItem.last_commit_at,
is_star: Boolean(starCountResp), is_star: Boolean(starCountResp),
is_watch: Boolean(watchCountResp), is_watch: Boolean(watchCountResp),
ssh_clone_url: repoItem.ssh_clone_url,
https_clone_url: repoItem.https_clone_url,
}; };
}, [repoItem, namespace, starCountResp, watchCountResp]); }, [repoItem, namespace, starCountResp, watchCountResp]);