chore: update style of admin pages

This commit is contained in:
Zhang Minghan 2024-01-11 08:59:13 +08:00
parent 4a3c957284
commit fa8f5b5b64
17 changed files with 54 additions and 25 deletions

View File

@ -16,6 +16,14 @@
height: max-content;
}
.admin-card {
border: 0 !important;
@media (max-width: 768px) {
border-radius: 0 !important;
}
}
.object-id {
display: flex;
flex-direction: row;

View File

@ -17,6 +17,10 @@
border: 1px solid hsl(var(--border));
padding-bottom: 0.5rem;
.channel-id {
color: hsl(var(--text-secondary));
}
&:hover {
border-color: hsl(var(--border-hover));
}

View File

@ -37,7 +37,7 @@
color: hsl(var(--text-secondary));
&:hover {
background: hsl(var(--card-hover));
color: hsl(var(--text));
}
&.active {
@ -54,12 +54,16 @@
}
.menu-item-icon {
width: 1.5rem;
height: 1.5rem;
scale: 0.95;
width: 1.25rem;
height: 1.25rem;
margin-right: 0.5rem;
margin-left: 0.5rem;
transform: translateY(1px);
svg {
width: 1.25rem;
height: 1.25rem;
}
}
}

View File

@ -43,7 +43,7 @@
--text: 0 0% 0%;
--text-dark: 0 0% 100%;
--text-secondary: 0 0% 20%;
--text-secondary: 0 0% 35%;
--text-secondary-dark: 0 0% 80%;
--selection: 212 100% 41%;

View File

@ -81,7 +81,9 @@ function ChannelTable({ display, setId, setEnabled }: ChannelTableProps) {
<TableBody>
{(data || []).map((chan, idx) => (
<TableRow key={idx}>
<TableCell>{chan.id}</TableCell>
<TableCell className={`channel-id select-none`}>
#{chan.id}
</TableCell>
<TableCell>{chan.name}</TableCell>
<TableCell>
<TypeBadge type={chan.type} />

View File

@ -3,6 +3,7 @@ import { useMemo } from "react";
import { useTranslation } from "react-i18next";
import { getModelColor } from "@/admin/colors.ts";
import { Loader2 } from "lucide-react";
import Tips from "@/components/Tips.tsx";
type ModelChartProps = {
labels: string[];
@ -70,7 +71,10 @@ function ModelChart({ labels, datasets, dark }: ModelChartProps) {
return (
<div className={`chart`}>
<p className={`chart-title mb-2`}>
<p>{t("admin.model-chart")}</p>
<p className={`flex flex-row items-center`}>
{t("admin.model-chart")}
<Tips content={t("admin.model-chart-tip")} />
</p>
{labels.length === 0 && (
<Loader2 className={`h-4 w-4 inline-block animate-spin`} />
)}

View File

@ -349,6 +349,7 @@
"subscription-users": "订阅用户",
"seat": "位",
"model-chart": "模型使用统计",
"model-chart-tip": "Token 用量",
"request-chart": "请求量统计",
"billing-chart": "收入统计",
"error-chart": "错误统计",

View File

@ -467,7 +467,8 @@
"custom-image": "Custom Image",
"custom-image-placeholder": "Please enter an image link",
"update": "Update"
}
},
"model-chart-tip": "Token usage"
},
"mask": {
"title": "Mask Settings",

View File

@ -467,7 +467,8 @@
"custom-image": "カスタム画像",
"custom-image-placeholder": "画像リンクを入力してください",
"update": "更新"
}
},
"model-chart-tip": "トークンの使用状況"
},
"mask": {
"title": "プリセット設定",

View File

@ -467,7 +467,8 @@
"custom-image": "Пользовательское изображение",
"custom-image-placeholder": "Введите ссылку на изображение",
"update": "Обновить"
}
},
"model-chart-tip": "Использование токенов"
},
"mask": {
"title": "Настройки маски",

View File

@ -13,7 +13,7 @@ import Register from "@/routes/Register.tsx";
import Forgot from "@/routes/Forgot.tsx";
import { lazyFactor } from "@/utils/loader.tsx";
import { useSelector } from "react-redux";
import { selectAdmin, selectAuthenticated } from "@/store/auth.ts";
import { selectAdmin, selectAuthenticated, selectInit } from "@/store/auth.ts";
const Generation = lazyFactor(() => import("@/routes/Generation.tsx"));
const Sharing = lazyFactor(() => import("@/routes/Sharing.tsx"));
@ -183,43 +183,46 @@ const router = createBrowserRouter(
);
export function AuthRequired({ children }: { children: React.ReactNode }) {
const init = useSelector(selectInit);
const authenticated = useSelector(selectAuthenticated);
const navigate = useNavigate();
const location = useLocation();
useEffect(() => {
if (!authenticated) {
if (init && !authenticated) {
navigate("/login", { state: { from: location.pathname } });
}
}, [authenticated]);
}, [init, authenticated]);
return <>{children}</>;
}
export function AuthForbidden({ children }: { children: React.ReactNode }) {
const init = useSelector(selectInit);
const authenticated = useSelector(selectAuthenticated);
const navigate = useNavigate();
const location = useLocation();
useEffect(() => {
if (authenticated) {
if (init && authenticated) {
navigate("/", { state: { from: location.pathname } });
}
}, [authenticated]);
}, [init, authenticated]);
return <>{children}</>;
}
export function AdminRequired({ children }: { children: React.ReactNode }) {
const init = useSelector(selectInit);
const admin = useSelector(selectAdmin);
const navigate = useNavigate();
const location = useLocation();
useEffect(() => {
if (!admin) {
if (init && !admin) {
navigate("/", { state: { from: location.pathname } });
}
}, [admin]);
}, [init, admin]);
return <>{children}</>;
}

