Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions app/[nsfront]/[nsbehind]/[name]/[version]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,22 @@ const CratePage = () => {
const [error, setError] = useState<string | null>(null);
const [packageCurrentPage, setPackageCurrentPage] = useState(1);
const [depCurrentPage, setDepCurrentPage] = useState(1);
const [versions, setVersions] = useState<string[]>([]);
const itemsPerPage = 1;
const basePath = `/${params.nsfront}/${params.nsbehind}/${params.name}/${params.version}`;
const basePath = `/${params.nsfront}/${params.nsbehind}/${params.name}`;

useEffect(() => {
const fetchCrateData = async () => {
try {
// 首先获取所有版本信息
const versionsResponse = await fetch(`/api/crates/${params.nsfront}/${params.nsbehind}/${params.name}/all`);
if (!versionsResponse.ok) {
throw new Error(`HTTP error! status: ${versionsResponse.status}`);
}
const versionsData = await versionsResponse.json();
setVersions(versionsData.versions || []);

// 获取当前URL版本的数据
const response = await fetch(`/api/crates/${params.nsfront}/${params.nsbehind}/${params.name}/${params.version}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
Expand All @@ -171,11 +181,12 @@ const CratePage = () => {
setError('An error occurred');
} finally {
setLoading(false);
console.log('results', versions);
}
};

fetchCrateData();
}, [params.name, params.version, params.nsfront, params.nsbehind]);
}, [params.name, params.nsfront, params.nsbehind]);

if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error}</p>;
Expand Down
23 changes: 23 additions & 0 deletions app/api/crates/[nsfront]/[nsbehind]/[cratename]/all/route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { NextRequest, NextResponse } from "next/server";
type Params = Promise<{ nsfront: string, nsbehind: string, cratename: string, version: string }>

export async function GET(req: NextRequest, props: { params: Params }) {
try {
const params = await props.params
const { nsfront, nsbehind, cratename } = params;
const endpoint = process.env.CRATES_PRO_INTERNAL_HOST;

const externalApiUrl = `${endpoint}/api/crates/${nsfront}/${nsbehind}/${cratename}/all`; // 替换为你的外部 API URL
const externalRes = await fetch(externalApiUrl);
if (!externalRes.ok) {
throw new Error('Failed to fetch external data');
}
const externalData = await externalRes.json();
console.log('crateinfo in api', externalData);
return NextResponse.json(externalData);
} catch (error) {
console.error('Error:', error);
return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });

}
}
2 changes: 1 addition & 1 deletion app/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ const Search = () => {
hover:shadow-[0_0_12px_0_rgba(43,88,221,0.2)]
`}
>
<Link href={`/${item.nsfront}/${item.nsbehind}/${item.name}/${item.version}`} className="block h-full">
<Link href={`/${item.nsfront}/${item.nsbehind}/${item.name}/all`} className="block h-full">
<div className="p-6 h-full flex flex-col justify-center">
<div className="text-sm text-gray-600 mb-1">NuGet</div>
<div className="text-blue-500 font-medium text-lg">{item.name}</div>
Expand Down
17 changes: 13 additions & 4 deletions components/CrateNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const CrateNav: React.FC<CrateNavProps> = ({ nsfront, nsbehind, name, version })
const router = useRouter();
const basePath = `/${nsfront}/${nsbehind}/${name}/${version}`;
const [isOpen, setIsOpen] = useState(false);
const [currentVersion, setCurrentVersion] = useState(version);
const [searchTerm, setSearchTerm] = useState('');
const { crateData, setCrateData } = useHeaderContext();

Expand Down Expand Up @@ -82,7 +81,7 @@ const CrateNav: React.FC<CrateNavProps> = ({ nsfront, nsbehind, name, version })
onClick={toggleDropdown}
className="flex items-center justify-between w-[150px] h-[36px] flex-shrink-0 rounded-[18.5px] border border-[#333333] bg-white px-4"
>
<span>{currentVersion || 'Select Version'}</span>
<span>{version}</span>
<Image
src={isOpen ? "/images/homepage/verison-up.png" : "/images/homepage/version-down.png"}
alt="version"
Expand All @@ -103,17 +102,27 @@ const CrateNav: React.FC<CrateNavProps> = ({ nsfront, nsbehind, name, version })
/>
</div>
<ul className="max-h-[150px] overflow-y-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none] [&:hover::-webkit-scrollbar]:block [&:hover::-webkit-scrollbar]:w-1 [&:hover::-webkit-scrollbar-thumb]:bg-gray-300 [&:hover::-webkit-scrollbar-track]:bg-transparent">
<Link
onClick={() => {
setSearchTerm('');
closeDropdown();
}}
href={`/${nsfront}/${nsbehind}/${name}/all`}
>
<li className="px-4 py-2 hover:bg-[#E2E9FF] cursor-pointer">
all
</li>
</Link>
{crateData.results?.versions
.filter(version => version.toLowerCase().includes(searchTerm.toLowerCase()))
.map((version, index) => (
<Link
key={index}
onClick={() => {
setCurrentVersion(version);
setSearchTerm('');
closeDropdown();
}}
href={`/${nsfront}/${nsbehind}/${crateData.results?.crate_name}/${version}`}
href={`/${nsfront}/${nsbehind}/${name}/${version}`}
>
<li className="px-4 py-2 hover:bg-[#E2E9FF] cursor-pointer">
{version}
Expand Down
30 changes: 16 additions & 14 deletions components/DependencyGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,25 +61,25 @@ const DependencyGraph: React.FC = () => {
svg.append('defs').append('marker')
.attr('id', 'arrowhead')
.attr('viewBox', '0 -5 10 10')
.attr('refX', 8)
.attr('refX', 12)
.attr('refY', 0)
.attr('orient', 'auto')
.attr('markerWidth', 6)
.attr('markerHeight', 6)
.attr('markerWidth', 8)
.attr('markerHeight', 8)
.append('path')
.attr('d', 'M 0,-5 L 10,0 L 0,5')
.attr('fill', '#333')
.style('stroke', 'none');

const nodesMap = new Map<string, DependencyNode>();
const links: DependencyLink[] = [];

// 根据cve_count设置节点颜色
function processDependencies(dep: GraphDependency, parent?: DependencyNode) {
const nodeId = `${dep.name_and_version}`;
let node = nodesMap.get(nodeId);
if (!node) {
const getColorByCveCount = (count: number) => {
if (count === 0) return '#2ecc71'; // 绿色
if (count === 0) return '#808080'; // 灰色
if (count >= 10) return '#8b0000'; // 深红色
if (count >= 6) return '#e74c3c'; // 红色
if (count >= 3) return '#e67e22'; // 橙色
Expand Down Expand Up @@ -108,18 +108,18 @@ const DependencyGraph: React.FC = () => {
const nodes = Array.from(nodesMap.values());

const simulation = d3.forceSimulation<DependencyNode>(nodes)
.force('link', d3.forceLink<DependencyNode, DependencyLink>(links).id(d => d.id).distance(80))
.force('charge', d3.forceManyBody().strength(-300))
.force('link', d3.forceLink<DependencyNode, DependencyLink>(links).id(d => d.id).distance(150))
.force('charge', d3.forceManyBody().strength(-500))
.force('center', d3.forceCenter(width / 2, height / 2))
.force('collide', d3.forceCollide().radius(15));
.force('collide', d3.forceCollide().radius(30));

const g = svg.append('g');

const link = g.append('g')
.selectAll('line')
.data(links)
.enter().append('line')
.attr('stroke-width', 1.5)
.attr('stroke-width', 2)
.attr('stroke', '#333')
.attr('marker-end', 'url(#arrowhead)')
.attr('x2', function (d) {
Expand All @@ -139,10 +139,10 @@ const DependencyGraph: React.FC = () => {
.selectAll('circle')
.data(nodes)
.enter().append('circle')
.attr('r', 8)
.attr('r', 15)
.attr('fill', d => d.color)
.attr('stroke', '#333')
.attr('stroke-width', 1.5)
.attr('stroke-width', 2)
.call(d3.drag<SVGCircleElement, DependencyNode>()
.on('start', dragstarted)
.on('drag', dragged)
Expand All @@ -157,9 +157,11 @@ const DependencyGraph: React.FC = () => {
.data(nodes)
.enter().append('text')
.attr('dy', '.35em')
.attr('x', d => d.x! + 10)
.attr('x', d => d.x! + 20)
.attr('y', d => d.y!)
.text(d => d.id);
.text(d => d.id)
.style('font-size', '14px')
.style('font-weight', 'bold');

simulation
.nodes(nodes)
Expand Down Expand Up @@ -189,7 +191,7 @@ const DependencyGraph: React.FC = () => {
.attr('cy', d => d.y!);

labels
.attr('x', d => d.x! + 10)
.attr('x', d => d.x! + 20)
.attr('y', d => d.y!);
}

Expand Down
6 changes: 4 additions & 2 deletions components/DependencyTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,10 @@ const DependencyTable: React.FC<DependencyTableProps> = ({ data }) => {
</div>
</div>
<Link
href={`/${params.nsfront}/${params.nsbehind}/${params.name}/${params.version}/dependencies/graph`}
className="w-[163px] h-[42px] flex-shrink-0 rounded-[21px] bg-[#4B68FF] shadow-[0_0_12px_0_#2b58dd17] text-white flex items-center justify-center hover:bg-[#3a57f0] transition-colors"
href={params.version === 'all' ? '#' : `/${params.nsfront}/${params.nsbehind}/${params.name}/${params.version}/dependencies/graph`}
className={`w-[163px] h-[42px] flex-shrink-0 rounded-[21px] shadow-[0_0_12px_0_#2b58dd17] text-white flex items-center justify-center transition-colors ${params.version === 'all' ? 'bg-gray-300' : 'bg-[#4B68FF] hover:bg-[#3a57f0]'}`}
style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}
{...(params.version === 'all' ? { tabIndex: -1, 'aria-disabled': true, onClick: (e) => e.preventDefault() } : {})}
>
<span className="font-['HarmonyOS_Sans_SC'] text-lg font-bold capitalize">Show Graph</span>
</Link>
Expand Down