mirror of
https://github.com/coaidev/coai.git
synced 2025-05-24 23:40:14 +09:00
chore: update style of admin pages
This commit is contained in:
parent
4a3c957284
commit
fa8f5b5b64
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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%;
|
||||
|
@ -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} />
|
||||
|
@ -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`} />
|
||||
)}
|
||||
|
@ -349,6 +349,7 @@
|
||||
"subscription-users": "订阅用户",
|
||||
"seat": "位",
|
||||
"model-chart": "模型使用统计",
|
||||
"model-chart-tip": "Token 用量",
|
||||
"request-chart": "请求量统计",
|
||||
"billing-chart": "收入统计",
|
||||
"error-chart": "错误统计",
|
||||
|
@ -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",
|
||||
|
@ -467,7 +467,8 @@
|
||||
"custom-image": "カスタム画像",
|
||||
"custom-image-placeholder": "画像リンクを入力してください",
|
||||
"update": "更新"
|
||||
}
|
||||
},
|
||||
"model-chart-tip": "トークンの使用状況"
|
||||
},
|
||||
"mask": {
|
||||
"title": "プリセット設定",
|
||||
|
@ -467,7 +467,8 @@
|
||||
"custom-image": "Пользовательское изображение",
|
||||
"custom-image-placeholder": "Введите ссылку на изображение",
|
||||
"update": "Обновить"
|
||||
}
|
||||
},
|
||||
"model-chart-tip": "Использование токенов"
|
||||
},
|
||||
"mask": {
|
||||
"title": "Настройки маски",
|
||||
|
@ -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}</>;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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")}
|
||||
|
Loading…
Reference in New Issue
Block a user