201 lines
5.6 KiB
TypeScript
201 lines
5.6 KiB
TypeScript
import React, { useState } from "react";
|
|
import useGiteaCommits from "../../hooks/useGiteaCommits";
|
|
import GiteaCommitItem from "./GiteaCommitItem";
|
|
import "../../styles/GiteaWidget.css";
|
|
import {
|
|
FaCodeBranch,
|
|
FaSync,
|
|
FaExclamationTriangle,
|
|
FaServer,
|
|
} from "react-icons/fa";
|
|
|
|
export const GiteaWidget = ({
|
|
defaultGiteaUrl = "https://git.konceptkit.com/",
|
|
defaultRepo = "owner/repo",
|
|
token = null,
|
|
limit = 5,
|
|
branch = "main",
|
|
title = "Recent Commits",
|
|
}) => {
|
|
const [giteaUrl, setGiteaUrl] = useState(defaultGiteaUrl);
|
|
const [repo, setRepo] = useState(defaultRepo);
|
|
const [inputGiteaUrl, setInputGiteaUrl] = useState(defaultGiteaUrl);
|
|
const [inputRepo, setInputRepo] = useState(defaultRepo);
|
|
const [showAdvanced, setShowAdvanced] = useState(false);
|
|
|
|
const { commits, loading, error } = useGiteaCommits(
|
|
giteaUrl,
|
|
repo,
|
|
token,
|
|
limit,
|
|
branch
|
|
);
|
|
|
|
const handleSubmit = (e) => {
|
|
e.preventDefault();
|
|
|
|
// Validate URL
|
|
let url = inputGiteaUrl;
|
|
if (!url.startsWith("http")) {
|
|
url = `https://${url}`;
|
|
}
|
|
|
|
// Remove trailing slash if present
|
|
url = url.replace(/\/$/, "");
|
|
|
|
setGiteaUrl(url);
|
|
|
|
// Validate repo format
|
|
if (inputRepo.includes("/")) {
|
|
setRepo(inputRepo);
|
|
} else {
|
|
alert('Repository must be in format "owner/repo"');
|
|
}
|
|
};
|
|
|
|
// Example preset repositories
|
|
const presetRepos = [
|
|
{ label: "Documentation", value: "owner/docs" },
|
|
{ label: "API Server", value: "owner/api-server" },
|
|
{ label: "Web App", value: "owner/web-app" },
|
|
];
|
|
|
|
return (
|
|
<div className="gitea-widget border-[#e1e4e8] rounded-2xl shadow-sm border-l-8 border-l-lime-600">
|
|
<div className="github-widget-header rounded-t-2xl">
|
|
<FaServer className="gitea-icon" />
|
|
<h3>{title}</h3>
|
|
|
|
<button
|
|
className="advanced-toggle"
|
|
onClick={() => setShowAdvanced(!showAdvanced)}
|
|
>
|
|
{showAdvanced ? "Simple" : "Advanced"}
|
|
</button>
|
|
</div>
|
|
|
|
{showAdvanced ? (
|
|
<form onSubmit={handleSubmit} className="config-form">
|
|
<div className="form-group">
|
|
<label>
|
|
<FaServer /> Gitea Instance URL
|
|
</label>
|
|
<input
|
|
type="text"
|
|
value={inputGiteaUrl}
|
|
onChange={(e) => setInputGiteaUrl(e.target.value)}
|
|
placeholder="https://gitea.example.com"
|
|
className="url-input"
|
|
/>
|
|
</div>
|
|
|
|
<div className="form-group">
|
|
<label>
|
|
<FaCodeBranch /> Repository
|
|
</label>
|
|
<input
|
|
type="text"
|
|
value={inputRepo}
|
|
onChange={(e) => setInputRepo(e.target.value)}
|
|
placeholder="owner/repository"
|
|
className="repo-input"
|
|
/>
|
|
<div className="preset-repos">
|
|
{presetRepos.map((preset) => (
|
|
<button
|
|
key={preset.value}
|
|
type="button"
|
|
className="preset-btn"
|
|
onClick={() => setInputRepo(preset.value)}
|
|
>
|
|
{preset.label}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<button type="submit" className="refresh-btn">
|
|
<FaSync /> Load Commits
|
|
</button>
|
|
</form>
|
|
) : (
|
|
<form onSubmit={handleSubmit} className="simple-form">
|
|
<div className="input-group">
|
|
<input
|
|
type="text"
|
|
value={inputRepo}
|
|
onChange={(e) => setInputRepo(e.target.value)}
|
|
placeholder="owner/repo"
|
|
className="simple-input"
|
|
/>
|
|
<button type="submit" className="simple-btn">
|
|
<FaSync />
|
|
</button>
|
|
</div>
|
|
</form>
|
|
)}
|
|
|
|
<div className="current-config">
|
|
<small>
|
|
Instance: <code>{giteaUrl}</code> | Repo: <code>{repo}</code> |
|
|
Branch: <code>{branch}</code>
|
|
</small>
|
|
</div>
|
|
|
|
<div className="widget-body">
|
|
{loading ? (
|
|
<div className="loading">
|
|
<div className="spinner"></div>
|
|
Loading commits from {repo}...
|
|
</div>
|
|
) : error ? (
|
|
<div className="error">
|
|
<FaExclamationTriangle />
|
|
<div className="error-details">
|
|
<p>Failed to load commits</p>
|
|
<small>{error}</small>
|
|
<p className="help-text">
|
|
Ensure:
|
|
<ul>
|
|
<li>Gitea instance is accessible</li>
|
|
<li>Repository exists and is accessible</li>
|
|
<li>API token has correct permissions (if private repo)</li>
|
|
</ul>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<div className="commits-list">
|
|
{commits.length > 0 ? (
|
|
commits.map((commit) => (
|
|
<GiteaCommitItem
|
|
key={commit.sha}
|
|
commit={commit}
|
|
giteaUrl={giteaUrl}
|
|
repo={repo}
|
|
/>
|
|
))
|
|
) : (
|
|
<div className="no-commits">
|
|
No commits found in the {branch} branch
|
|
</div>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="widget-footer">
|
|
<a
|
|
href={`${giteaUrl}/${repo}`}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="view-all"
|
|
>
|
|
View on Gitea →
|
|
</a>
|
|
<span className="commit-count">{commits.length} commits shown</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|