feat: 設定画面を実装
Workspace・認証モード・保存容量・配布上限・API情報を一覧表示する 設定画面を追加した。OIDCモードではログインユーザー表示とログアウト ボタンを表示し、demoモードではアカウント情報を固定表示する。 - settings用のグリッド/行/バッジ/クォータスタイルをglobals.cssに追加 - AdminShellの未使用変数警告を解消
This commit is contained in:
@@ -1,7 +1,86 @@
|
||||
import Link from "next/link";
|
||||
import { ArrowUpRight, KeyRound, ShieldCheck, SlidersHorizontal } from "lucide-react";
|
||||
"use client";
|
||||
|
||||
export default function SettingsPage() {
|
||||
return <><div className="admin-page-heading"><div><div className="admin-eyebrow">WORKSPACE SETTINGS</div><h1>設定</h1><p>認証と配布上限は環境設定で管理します。</p></div></div><section className="admin-section-card settings-placeholder"><div className="settings-placeholder-icon"><SlidersHorizontal size={20} /></div><h2>設定画面は準備中です</h2><p>SSO、ストレージ、アップロード上限は現在の環境変数と管理者設定で制御されています。</p><div className="settings-placeholder-grid"><div><ShieldCheck size={17} /><strong>認証</strong><span>OIDC / demo mode</span></div><div><KeyRound size={17} /><strong>配布</strong><span>Workspace単位の認可</span></div></div><Link className="admin-link" href="https://faq.altstore.io/developers/distribute-with-altstore-pal" target="_blank">PALドキュメントを開く <ArrowUpRight size={14} /></Link></section></>;
|
||||
import { useEffect, useState } from "react";
|
||||
import { BookOpen, Database, HardDrive, KeyRound, LogOut, Server, ShieldCheck, SlidersHorizontal, User, Workflow } from "lucide-react";
|
||||
import { API_BASE, AUTH_MODE, formatBytes } from "@/app/lib/dashboard";
|
||||
import { useDashboard } from "@/components/altdock/dashboard-provider";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import type { Identity } from "@/packages/core/src/index";
|
||||
|
||||
function SettingRow({ icon: Icon, label, value, hint }: { icon: typeof User; label: string; value: React.ReactNode; hint?: string }) {
|
||||
return <div className="settings-row"><span className="settings-row-icon"><Icon size={16} strokeWidth={1.8} /></span><div className="settings-row-copy"><span>{label}</span><strong>{value}</strong>{hint && <small>{hint}</small>}</div></div>;
|
||||
}
|
||||
|
||||
function Section({ title, description, children }: { title: string; description: string; children: React.ReactNode }) {
|
||||
return <section className="admin-section-card settings-section"><div className="admin-section-card-header"><div><h2>{title}</h2><p>{description}</p></div></div>{children}</section>;
|
||||
}
|
||||
|
||||
export default function SettingsPage() {
|
||||
const { dashboard } = useDashboard();
|
||||
const [identity, setIdentity] = useState<Identity | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (AUTH_MODE !== "oidc") return;
|
||||
let cancelled = false;
|
||||
fetch(`${API_BASE}/api/v1/me`, { credentials: "include" })
|
||||
.then((response) => response.ok ? response.json() : null)
|
||||
.then((body) => { if (!cancelled && body?.identity) setIdentity(body.identity as Identity); })
|
||||
.catch(() => {});
|
||||
return () => { cancelled = true; };
|
||||
}, []);
|
||||
|
||||
const storagePercent = dashboard ? Math.min(100, (dashboard.usage.storageBytes / Math.max(1, dashboard.limits.maxStorageBytes)) * 100) : 0;
|
||||
|
||||
return <>
|
||||
<div className="admin-page-heading"><div><div className="admin-eyebrow">WORKSPACE SETTINGS</div><h1>設定</h1><p>Workspace・認証・配布上限の状態を確認できます。</p></div></div>
|
||||
|
||||
<div className="settings-grid">
|
||||
<Section title="Workspace" description="AltDock上の配布単位となるWorkspace情報です。">
|
||||
<div className="settings-rows">
|
||||
<SettingRow icon={Workflow} label="Workspace名" value={dashboard?.workspace.name || "—"} />
|
||||
<SettingRow icon={SlidersHorizontal} label="Workspace slug" value={<code>{dashboard?.workspace.slug || "—"}</code>} />
|
||||
<SettingRow icon={User} label="ログインユーザー" value={AUTH_MODE === "oidc" ? (identity?.displayName || "—") : "Demo Developer"} hint={AUTH_MODE === "oidc" ? identity?.email : "demo@altdock.local"} />
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="認証" description="このAPIに接続している認証モードです。">
|
||||
<div className="settings-rows">
|
||||
<SettingRow icon={ShieldCheck} label="認証モード" value={AUTH_MODE === "oidc" ? <span className="settings-badge settings-badge-ok">OIDC SSO</span> : <span className="settings-badge">Demo mode</span>} hint={AUTH_MODE === "oidc" ? "汎用OIDCプロバイダでログインしています" : "開発用の簡易認証です。本番ではOIDCを推奨します"} />
|
||||
{AUTH_MODE === "oidc" && <SettingRow icon={KeyRound} label="SSOセッション" value={identity ? <span className="settings-badge settings-badge-ok">ログイン中</span> : <span className="settings-badge">セッション確認中…</span>} />}
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="保存容量" description="Workspaceで使用しているストレージの割合です。">
|
||||
<div className="settings-quota">
|
||||
<div className="settings-quota-top"><span>{formatBytes(dashboard?.usage.storageBytes || 0)} / {formatBytes(dashboard?.limits.maxStorageBytes || 0)}</span><strong>{storagePercent.toFixed(1)}%</strong></div>
|
||||
<div className="admin-progress"><span style={{ width: `${storagePercent}%` }} /></div>
|
||||
<small>ADP ZIP本体と公開済みアセットの合計サイズ</small>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="配布上限" description="環境変数で変更できる制限値です。">
|
||||
<div className="settings-rows">
|
||||
<SettingRow icon={HardDrive} label="ADP ZIP 1件の上限" value={formatBytes(dashboard?.limits.maxUploadBytes || 0)} />
|
||||
<SettingRow icon={Database} label="WorkspaceあたりのSource数" value={dashboard?.limits.maxSources || "—"} />
|
||||
<SettingRow icon={Workflow} label="Sourceあたりのアプリ数" value={dashboard?.limits.maxAppsPerSource || "—"} />
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="API" description="フロントエンドが利用しているAPIエンドポイントです。">
|
||||
<div className="settings-rows">
|
||||
<SettingRow icon={Server} label="API Base URL" value={<code>{API_BASE}</code>} />
|
||||
<SettingRow icon={Server} label="ヘルスチェック" value={<a className="admin-link" href={`${API_BASE}/healthz`} target="_blank" rel="noreferrer">/healthz を開く</a>} />
|
||||
<SettingRow icon={Server} label="バージョン" value={<a className="admin-link" href={`${API_BASE}/version`} target="_blank" rel="noreferrer">/version を開く</a>} />
|
||||
</div>
|
||||
</Section>
|
||||
</div>
|
||||
|
||||
<section className="admin-section-card settings-footer">
|
||||
<div><ShieldCheck size={17} /><span><strong>AltDock 管理画面</strong><small>Source・アプリ・リリースは左のナビゲーションから操作できます。</small></span></div>
|
||||
<div className="settings-footer-actions">
|
||||
<Button variant="outline" size="sm" onClick={() => window.open("https://faq.altstore.io/developers/distribute-with-altstore-pal", "_blank")}><BookOpen size={14} />PALドキュメント</Button>
|
||||
{AUTH_MODE === "oidc" && <Button variant="ghost" size="sm" onClick={() => { window.location.href = `${API_BASE}/auth/logout`; }}><LogOut size={14} />ログアウト</Button>}
|
||||
</div>
|
||||
</section>
|
||||
</>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user