View File

@ -11,7 +11,7 @@ function Broadcast() {
const { t } = useTranslation();
return (
<div className={`broadcast`}>
<Card className={`broadcast-card`}>
<Card className={`admin-card broadcast-card`}>
<CardHeader className={`select-none`}>
<CardTitle>{t("admin.broadcast")}</CardTitle>
</CardHeader>

View File

@ -12,7 +12,7 @@ function Channel() {
return (
<div className={`channel`}>
<Card className={`channel-card`}>
<Card className={`admin-card channel-card`}>
<CardHeader className={`select-none`}>
<CardTitle>{t("admin.channel")}</CardTitle>
</CardHeader>

View File

@ -12,7 +12,7 @@ function Charge() {
return (
<div className={`charge`}>
<Card className={`charge-card`}>
<Card className={`admin-card charge-card`}>
<CardHeader className={`select-none`}>
<CardTitle>{t("admin.prize")}</CardTitle>
</CardHeader>

View File

@ -384,7 +384,7 @@ function Market() {
return (
<div className={`market`}>
<Card className={`market-card`}>
<Card className={`admin-card market-card`}>
<CardHeader className={`flex flex-row items-center select-none`}>
<CardTitle>{t("admin.market.title")}</CardTitle>
<Button

View File

@ -411,7 +411,7 @@ function System() {
return (
<div className={`system`}>
<Card className={`system-card`}>
<Card className={`admin-card system-card`}>
<CardHeader className={`select-none`}>
<CardTitle>{t("admin.settings")}</CardTitle>
</CardHeader>

View File

@ -16,7 +16,7 @@ function Users() {
return (
<div className={`user-interface ${mobile ? "mobile" : ""}`}>
<Card>
<Card className={`admin-card`}>
<CardHeader className={`select-none`}>
<CardTitle>{t("admin.user")}</CardTitle>
</CardHeader>
@ -24,7 +24,7 @@ function Users() {
<UserTable />
</CardContent>
</Card>
<Card>
<Card className={`admin-card`}>
<CardHeader className={`select-none`}>
<CardTitle className={`flex items-center`}>
{t("admin.invitation-manage")}
@ -38,7 +38,7 @@ function Users() {
<InvitationTable />
</CardContent>
</Card>
<Card>
<Card className={`admin-card`}>
<CardHeader className={`select-none`}>
<CardTitle className={`flex items-center`}>
{t("admin.invitation")}