mirror of
https://github.com/RayLabsHQ/gitea-mirror.git
synced 2025-12-07 03:56:46 +03:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2bec1d56e | ||
|
|
c9404f2674 | ||
|
|
80ef19c634 | ||
|
|
83c924566c |
10
CHANGELOG.md
10
CHANGELOG.md
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2.16.3] - 2025-06-20
|
||||
|
||||
### Added
|
||||
- Custom 404 error page with helpful navigation links
|
||||
- HoverCard components for better UX in configuration forms
|
||||
|
||||
### Improved
|
||||
- Replaced popover components with hover cards for information tooltips
|
||||
- Enhanced user experience with responsive hover interactions
|
||||
|
||||
## [2.16.2] - 2025-06-17
|
||||
|
||||
### Added
|
||||
|
||||
3
bun.lock
3
bun.lock
@@ -15,6 +15,7 @@
|
||||
"@radix-ui/react-collapsible": "^1.1.11",
|
||||
"@radix-ui/react-dialog": "^1.1.14",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.15",
|
||||
"@radix-ui/react-hover-card": "^1.1.14",
|
||||
"@radix-ui/react-label": "^2.1.7",
|
||||
"@radix-ui/react-popover": "^1.1.14",
|
||||
"@radix-ui/react-radio-group": "^1.3.7",
|
||||
@@ -334,6 +335,8 @@
|
||||
|
||||
"@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw=="],
|
||||
|
||||
"@radix-ui/react-hover-card": ["@radix-ui/react-hover-card@1.1.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-popper": "1.2.7", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-CPYZ24Mhirm+g6D8jArmLzjYu4Eyg3TTUHswR26QgzXBHBe64BO/RHOJKzmF/Dxb4y4f9PKyJdwm/O/AhNkb+Q=="],
|
||||
|
||||
"@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="],
|
||||
|
||||
"@radix-ui/react-label": ["@radix-ui/react-label@2.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ=="],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "gitea-mirror",
|
||||
"type": "module",
|
||||
"version": "2.16.2",
|
||||
"version": "2.16.3",
|
||||
"engines": {
|
||||
"bun": ">=1.2.9"
|
||||
},
|
||||
@@ -42,6 +42,7 @@
|
||||
"@radix-ui/react-collapsible": "^1.1.11",
|
||||
"@radix-ui/react-dialog": "^1.1.14",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.15",
|
||||
"@radix-ui/react-hover-card": "^1.1.14",
|
||||
"@radix-ui/react-label": "^2.1.7",
|
||||
"@radix-ui/react-popover": "^1.1.14",
|
||||
"@radix-ui/react-radio-group": "^1.3.7",
|
||||
|
||||
81
src/components/NotFound.tsx
Normal file
81
src/components/NotFound.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
import React from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
||||
import { Home, ArrowLeft, GitBranch, BookOpen, Settings, FileQuestion } from "lucide-react";
|
||||
|
||||
export function NotFound() {
|
||||
return (
|
||||
<div className="h-dvh bg-muted/30 flex items-center justify-center p-4">
|
||||
<Card className="w-full max-w-md">
|
||||
<CardHeader className="text-center pb-4">
|
||||
<div className="mx-auto mb-4 h-16 w-16 rounded-full bg-muted flex items-center justify-center">
|
||||
<FileQuestion className="h-8 w-8 text-muted-foreground" />
|
||||
</div>
|
||||
<h1 className="text-3xl font-bold">404</h1>
|
||||
<h2 className="text-xl font-semibold mt-2">Page Not Found</h2>
|
||||
<p className="text-muted-foreground mt-2">
|
||||
The page you're looking for doesn't exist or has been moved.
|
||||
</p>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent className="space-y-6">
|
||||
{/* Action Buttons */}
|
||||
<div className="flex flex-col gap-3">
|
||||
<Button asChild className="w-full">
|
||||
<a href="/">
|
||||
<Home className="mr-2 h-4 w-4" />
|
||||
Go to Dashboard
|
||||
</a>
|
||||
</Button>
|
||||
<Button variant="outline" className="w-full" onClick={() => window.history.back()}>
|
||||
<ArrowLeft className="mr-2 h-4 w-4" />
|
||||
Go Back
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Divider */}
|
||||
<div className="relative">
|
||||
<div className="absolute inset-0 flex items-center">
|
||||
<span className="w-full border-t" />
|
||||
</div>
|
||||
<div className="relative flex justify-center text-xs uppercase">
|
||||
<span className="bg-card px-2 text-muted-foreground">or visit</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Quick Links */}
|
||||
<div className="grid grid-cols-3 gap-3">
|
||||
<a
|
||||
href="/repositories"
|
||||
className="flex flex-col items-center gap-2 p-3 rounded-md hover:bg-muted transition-colors"
|
||||
>
|
||||
<GitBranch className="h-5 w-5 text-muted-foreground" />
|
||||
<span className="text-xs">Repositories</span>
|
||||
</a>
|
||||
<a
|
||||
href="/config"
|
||||
className="flex flex-col items-center gap-2 p-3 rounded-md hover:bg-muted transition-colors"
|
||||
>
|
||||
<Settings className="h-5 w-5 text-muted-foreground" />
|
||||
<span className="text-xs">Config</span>
|
||||
</a>
|
||||
<a
|
||||
href="/docs"
|
||||
className="flex flex-col items-center gap-2 p-3 rounded-md hover:bg-muted transition-colors"
|
||||
>
|
||||
<BookOpen className="h-5 w-5 text-muted-foreground" />
|
||||
<span className="text-xs">Docs</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Error Code */}
|
||||
<div className="text-center pt-2">
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Error Code: <code className="font-mono">404_NOT_FOUND</code>
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -14,10 +14,10 @@ import { Info } from "lucide-react";
|
||||
import { GitHubMirrorSettings } from "./GitHubMirrorSettings";
|
||||
import { Separator } from "../ui/separator";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
HoverCard,
|
||||
HoverCardContent,
|
||||
HoverCardTrigger,
|
||||
} from "@/components/ui/hover-card";
|
||||
|
||||
interface GitHubConfigFormProps {
|
||||
config: GitHubConfig;
|
||||
@@ -130,16 +130,13 @@ export function GitHubConfigForm({
|
||||
>
|
||||
GitHub Token
|
||||
</label>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className="p-0.5 hover:bg-muted rounded-sm transition-colors"
|
||||
>
|
||||
<HoverCard openDelay={200}>
|
||||
<HoverCardTrigger asChild>
|
||||
<span className="inline-flex p-0.5 hover:bg-muted rounded-sm transition-colors cursor-help">
|
||||
<Info className="h-3.5 w-3.5 text-muted-foreground" />
|
||||
</button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent side="right" align="start" className="w-80">
|
||||
</span>
|
||||
</HoverCardTrigger>
|
||||
<HoverCardContent side="right" align="start" className="w-80">
|
||||
<div className="space-y-2">
|
||||
<h4 className="font-medium text-sm">GitHub Token Requirements</h4>
|
||||
<div className="text-sm space-y-2">
|
||||
@@ -166,8 +163,8 @@ export function GitHubConfigForm({
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</HoverCardContent>
|
||||
</HoverCard>
|
||||
</div>
|
||||
<Input
|
||||
id="github-token"
|
||||
|
||||
@@ -3,10 +3,10 @@ import { Card } from "@/components/ui/card";
|
||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
||||
import { Info, GitBranch, FolderTree, Star, Building2, User, Building } from "lucide-react";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
HoverCard,
|
||||
HoverCardContent,
|
||||
HoverCardTrigger,
|
||||
} from "@/components/ui/hover-card";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export type MirrorStrategy = "preserve" | "single-org" | "flat-user";
|
||||
@@ -275,17 +275,16 @@ export const OrganizationStrategy: React.FC<OrganizationStrategyProps> = ({
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className="p-1.5 hover:bg-muted rounded-md transition-colors"
|
||||
<HoverCard openDelay={200}>
|
||||
<HoverCardTrigger asChild>
|
||||
<span
|
||||
className="inline-flex p-1.5 hover:bg-muted rounded-md transition-colors cursor-help"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Info className="h-4 w-4 text-muted-foreground" />
|
||||
</button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent side="left" align="center" className="w-[500px]">
|
||||
</span>
|
||||
</HoverCardTrigger>
|
||||
<HoverCardContent side="left" align="center" className="w-[500px]">
|
||||
<div className="space-y-3">
|
||||
<h4 className="font-medium text-sm">Repository Mapping Preview</h4>
|
||||
<MappingPreview
|
||||
@@ -297,8 +296,8 @@ export const OrganizationStrategy: React.FC<OrganizationStrategyProps> = ({
|
||||
giteaUsername={giteaUsername}
|
||||
/>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</HoverCardContent>
|
||||
</HoverCard>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
42
src/components/ui/hover-card.tsx
Normal file
42
src/components/ui/hover-card.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import * as React from "react"
|
||||
import * as HoverCardPrimitive from "@radix-ui/react-hover-card"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function HoverCard({
|
||||
...props
|
||||
}: React.ComponentProps<typeof HoverCardPrimitive.Root>) {
|
||||
return <HoverCardPrimitive.Root data-slot="hover-card" {...props} />
|
||||
}
|
||||
|
||||
function HoverCardTrigger({
|
||||
...props
|
||||
}: React.ComponentProps<typeof HoverCardPrimitive.Trigger>) {
|
||||
return (
|
||||
<HoverCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
function HoverCardContent({
|
||||
className,
|
||||
align = "center",
|
||||
sideOffset = 4,
|
||||
...props
|
||||
}: React.ComponentProps<typeof HoverCardPrimitive.Content>) {
|
||||
return (
|
||||
<HoverCardPrimitive.Portal data-slot="hover-card-portal">
|
||||
<HoverCardPrimitive.Content
|
||||
data-slot="hover-card-content"
|
||||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-64 origin-(--radix-hover-card-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</HoverCardPrimitive.Portal>
|
||||
)
|
||||
}
|
||||
|
||||
export { HoverCard, HoverCardTrigger, HoverCardContent }
|
||||
37
src/pages/404.astro
Normal file
37
src/pages/404.astro
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
import '../styles/global.css';
|
||||
import ThemeScript from '@/components/theme/ThemeScript.astro';
|
||||
import { NotFound } from '@/components/NotFound';
|
||||
|
||||
const generator = Astro.generator;
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="generator" content={generator} />
|
||||
<title>Page Not Found - Gitea Mirror</title>
|
||||
<ThemeScript />
|
||||
</head>
|
||||
<body>
|
||||
<NotFound client:load />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style>
|
||||
/* Floating animation for 404 text */
|
||||
:global(.animate-float) {
|
||||
animation: float 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user