Some fixes
This commit is contained in:
@ -102,11 +102,26 @@ function App() {
|
||||
const [approvalNotes, setApprovalNotes] = useState<{ [key: string]: string }>(
|
||||
{},
|
||||
);
|
||||
const [editingSettings, setEditingSettings] = useState<{ [key: string]: string }>({});
|
||||
const [categories, setCategories] = useState<CategoryData>({ feedCategories: [], episodeCategories: [], allCategories: [] });
|
||||
const [categoryCounts, setCategoryCounts] = useState<{ [category: string]: CategoryCounts }>({});
|
||||
const [editingSettings, setEditingSettings] = useState<{
|
||||
[key: string]: string;
|
||||
}>({});
|
||||
const [categories, setCategories] = useState<CategoryData>({
|
||||
feedCategories: [],
|
||||
episodeCategories: [],
|
||||
allCategories: [],
|
||||
});
|
||||
const [categoryCounts, setCategoryCounts] = useState<{
|
||||
[category: string]: CategoryCounts;
|
||||
}>({});
|
||||
const [activeTab, setActiveTab] = useState<
|
||||
"dashboard" | "feeds" | "episodes" | "env" | "settings" | "batch" | "requests" | "categories"
|
||||
| "dashboard"
|
||||
| "feeds"
|
||||
| "episodes"
|
||||
| "env"
|
||||
| "settings"
|
||||
| "batch"
|
||||
| "requests"
|
||||
| "categories"
|
||||
>("dashboard");
|
||||
|
||||
useEffect(() => {
|
||||
@ -116,16 +131,23 @@ function App() {
|
||||
const loadData = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const [feedsRes, statsRes, envRes, settingsRes, requestsRes, episodesRes, categoriesRes] =
|
||||
await Promise.all([
|
||||
fetch("/api/admin/feeds"),
|
||||
fetch("/api/admin/stats"),
|
||||
fetch("/api/admin/env"),
|
||||
fetch("/api/admin/settings"),
|
||||
fetch("/api/admin/feed-requests"),
|
||||
fetch("/api/admin/episodes"),
|
||||
fetch("/api/admin/categories/all"),
|
||||
]);
|
||||
const [
|
||||
feedsRes,
|
||||
statsRes,
|
||||
envRes,
|
||||
settingsRes,
|
||||
requestsRes,
|
||||
episodesRes,
|
||||
categoriesRes,
|
||||
] = await Promise.all([
|
||||
fetch("/api/admin/feeds"),
|
||||
fetch("/api/admin/stats"),
|
||||
fetch("/api/admin/env"),
|
||||
fetch("/api/admin/settings"),
|
||||
fetch("/api/admin/feed-requests"),
|
||||
fetch("/api/admin/episodes"),
|
||||
fetch("/api/admin/categories/all"),
|
||||
]);
|
||||
|
||||
if (
|
||||
!feedsRes.ok ||
|
||||
@ -139,16 +161,23 @@ function App() {
|
||||
throw new Error("Failed to load data");
|
||||
}
|
||||
|
||||
const [feedsData, statsData, envData, settingsData, requestsData, episodesData, categoriesData] =
|
||||
await Promise.all([
|
||||
feedsRes.json(),
|
||||
statsRes.json(),
|
||||
envRes.json(),
|
||||
settingsRes.json(),
|
||||
requestsRes.json(),
|
||||
episodesRes.json(),
|
||||
categoriesRes.json(),
|
||||
]);
|
||||
const [
|
||||
feedsData,
|
||||
statsData,
|
||||
envData,
|
||||
settingsData,
|
||||
requestsData,
|
||||
episodesData,
|
||||
categoriesData,
|
||||
] = await Promise.all([
|
||||
feedsRes.json(),
|
||||
statsRes.json(),
|
||||
envRes.json(),
|
||||
settingsRes.json(),
|
||||
requestsRes.json(),
|
||||
episodesRes.json(),
|
||||
categoriesRes.json(),
|
||||
]);
|
||||
|
||||
setFeeds(feedsData);
|
||||
setStats(statsData);
|
||||
@ -157,24 +186,28 @@ function App() {
|
||||
setFeedRequests(requestsData);
|
||||
setEpisodes(episodesData);
|
||||
setCategories(categoriesData);
|
||||
|
||||
|
||||
// Load category counts for all categories
|
||||
const countsPromises = categoriesData.allCategories.map(async (category: string) => {
|
||||
const res = await fetch(`/api/admin/categories/${encodeURIComponent(category)}/counts`);
|
||||
if (res.ok) {
|
||||
const counts = await res.json();
|
||||
return { category, counts };
|
||||
}
|
||||
return { category, counts: { feedCount: 0, episodeCount: 0 } };
|
||||
});
|
||||
|
||||
const countsPromises = categoriesData.allCategories.map(
|
||||
async (category: string) => {
|
||||
const res = await fetch(
|
||||
`/api/admin/categories/${encodeURIComponent(category)}/counts`,
|
||||
);
|
||||
if (res.ok) {
|
||||
const counts = await res.json();
|
||||
return { category, counts };
|
||||
}
|
||||
return { category, counts: { feedCount: 0, episodeCount: 0 } };
|
||||
},
|
||||
);
|
||||
|
||||
const countsResults = await Promise.all(countsPromises);
|
||||
const countsMap: { [category: string]: CategoryCounts } = {};
|
||||
countsResults.forEach(({ category, counts }) => {
|
||||
countsMap[category] = counts;
|
||||
});
|
||||
setCategoryCounts(countsMap);
|
||||
|
||||
|
||||
setError(null);
|
||||
} catch (err) {
|
||||
setError("データの読み込みに失敗しました");
|
||||
@ -426,26 +459,44 @@ function App() {
|
||||
setEditingSettings({ ...editingSettings, [key]: value });
|
||||
};
|
||||
|
||||
const deleteCategory = async (category: string, target: "feeds" | "episodes" | "both") => {
|
||||
const targetText = target === "both" ? "フィードとエピソード" : target === "feeds" ? "フィード" : "エピソード";
|
||||
const counts = categoryCounts[category] || { feedCount: 0, episodeCount: 0 };
|
||||
const totalCount = target === "both" ? counts.feedCount + counts.episodeCount :
|
||||
target === "feeds" ? counts.feedCount : counts.episodeCount;
|
||||
const deleteCategory = async (
|
||||
category: string,
|
||||
target: "feeds" | "episodes" | "both",
|
||||
) => {
|
||||
const targetText =
|
||||
target === "both"
|
||||
? "フィードとエピソード"
|
||||
: target === "feeds"
|
||||
? "フィード"
|
||||
: "エピソード";
|
||||
const counts = categoryCounts[category] || {
|
||||
feedCount: 0,
|
||||
episodeCount: 0,
|
||||
};
|
||||
const totalCount =
|
||||
target === "both"
|
||||
? counts.feedCount + counts.episodeCount
|
||||
: target === "feeds"
|
||||
? counts.feedCount
|
||||
: counts.episodeCount;
|
||||
|
||||
if (
|
||||
!confirm(
|
||||
`本当にカテゴリ「${category}」を${targetText}から削除しますか?\n\n${totalCount}件のアイテムが影響を受けます。この操作は取り消せません。`
|
||||
`本当にカテゴリ「${category}」を${targetText}から削除しますか?\n\n${totalCount}件のアイテムが影響を受けます。この操作は取り消せません。`,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await fetch(`/api/admin/categories/${encodeURIComponent(category)}`, {
|
||||
method: "DELETE",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ target }),
|
||||
});
|
||||
const res = await fetch(
|
||||
`/api/admin/categories/${encodeURIComponent(category)}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ target }),
|
||||
},
|
||||
);
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
@ -1230,26 +1281,33 @@ function App() {
|
||||
</p>
|
||||
|
||||
<div style={{ marginBottom: "20px" }}>
|
||||
<div className="stats-grid" style={{ gridTemplateColumns: "repeat(4, 1fr)" }}>
|
||||
<div
|
||||
className="stats-grid"
|
||||
style={{ gridTemplateColumns: "repeat(4, 1fr)" }}
|
||||
>
|
||||
<div className="stat-card">
|
||||
<div className="value">{settings.length}</div>
|
||||
<div className="label">総設定数</div>
|
||||
</div>
|
||||
<div className="stat-card">
|
||||
<div className="value">
|
||||
{settings.filter(s => s.value !== null && s.value !== "").length}
|
||||
{
|
||||
settings.filter(
|
||||
(s) => s.value !== null && s.value !== "",
|
||||
).length
|
||||
}
|
||||
</div>
|
||||
<div className="label">設定済み</div>
|
||||
</div>
|
||||
<div className="stat-card">
|
||||
<div className="value">
|
||||
{settings.filter(s => s.required).length}
|
||||
{settings.filter((s) => s.required).length}
|
||||
</div>
|
||||
<div className="label">必須設定</div>
|
||||
</div>
|
||||
<div className="stat-card">
|
||||
<div className="value">
|
||||
{settings.filter(s => s.isCredential).length}
|
||||
{settings.filter((s) => s.isCredential).length}
|
||||
</div>
|
||||
<div className="label">認証情報</div>
|
||||
</div>
|
||||
@ -1258,63 +1316,109 @@ function App() {
|
||||
|
||||
<div className="settings-list">
|
||||
{settings.map((setting) => (
|
||||
<div key={setting.key} className="setting-item" style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
padding: "16px",
|
||||
border: "1px solid #ddd",
|
||||
borderRadius: "4px",
|
||||
marginBottom: "12px",
|
||||
backgroundColor: setting.required && (!setting.value || setting.value === "") ? "#fff5f5" : "#fff"
|
||||
}}>
|
||||
<div
|
||||
key={setting.key}
|
||||
className="setting-item"
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
padding: "16px",
|
||||
border: "1px solid #ddd",
|
||||
borderRadius: "4px",
|
||||
marginBottom: "12px",
|
||||
backgroundColor:
|
||||
setting.required &&
|
||||
(!setting.value || setting.value === "")
|
||||
? "#fff5f5"
|
||||
: "#fff",
|
||||
}}
|
||||
>
|
||||
<div style={{ flex: 1 }}>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: "8px", marginBottom: "4px" }}>
|
||||
<h4 style={{ margin: 0, fontSize: "16px" }}>{setting.key}</h4>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "8px",
|
||||
marginBottom: "4px",
|
||||
}}
|
||||
>
|
||||
<h4 style={{ margin: 0, fontSize: "16px" }}>
|
||||
{setting.key}
|
||||
</h4>
|
||||
{setting.required && (
|
||||
<span style={{
|
||||
padding: "2px 6px",
|
||||
background: "#dc3545",
|
||||
color: "white",
|
||||
borderRadius: "4px",
|
||||
fontSize: "10px"
|
||||
}}>必須</span>
|
||||
<span
|
||||
style={{
|
||||
padding: "2px 6px",
|
||||
background: "#dc3545",
|
||||
color: "white",
|
||||
borderRadius: "4px",
|
||||
fontSize: "10px",
|
||||
}}
|
||||
>
|
||||
必須
|
||||
</span>
|
||||
)}
|
||||
{setting.isCredential && (
|
||||
<span style={{
|
||||
padding: "2px 6px",
|
||||
background: "#ffc107",
|
||||
color: "black",
|
||||
borderRadius: "4px",
|
||||
fontSize: "10px"
|
||||
}}>認証情報</span>
|
||||
<span
|
||||
style={{
|
||||
padding: "2px 6px",
|
||||
background: "#ffc107",
|
||||
color: "black",
|
||||
borderRadius: "4px",
|
||||
fontSize: "10px",
|
||||
}}
|
||||
>
|
||||
認証情報
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p style={{ margin: "0 0 8px 0", fontSize: "14px", color: "#666" }}>
|
||||
<p
|
||||
style={{
|
||||
margin: "0 0 8px 0",
|
||||
fontSize: "14px",
|
||||
color: "#666",
|
||||
}}
|
||||
>
|
||||
{setting.description}
|
||||
</p>
|
||||
<div style={{ fontSize: "12px", color: "#999" }}>
|
||||
デフォルト値: {setting.defaultValue || "なし"} |
|
||||
最終更新: {new Date(setting.updatedAt).toLocaleString("ja-JP")}
|
||||
デフォルト値: {setting.defaultValue || "なし"} |
|
||||
最終更新:{" "}
|
||||
{new Date(setting.updatedAt).toLocaleString("ja-JP")}
|
||||
</div>
|
||||
|
||||
|
||||
{editingSettings[setting.key] !== undefined ? (
|
||||
<div style={{ marginTop: "8px", display: "flex", gap: "8px", alignItems: "center" }}>
|
||||
<div
|
||||
style={{
|
||||
marginTop: "8px",
|
||||
display: "flex",
|
||||
gap: "8px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<input
|
||||
type={setting.isCredential ? "password" : "text"}
|
||||
value={editingSettings[setting.key]}
|
||||
onChange={(e) => updateEditingValue(setting.key, e.target.value)}
|
||||
onChange={(e) =>
|
||||
updateEditingValue(setting.key, e.target.value)
|
||||
}
|
||||
placeholder={setting.defaultValue || "値を入力..."}
|
||||
style={{
|
||||
flex: 1,
|
||||
padding: "6px 10px",
|
||||
border: "1px solid #ddd",
|
||||
borderRadius: "4px",
|
||||
fontSize: "14px"
|
||||
fontSize: "14px",
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
className="btn btn-success"
|
||||
onClick={() => updateSetting(setting.key, editingSettings[setting.key])}
|
||||
onClick={() =>
|
||||
updateSetting(
|
||||
setting.key,
|
||||
editingSettings[setting.key],
|
||||
)
|
||||
}
|
||||
style={{ fontSize: "12px", padding: "6px 12px" }}
|
||||
>
|
||||
保存
|
||||
@ -1328,20 +1432,36 @@ function App() {
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<div style={{ marginTop: "8px", display: "flex", alignItems: "center", gap: "12px" }}>
|
||||
<div style={{
|
||||
flex: 1,
|
||||
padding: "6px 10px",
|
||||
background: "#f8f9fa",
|
||||
border: "1px solid #e9ecef",
|
||||
borderRadius: "4px",
|
||||
fontSize: "14px",
|
||||
minHeight: "32px",
|
||||
<div
|
||||
style={{
|
||||
marginTop: "8px",
|
||||
display: "flex",
|
||||
alignItems: "center"
|
||||
}}>
|
||||
alignItems: "center",
|
||||
gap: "12px",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
padding: "6px 10px",
|
||||
background: "#f8f9fa",
|
||||
border: "1px solid #e9ecef",
|
||||
borderRadius: "4px",
|
||||
fontSize: "14px",
|
||||
minHeight: "32px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
{setting.value === null || setting.value === "" ? (
|
||||
<span style={{ color: "#dc3545", fontStyle: "italic" }}>未設定</span>
|
||||
<span
|
||||
style={{
|
||||
color: "#dc3545",
|
||||
fontStyle: "italic",
|
||||
}}
|
||||
>
|
||||
未設定
|
||||
</span>
|
||||
) : setting.isCredential ? (
|
||||
<span style={{ color: "#666" }}>••••••••</span>
|
||||
) : (
|
||||
@ -1350,7 +1470,9 @@ function App() {
|
||||
</div>
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
onClick={() => startEditingSetting(setting.key, setting.value)}
|
||||
onClick={() =>
|
||||
startEditingSetting(setting.key, setting.value)
|
||||
}
|
||||
style={{ fontSize: "12px", padding: "6px 12px" }}
|
||||
>
|
||||
編集
|
||||
@ -1379,10 +1501,18 @@ function App() {
|
||||
paddingLeft: "20px",
|
||||
}}
|
||||
>
|
||||
<li><strong>必須設定:</strong> アプリケーションの動作に必要な設定です</li>
|
||||
<li><strong>認証情報:</strong> セキュリティ上重要な情報で、表示時にマスクされます</li>
|
||||
<li>
|
||||
<strong>必須設定:</strong>{" "}
|
||||
アプリケーションの動作に必要な設定です
|
||||
</li>
|
||||
<li>
|
||||
<strong>認証情報:</strong>{" "}
|
||||
セキュリティ上重要な情報で、表示時にマスクされます
|
||||
</li>
|
||||
<li>設定の変更は即座にアプリケーションに反映されます</li>
|
||||
<li>デフォルト値が設定されている項目は、空にするとデフォルト値が使用されます</li>
|
||||
<li>
|
||||
デフォルト値が設定されている項目は、空にするとデフォルト値が使用されます
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</>
|
||||
@ -1396,17 +1526,26 @@ function App() {
|
||||
</p>
|
||||
|
||||
<div style={{ marginBottom: "20px" }}>
|
||||
<div className="stats-grid" style={{ gridTemplateColumns: "repeat(3, 1fr)" }}>
|
||||
<div
|
||||
className="stats-grid"
|
||||
style={{ gridTemplateColumns: "repeat(3, 1fr)" }}
|
||||
>
|
||||
<div className="stat-card">
|
||||
<div className="value">{categories.allCategories.length}</div>
|
||||
<div className="value">
|
||||
{categories.allCategories.length}
|
||||
</div>
|
||||
<div className="label">総カテゴリ数</div>
|
||||
</div>
|
||||
<div className="stat-card">
|
||||
<div className="value">{categories.feedCategories.length}</div>
|
||||
<div className="value">
|
||||
{categories.feedCategories.length}
|
||||
</div>
|
||||
<div className="label">フィードカテゴリ</div>
|
||||
</div>
|
||||
<div className="stat-card">
|
||||
<div className="value">{categories.episodeCategories.length}</div>
|
||||
<div className="value">
|
||||
{categories.episodeCategories.length}
|
||||
</div>
|
||||
<div className="label">エピソードカテゴリ</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1425,16 +1564,27 @@ function App() {
|
||||
) : (
|
||||
<div style={{ marginTop: "24px" }}>
|
||||
<h4>カテゴリ一覧 ({categories.allCategories.length}件)</h4>
|
||||
<div style={{ marginBottom: "16px", fontSize: "14px", color: "#666" }}>
|
||||
<div
|
||||
style={{
|
||||
marginBottom: "16px",
|
||||
fontSize: "14px",
|
||||
color: "#666",
|
||||
}}
|
||||
>
|
||||
削除対象を選択してから削除ボタンをクリックしてください。
|
||||
</div>
|
||||
|
||||
|
||||
<div className="category-list">
|
||||
{categories.allCategories.map((category) => {
|
||||
const counts = categoryCounts[category] || { feedCount: 0, episodeCount: 0 };
|
||||
const isInFeeds = categories.feedCategories.includes(category);
|
||||
const isInEpisodes = categories.episodeCategories.includes(category);
|
||||
|
||||
const counts = categoryCounts[category] || {
|
||||
feedCount: 0,
|
||||
episodeCount: 0,
|
||||
};
|
||||
const isInFeeds =
|
||||
categories.feedCategories.includes(category);
|
||||
const isInEpisodes =
|
||||
categories.episodeCategories.includes(category);
|
||||
|
||||
return (
|
||||
<div
|
||||
key={category}
|
||||
@ -1442,42 +1592,70 @@ function App() {
|
||||
style={{ marginBottom: "16px" }}
|
||||
>
|
||||
<div className="feed-info">
|
||||
<h4 style={{ margin: "0 0 8px 0", fontSize: "16px" }}>
|
||||
<h4
|
||||
style={{ margin: "0 0 8px 0", fontSize: "16px" }}
|
||||
>
|
||||
{category}
|
||||
</h4>
|
||||
<div style={{ fontSize: "14px", color: "#666", marginBottom: "8px" }}>
|
||||
<div
|
||||
style={{
|
||||
fontSize: "14px",
|
||||
color: "#666",
|
||||
marginBottom: "8px",
|
||||
}}
|
||||
>
|
||||
<span>フィード: {counts.feedCount}件</span>
|
||||
<span style={{ margin: "0 12px" }}>|</span>
|
||||
<span>エピソード: {counts.episodeCount}件</span>
|
||||
<span style={{ margin: "0 12px" }}>|</span>
|
||||
<span>合計: {counts.feedCount + counts.episodeCount}件</span>
|
||||
<span>
|
||||
合計: {counts.feedCount + counts.episodeCount}件
|
||||
</span>
|
||||
</div>
|
||||
<div style={{ fontSize: "12px", color: "#999" }}>
|
||||
<span style={{
|
||||
padding: "2px 6px",
|
||||
background: isInFeeds ? "#e3f2fd" : "#f5f5f5",
|
||||
color: isInFeeds ? "#1976d2" : "#999",
|
||||
borderRadius: "4px",
|
||||
marginRight: "8px"
|
||||
}}>
|
||||
<span
|
||||
style={{
|
||||
padding: "2px 6px",
|
||||
background: isInFeeds ? "#e3f2fd" : "#f5f5f5",
|
||||
color: isInFeeds ? "#1976d2" : "#999",
|
||||
borderRadius: "4px",
|
||||
marginRight: "8px",
|
||||
}}
|
||||
>
|
||||
フィード: {isInFeeds ? "使用中" : "未使用"}
|
||||
</span>
|
||||
<span style={{
|
||||
padding: "2px 6px",
|
||||
background: isInEpisodes ? "#e8f5e8" : "#f5f5f5",
|
||||
color: isInEpisodes ? "#388e3c" : "#999",
|
||||
borderRadius: "4px"
|
||||
}}>
|
||||
<span
|
||||
style={{
|
||||
padding: "2px 6px",
|
||||
background: isInEpisodes
|
||||
? "#e8f5e8"
|
||||
: "#f5f5f5",
|
||||
color: isInEpisodes ? "#388e3c" : "#999",
|
||||
borderRadius: "4px",
|
||||
}}
|
||||
>
|
||||
エピソード: {isInEpisodes ? "使用中" : "未使用"}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="feed-actions" style={{ flexDirection: "column", gap: "8px", minWidth: "160px" }}>
|
||||
<div
|
||||
className="feed-actions"
|
||||
style={{
|
||||
flexDirection: "column",
|
||||
gap: "8px",
|
||||
minWidth: "160px",
|
||||
}}
|
||||
>
|
||||
{isInFeeds && (
|
||||
<button
|
||||
className="btn btn-warning"
|
||||
onClick={() => deleteCategory(category, "feeds")}
|
||||
style={{ fontSize: "12px", padding: "6px 12px" }}
|
||||
onClick={() =>
|
||||
deleteCategory(category, "feeds")
|
||||
}
|
||||
style={{
|
||||
fontSize: "12px",
|
||||
padding: "6px 12px",
|
||||
}}
|
||||
>
|
||||
フィードから削除
|
||||
</button>
|
||||
@ -1485,8 +1663,13 @@ function App() {
|
||||
{isInEpisodes && (
|
||||
<button
|
||||
className="btn btn-warning"
|
||||
onClick={() => deleteCategory(category, "episodes")}
|
||||
style={{ fontSize: "12px", padding: "6px 12px" }}
|
||||
onClick={() =>
|
||||
deleteCategory(category, "episodes")
|
||||
}
|
||||
style={{
|
||||
fontSize: "12px",
|
||||
padding: "6px 12px",
|
||||
}}
|
||||
>
|
||||
エピソードから削除
|
||||
</button>
|
||||
@ -1495,7 +1678,10 @@ function App() {
|
||||
<button
|
||||
className="btn btn-danger"
|
||||
onClick={() => deleteCategory(category, "both")}
|
||||
style={{ fontSize: "12px", padding: "6px 12px" }}
|
||||
style={{
|
||||
fontSize: "12px",
|
||||
padding: "6px 12px",
|
||||
}}
|
||||
>
|
||||
すべてから削除
|
||||
</button>
|
||||
@ -1525,10 +1711,21 @@ function App() {
|
||||
paddingLeft: "20px",
|
||||
}}
|
||||
>
|
||||
<li><strong>フィードから削除:</strong> フィードのカテゴリのみを削除します</li>
|
||||
<li><strong>エピソードから削除:</strong> エピソードのカテゴリのみを削除します</li>
|
||||
<li><strong>すべてから削除:</strong> フィードとエピソード両方からカテゴリを削除します</li>
|
||||
<li>削除されたカテゴリは NULL に設定され、分類が解除されます</li>
|
||||
<li>
|
||||
<strong>フィードから削除:</strong>{" "}
|
||||
フィードのカテゴリのみを削除します
|
||||
</li>
|
||||
<li>
|
||||
<strong>エピソードから削除:</strong>{" "}
|
||||
エピソードのカテゴリのみを削除します
|
||||
</li>
|
||||
<li>
|
||||
<strong>すべてから削除:</strong>{" "}
|
||||
フィードとエピソード両方からカテゴリを削除します
|
||||
</li>
|
||||
<li>
|
||||
削除されたカテゴリは NULL に設定され、分類が解除されます
|
||||
</li>
|
||||
<li>この操作は元に戻すことができません</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user