mirror of
https://github.com/iflytek/skillhub.git
synced 2026-10-09 03:17:52 +00:00
feat(web): add header nav to landing page and local dev improvements
- Add sticky header with LanguageSwitcher and UserMenu to landing page - Update token dialog and i18n translations - Fix dev process script and compose release config - Remove stale skillhub submodule reference
This commit is contained in:
parent
cfc296181f
commit
fd790a9610
6 changed files with 50 additions and 11 deletions
|
|
@ -7,6 +7,7 @@ import subprocess
|
|||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
|
||||
def is_running(pid: int) -> bool:
|
||||
|
|
@ -17,7 +18,7 @@ def is_running(pid: int) -> bool:
|
|||
return True
|
||||
|
||||
|
||||
def read_pid(pid_file: Path) -> int | None:
|
||||
def read_pid(pid_file: Path) -> Optional[int]:
|
||||
if not pid_file.exists():
|
||||
return None
|
||||
content = pid_file.read_text(encoding="utf-8").strip()
|
||||
|
|
|
|||
1
skillhub
1
skillhub
|
|
@ -1 +0,0 @@
|
|||
Subproject commit a3c66108c6750a44f703e227ade992ee7715d099
|
||||
|
|
@ -14,6 +14,7 @@ import {
|
|||
import { Button } from '@/shared/ui/button'
|
||||
import { Input } from '@/shared/ui/input'
|
||||
import { Label } from '@/shared/ui/label'
|
||||
import { toast } from '@/shared/lib/toast'
|
||||
import type { CreateTokenRequest, CreateTokenResponse } from '@/api/types'
|
||||
|
||||
interface CreateTokenDialogProps {
|
||||
|
|
@ -48,6 +49,18 @@ export function CreateTokenDialog({ children }: CreateTokenDialogProps) {
|
|||
createMutation.reset()
|
||||
}
|
||||
|
||||
const handleCopyToken = async () => {
|
||||
if (!createdToken) return
|
||||
|
||||
try {
|
||||
await navigator.clipboard.writeText(createdToken.token)
|
||||
toast.success(t('createToken.copySuccess'))
|
||||
} catch (error) {
|
||||
console.error('Failed to copy token:', error)
|
||||
toast.error(t('createToken.copyFailed'))
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>{children}</DialogTrigger>
|
||||
|
|
@ -109,11 +122,7 @@ export function CreateTokenDialog({ children }: CreateTokenDialogProps) {
|
|||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(createdToken.token)
|
||||
}}
|
||||
>
|
||||
<Button onClick={handleCopyToken}>
|
||||
{t('createToken.copyToken')}
|
||||
</Button>
|
||||
<Button variant="outline" onClick={handleClose}>
|
||||
|
|
|
|||
|
|
@ -399,7 +399,9 @@
|
|||
"successDescription": "Copy and save this token now. It will only be shown once.",
|
||||
"tokenLabel": "Token",
|
||||
"nameDisplay": "Name",
|
||||
"copyToken": "Copy Token"
|
||||
"copyToken": "Copy Token",
|
||||
"copySuccess": "Token copied to clipboard",
|
||||
"copyFailed": "Failed to copy token. Please try again."
|
||||
},
|
||||
"starButton": {
|
||||
"starred": "Starred",
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@
|
|||
"viewStars": "查看我的收藏",
|
||||
"credentials": "访问凭证",
|
||||
"openTokens": "打开 Token 页面",
|
||||
"governanceTitle": "查看提交审核",
|
||||
"governanceTitle": "审核与治理",
|
||||
"viewPromotions": "查看提升审核"
|
||||
},
|
||||
"mySkills": {
|
||||
|
|
@ -399,7 +399,9 @@
|
|||
"successDescription": "请立即复制并保存此 Token,它只会显示一次",
|
||||
"tokenLabel": "Token",
|
||||
"nameDisplay": "名称",
|
||||
"copyToken": "复制 Token"
|
||||
"copyToken": "复制 Token",
|
||||
"copySuccess": "Token 已复制到剪贴板",
|
||||
"copyFailed": "复制 Token 失败,请重试"
|
||||
},
|
||||
"starButton": {
|
||||
"starred": "已收藏",
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
import { useNavigate } from '@tanstack/react-router'
|
||||
import { Link, useNavigate } from '@tanstack/react-router'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { SearchBar } from '@/features/search/search-bar'
|
||||
import { useAuth } from '@/features/auth/use-auth'
|
||||
import { LanguageSwitcher } from '@/shared/components/language-switcher'
|
||||
import { UserMenu } from '@/shared/components/user-menu'
|
||||
import { Button } from '@/shared/ui/button'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
|
||||
export function LandingPage() {
|
||||
const { t } = useTranslation()
|
||||
const navigate = useNavigate()
|
||||
const { user, isLoading } = useAuth()
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null)
|
||||
const [stats] = useState({
|
||||
skills: '1000+',
|
||||
|
|
@ -146,6 +150,28 @@ export function LandingPage() {
|
|||
|
||||
return (
|
||||
<div className="relative min-h-screen overflow-hidden bg-gradient-to-br from-slate-950 via-indigo-950 to-slate-900">
|
||||
<header className="sticky top-0 z-50 border-b border-slate-700/30 bg-slate-950/60 backdrop-blur-lg">
|
||||
<div className="container mx-auto flex items-center justify-between px-6 py-3">
|
||||
<Link to="/" className="text-lg font-bold text-transparent bg-clip-text bg-gradient-to-r from-cyan-300 to-blue-400">
|
||||
SkillHub
|
||||
</Link>
|
||||
<nav className="flex items-center gap-4">
|
||||
<LanguageSwitcher />
|
||||
{isLoading ? null : user ? (
|
||||
<UserMenu user={user} />
|
||||
) : (
|
||||
<Link
|
||||
to="/login"
|
||||
search={{ returnTo: '' }}
|
||||
className="text-sm text-slate-300 hover:text-cyan-400 transition-colors"
|
||||
>
|
||||
{t('nav.login')}
|
||||
</Link>
|
||||
)}
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className="absolute inset-0 pointer-events-none"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue