100 lines
26 KiB
JavaScript
100 lines
26 KiB
JavaScript
import { c as createComponent, m as maybeRenderHead, a as addAttribute, r as renderTemplate, b as createAstro, d as renderComponent } from '../chunks/astro/server_DrnzQWw3.mjs';
|
||
import 'kleur/colors';
|
||
import { $ as $$BaseLayout } from '../chunks/BaseLayout_Bc2tHXHa.mjs';
|
||
import 'clsx';
|
||
import { i as isAdminAuthenticated } from '../chunks/adminAuth_CY4OwU1a.mjs';
|
||
import { r as readCms } from '../chunks/cms_CRTVymfB.mjs';
|
||
export { renderers } from '../renderers.mjs';
|
||
|
||
const $$Astro$1 = createAstro();
|
||
const $$AdminPager = createComponent(($$result, $$props, $$slots) => {
|
||
const Astro2 = $$result.createAstro($$Astro$1, $$props, $$slots);
|
||
Astro2.self = $$AdminPager;
|
||
const { currentPage, totalPages, tab, pageParam } = Astro2.props;
|
||
const href = (page) => `/admin/?tab=${tab}&${pageParam}=${page}`;
|
||
const pages = Array.from({ length: totalPages }, (_, index) => index + 1);
|
||
const previousPage = Math.max(1, currentPage - 1);
|
||
const nextPage = Math.min(totalPages, currentPage + 1);
|
||
return renderTemplate`${totalPages > 1 && renderTemplate`${maybeRenderHead()}<nav class="flex flex-wrap items-center justify-center gap-1.5 mt-6" aria-label="صفحهبندی"><a${addAttribute(href(previousPage), "href")}${addAttribute(currentPage === 1 ? "true" : void 0, "aria-disabled")}${addAttribute([
|
||
"px-3 h-8 rounded-lg border border-gray-200 bg-white flex items-center text-xs font-bold",
|
||
currentPage === 1 ? "opacity-40 pointer-events-none" : "hover:bg-brand hover:text-white hover:border-brand"
|
||
], "class:list")}>
|
||
قبلی
|
||
</a>${pages.map((page) => renderTemplate`<a${addAttribute(href(page), "href")}${addAttribute(page === currentPage ? "page" : void 0, "aria-current")}${addAttribute([
|
||
"w-8 h-8 rounded-lg border flex items-center justify-center text-xs font-bold transition-colors",
|
||
page === currentPage ? "bg-brand text-white border-brand" : "bg-white border-gray-200 hover:bg-gray-50"
|
||
], "class:list")}>${page}</a>`)}<a${addAttribute(href(nextPage), "href")}${addAttribute(currentPage === totalPages ? "true" : void 0, "aria-disabled")}${addAttribute([
|
||
"px-3 h-8 rounded-lg border border-gray-200 bg-white flex items-center text-xs font-bold",
|
||
currentPage === totalPages ? "opacity-40 pointer-events-none" : "hover:bg-brand hover:text-white hover:border-brand"
|
||
], "class:list")}>
|
||
بعدی
|
||
</a></nav>`}`;
|
||
}, "/Users/drfelfel/ruseemrooz/src/components/admin/AdminPager.astro", void 0);
|
||
|
||
const $$Astro = createAstro();
|
||
const $$Index = createComponent(async ($$result, $$props, $$slots) => {
|
||
const Astro2 = $$result.createAstro($$Astro, $$props, $$slots);
|
||
Astro2.self = $$Index;
|
||
if (!isAdminAuthenticated(Astro2)) {
|
||
return Astro2.redirect("/admin/login/");
|
||
}
|
||
const PAGE_SIZE = 8;
|
||
const cms = await readCms();
|
||
const approvedPosts = cms.posts.filter((post) => post.status === "approved");
|
||
const pendingPosts = cms.posts.filter((post) => post.status === "pending");
|
||
const tassMemoryCount = cms.settings.agents?.tass?.processedLinks?.length ?? 0;
|
||
const saved = Astro2.url.searchParams.has("saved");
|
||
const deleteError = Astro2.url.searchParams.has("deleteError");
|
||
const editSlug = Astro2.url.searchParams.get("edit");
|
||
const editingPost = cms.posts.find((post) => post.slug === editSlug);
|
||
const postForForm = editingPost ?? {
|
||
slug: "",
|
||
title: "",
|
||
category: cms.categories[0] ?? "",
|
||
time: "\u0647\u0645\u200C\u0627\u06A9\u0646\u0648\u0646",
|
||
readTime: "\u06F3 \u062F\u0642\u06CC\u0642\u0647",
|
||
excerpt: "",
|
||
status: "pending",
|
||
body: [],
|
||
image: "",
|
||
thumbnail: "",
|
||
urgent: false,
|
||
sidebar: false
|
||
};
|
||
const selectedImage = postForForm.image || "";
|
||
const selectedThumbnail = postForForm.thumbnail || selectedImage;
|
||
const activeTab = Astro2.url.searchParams.get("tab") === "approved" ? "approved" : "pending";
|
||
const totalPagesFor = (items) => Math.max(1, Math.ceil(items.length / PAGE_SIZE));
|
||
const clampPage = (param, total) => {
|
||
const parsed = Number(Astro2.url.searchParams.get(param) ?? "1");
|
||
return Math.min(Math.max(1, Number.isFinite(parsed) ? parsed : 1), total);
|
||
};
|
||
const pendingTotalPages = totalPagesFor(pendingPosts);
|
||
const approvedTotalPages = totalPagesFor(approvedPosts);
|
||
const pendingPage = clampPage("pendingPage", pendingTotalPages);
|
||
const approvedPage = clampPage("approvedPage", approvedTotalPages);
|
||
const pendingSlice = pendingPosts.slice((pendingPage - 1) * PAGE_SIZE, pendingPage * PAGE_SIZE);
|
||
const approvedSlice = approvedPosts.slice((approvedPage - 1) * PAGE_SIZE, approvedPage * PAGE_SIZE);
|
||
const tabClass = (id) => [
|
||
"px-4 h-9 rounded-lg border text-xs font-bold transition-colors",
|
||
id === activeTab ? "bg-brand text-white border-brand" : "bg-white text-gray-700 border-gray-200 hover:bg-gray-50"
|
||
].join(" ");
|
||
return renderTemplate`${renderComponent($$result, "BaseLayout", $$BaseLayout, { "title": "\u067E\u0646\u0644 \u0627\u062F\u0645\u06CC\u0646 | \u0631\u0648\u0633 \u0627\u0645\u0631\u0648\u0632" }, { "default": async ($$result2) => renderTemplate` ${maybeRenderHead()}<main class="max-w-7xl mx-auto px-4 lg:px-8 py-8"> <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 mb-6"> <div> <span class="text-brand text-sm font-bold">مدیریت محتوا</span> <h1 class="text-2xl font-black mt-1">پنل سبک روس امروز</h1> <p class="text-gray-500 text-sm mt-2">تایید نوشتههای AI، مدیریت دستهها، خبر فوری، آگهی و چیدمان صفحه اول</p> </div> <form action="/api/admin/logout" method="post"> <button class="bg-gray-900 text-white text-sm px-4 py-2 rounded-xl">خروج</button> </form> </div> ${saved && renderTemplate`<p class="bg-green-50 text-green-700 text-sm rounded-xl px-4 py-3 mb-5">تغییرات ذخیره شد.</p>`} ${deleteError && renderTemplate`<p class="bg-red-50 text-brand text-sm rounded-xl px-4 py-3 mb-5">برای حذف باید دقیقاً confirm را وارد کنید.</p>`} <div class="grid grid-cols-1 lg:grid-cols-3 gap-6"> <section class="lg:col-span-2 space-y-6"> <div class="bg-white rounded-2xl shadow-sm p-5"> <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3"> <div> <h2 class="font-bold text-lg">مدیریت حذف اخبار</h2> <p class="text-sm text-gray-500 mt-1">حذف همه اخبار نیاز به تایپ \`confirm\` دارد و قابل بازگشت نیست.</p> </div> <form action="/api/admin/save" method="post" data-confirm-form data-confirm-message="برای حذف همه اخبار عبارت confirm را تایپ کنید."> <input type="hidden" name="action" value="delete-all-posts"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="confirm" value="" data-confirm-input> <button class="bg-red-600 text-white text-sm px-4 py-2 rounded-xl">حذف همه اخبار</button> </form> </div> </div> <div class="bg-white rounded-2xl shadow-sm p-5"> <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 mb-4"> <h2 class="font-bold text-lg">مدیریت نوشتهها</h2> <nav${addAttribute(activeTab, "data-active-tab")} class="flex gap-2" aria-label="تب نوشتهها"> <a href="/admin/?tab=pending" data-tab="pending"${addAttribute(tabClass("pending"), "class")}>تایید نشده (${pendingPosts.length})</a> <a href="/admin/?tab=approved" data-tab="approved"${addAttribute(tabClass("approved"), "class")}>تایید شده (${approvedPosts.length})</a> </nav> </div> <div data-panel="pending"${addAttribute(["space-y-3", { hidden: activeTab !== "pending" }], "class:list")}> ${pendingSlice.length === 0 && renderTemplate`<p class="text-sm text-gray-400">نوشته تایید نشدهای وجود ندارد.</p>`} ${pendingSlice.map((post) => renderTemplate`<article class="border border-gray-100 rounded-xl p-4"> <div class="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-3"> <div> <span class="text-xs text-brand font-bold">${post.category}</span> <h3 class="font-bold mt-1">${post.title}</h3> <p class="text-sm text-gray-500 mt-1 line-clamp-2">${post.excerpt}</p> </div> <div class="flex gap-2 flex-shrink-0"> <a${addAttribute(`/admin/?tab=${activeTab}&edit=${post.slug}`, "href")} class="bg-gray-100 text-gray-700 text-xs px-3 py-2 rounded-lg">ویرایش</a> <form action="/api/admin/save" method="post" data-confirm-form${addAttribute(`\u0628\u0631\u0627\u06CC \u062D\u0630\u0641 \xAB${post.title}\xBB \u0639\u0628\u0627\u0631\u062A confirm \u0631\u0627 \u062A\u0627\u06CC\u067E \u06A9\u0646\u06CC\u062F.`, "data-confirm-message")}> <input type="hidden" name="action" value="delete-post"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="slug"${addAttribute(post.slug, "value")}> <input type="hidden" name="confirm" value="" data-confirm-input> <button class="bg-red-50 text-brand text-xs px-3 py-2 rounded-lg">حذف</button> </form> <form action="/api/admin/save" method="post"> <input type="hidden" name="action" value="post-status"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="slug"${addAttribute(post.slug, "value")}> <input type="hidden" name="status" value="approved"> <button class="bg-green-600 text-white text-xs px-3 py-2 rounded-lg">تایید</button> </form> </div> </div> </article>`)} ${renderComponent($$result2, "AdminPager", $$AdminPager, { "currentPage": pendingPage, "totalPages": pendingTotalPages, "tab": "pending", "pageParam": "pendingPage" })} </div> <div data-panel="approved"${addAttribute(["space-y-3", { hidden: activeTab !== "approved" }], "class:list")}> ${approvedSlice.length === 0 && renderTemplate`<p class="text-sm text-gray-400">نوشته تایید شدهای وجود ندارد.</p>`} ${approvedSlice.map((post) => renderTemplate`<article class="border border-gray-100 rounded-xl p-4"> <div class="flex flex-col gap-3"> <div> <div class="flex flex-wrap items-center gap-2"> <span class="text-xs text-brand font-bold">${post.category}</span> ${post.urgent && renderTemplate`<span class="bg-red-50 text-brand text-xs px-2 py-1 rounded-full">فوری</span>`} ${post.sidebar && renderTemplate`<span class="bg-blue-50 text-blue-700 text-xs px-2 py-1 rounded-full">پنل کناری</span>`} ${(cms.settings.breakingNews.postSlugs ?? []).includes(post.slug) && renderTemplate`<span class="bg-yellow-50 text-yellow-700 text-xs px-2 py-1 rounded-full">نوار بالایی</span>`} ${cms.settings.homeLayout.featuredSlug === post.slug && renderTemplate`<span class="bg-green-50 text-green-700 text-xs px-2 py-1 rounded-full">خبر اصلی</span>`} </div> <h3 class="font-bold mt-2">${post.title}</h3> </div> <div class="flex flex-wrap gap-2"> <a${addAttribute(`/admin/?tab=${activeTab}&edit=${post.slug}`, "href")} class="bg-gray-100 text-gray-700 text-xs px-3 py-2 rounded-lg">ویرایش</a> <form action="/api/admin/save" method="post"> <input type="hidden" name="action" value="post-status"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="slug"${addAttribute(post.slug, "value")}> <input type="hidden" name="status" value="pending"> <button class="bg-red-50 text-brand text-xs px-3 py-2 rounded-lg">برداشتن تایید</button> </form> <form action="/api/admin/save" method="post" data-confirm-form${addAttribute(`\u0628\u0631\u0627\u06CC \u062D\u0630\u0641 \xAB${post.title}\xBB \u0639\u0628\u0627\u0631\u062A confirm \u0631\u0627 \u062A\u0627\u06CC\u067E \u06A9\u0646\u06CC\u062F.`, "data-confirm-message")}> <input type="hidden" name="action" value="delete-post"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="slug"${addAttribute(post.slug, "value")}> <input type="hidden" name="confirm" value="" data-confirm-input> <button class="bg-red-50 text-brand text-xs px-3 py-2 rounded-lg">حذف</button> </form> </div> <div class="flex flex-wrap gap-2"> <form action="/api/admin/save" method="post"> <input type="hidden" name="action" value="toggle-post-flag"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="slug"${addAttribute(post.slug, "value")}> <input type="hidden" name="flag" value="urgent"> <button${addAttribute(["text-xs px-3 py-2 rounded-lg", post.urgent ? "bg-brand text-white" : "bg-red-50 text-brand"], "class:list")}>${post.urgent ? "\u0628\u0631\u062F\u0627\u0634\u062A\u0646 \u0641\u0648\u0631\u06CC" : "\u0641\u0648\u0631\u06CC \u06A9\u0646"}</button> </form> <form action="/api/admin/save" method="post"> <input type="hidden" name="action" value="toggle-post-flag"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="slug"${addAttribute(post.slug, "value")}> <input type="hidden" name="flag" value="sidebar"> <button${addAttribute(["text-xs px-3 py-2 rounded-lg", post.sidebar ? "bg-blue-600 text-white" : "bg-blue-50 text-blue-700"], "class:list")}>${post.sidebar ? "\u062D\u0630\u0641 \u0627\u0632 \u067E\u0646\u0644 \u06A9\u0646\u0627\u0631\u06CC" : "\u0627\u0641\u0632\u0648\u062F\u0646 \u0628\u0647 \u067E\u0646\u0644 \u06A9\u0646\u0627\u0631\u06CC"}</button> </form> <form action="/api/admin/save" method="post"> <input type="hidden" name="action" value="set-breaking-post"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="slug"${addAttribute(post.slug, "value")}> <button class="bg-yellow-50 text-yellow-700 text-xs px-3 py-2 rounded-lg">متن فوری بالا</button> </form> <form action="/api/admin/save" method="post"> <input type="hidden" name="action" value="set-home-featured"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="slug"${addAttribute(post.slug, "value")}> <button class="bg-green-50 text-green-700 text-xs px-3 py-2 rounded-lg">خبر اصلی صفحه اول</button> </form> </div> </div> </article>`)} ${renderComponent($$result2, "AdminPager", $$AdminPager, { "currentPage": approvedPage, "totalPages": approvedTotalPages, "tab": "approved", "pageParam": "approvedPage" })} </div> </div> </section> <aside class="space-y-6"> <div class="bg-white rounded-2xl shadow-sm p-5 space-y-3"> <h2 class="font-bold text-lg">Agent خبرخوان TASS</h2> <p class="text-xs text-gray-500 leading-6">RSS را میخواند، متن و تصویر خبر را استخراج میکند، با OpenAI-compatible API ترجمه میکند و پست را در وضعیت تایید نشده میسازد.</p> <p class="text-xs text-gray-400">حافظه فعلی: ${tassMemoryCount} لینک پردازششده</p> <button id="run-tass-agent" class="w-full bg-brand text-white rounded-xl py-3 font-bold">اجرای agent و ساخت پست</button> <div class="grid grid-cols-2 gap-2"> <form action="/api/admin/save" method="post"> <input type="hidden" name="action" value="clear-tass-memory"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <button class="w-full bg-gray-100 text-gray-700 rounded-xl py-2 text-sm font-bold">خالی کردن حافظه</button> </form> <form action="/api/admin/save" method="post"> <input type="hidden" name="action" value="fill-tass-memory"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <button class="w-full bg-gray-100 text-gray-700 rounded-xl py-2 text-sm font-bold">پر کردن از RSS فعلی</button> </form> </div> <pre id="tass-agent-result" class="hidden bg-gray-900 text-white text-xs rounded-xl p-3 overflow-auto whitespace-pre-wrap"></pre> </div> <form action="/api/admin/save" method="post" class="bg-white rounded-2xl shadow-sm p-5 space-y-3"> <input type="hidden" name="action" value="save-post"> <input type="hidden" name="originalSlug"${addAttribute(editingPost?.slug ?? "", "value")}> <h2 class="font-bold text-lg">${editingPost ? "\u0648\u06CC\u0631\u0627\u06CC\u0634 \u0646\u0648\u0634\u062A\u0647" : "\u0627\u0641\u0632\u0648\u062F\u0646 \u0646\u0648\u0634\u062A\u0647"}</h2> <label class="block text-sm font-bold">عنوان<input name="title"${addAttribute(postForForm.title, "value")} required class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <label class="block text-sm font-bold">اسلاگ<input name="slug"${addAttribute(postForForm.slug, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <label class="block text-sm font-bold">دستهبندی<select name="category" class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand">${cms.categories.map((category) => renderTemplate`<option${addAttribute(category, "value")}${addAttribute(category === postForForm.category, "selected")}>${category}</option>`)}</select></label> <div class="grid grid-cols-2 gap-2"> <label class="block text-sm font-bold">زمان<input name="time"${addAttribute(postForForm.time, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <label class="block text-sm font-bold">مدت مطالعه<input name="readTime"${addAttribute(postForForm.readTime, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> </div> <label class="block text-sm font-bold">وضعیت<select name="status" class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"><option value="pending"${addAttribute(postForForm.status === "pending", "selected")}>تایید نشده</option><option value="approved"${addAttribute(postForForm.status === "approved", "selected")}>تایید شده</option></select></label> <div class="grid grid-cols-2 gap-2"> <label class="flex items-center gap-2 text-sm font-bold bg-gray-50 rounded-xl px-3 py-2"><input type="checkbox" name="urgent"${addAttribute(postForForm.urgent, "checked")}> فوری</label> <label class="flex items-center gap-2 text-sm font-bold bg-gray-50 rounded-xl px-3 py-2"><input type="checkbox" name="sidebar"${addAttribute(postForForm.sidebar, "checked")}> پنل کناری</label> </div> <div class="border border-gray-100 rounded-xl p-3 space-y-3"> <div class="flex items-center justify-between gap-2"> <span class="text-sm font-bold">تصویر شاخص</span> <button type="button"${addAttribute(selectedImage, "data-insert-image")}${addAttribute(!selectedImage, "disabled")} class="bg-gray-100 text-gray-700 text-xs px-3 py-2 rounded-lg disabled:opacity-40">درج داخل متن</button> </div> <div id="new-image-preview" class="w-full h-36 rounded-xl bg-gray-100 flex items-center justify-center overflow-hidden"> ${selectedThumbnail ? renderTemplate`<img${addAttribute(selectedThumbnail, "src")} alt="" class="w-full h-full object-cover">` : renderTemplate`<span class="text-gray-400 text-sm">تصویری انتخاب نشده</span>`} </div> <p id="upload-status" class="text-xs rounded-lg px-2.5 py-1 text-gray-400">تصویری انتخاب نشده</p> <div class="flex flex-col sm:flex-row gap-2"> <input id="new-image-file" type="file" accept="image/*" class="w-full bg-gray-100 rounded-xl px-3 py-2 text-sm"> <button id="new-upload-btn" type="button" class="bg-gray-900 text-white rounded-xl px-4 py-2 text-sm font-bold sm:flex-shrink-0">آپلود و ساخت thumbnail</button> </div> <input id="new-image-field" name="image"${addAttribute(selectedImage, "value")} placeholder="/uploads/image.webp" class="w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand text-sm"> <input id="new-thumb-field" name="thumbnail"${addAttribute(selectedThumbnail, "value")} placeholder="/uploads/thumbs/image-thumb.webp" class="w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand text-sm"> </div> <label class="block text-sm font-bold">خلاصه<textarea name="excerpt" rows="3" class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand">${postForForm.excerpt}</textarea></label> <label class="block text-sm font-bold">
|
||
متن
|
||
<div class="flex flex-wrap gap-2 mt-2 mb-2"> <button type="button" data-editor-command="heading" class="bg-gray-100 text-gray-700 text-xs px-3 py-2 rounded-lg">تیتر</button> <button type="button" data-editor-command="quote" class="bg-gray-100 text-gray-700 text-xs px-3 py-2 rounded-lg">نقلقول</button> <button type="button" data-editor-command="separator" class="bg-gray-100 text-gray-700 text-xs px-3 py-2 rounded-lg">جداکننده</button> <button type="button"${addAttribute(selectedImage, "data-insert-image")}${addAttribute(!selectedImage, "disabled")} class="bg-red-50 text-brand text-xs px-3 py-2 rounded-lg disabled:opacity-40">درج تصویر آپلودشده</button> </div> <textarea id="post-body-editor" name="body" rows="12" class="w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand leading-7 font-mono text-sm">${postForForm.body.join("\n\n")}</textarea> <span class="block text-xs text-gray-400 mt-2">برای تصویر داخل متن از \`[image:/uploads/example.webp|توضیح تصویر]\` استفاده میشود.</span> </label> <button class="w-full bg-brand text-white rounded-xl py-3 font-bold">ذخیره نوشته</button> </form> <form action="/api/admin/save" method="post" class="bg-white rounded-2xl shadow-sm p-5 space-y-3"> <input type="hidden" name="action" value="categories"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <h2 class="font-bold text-lg">دستهبندیها</h2> <textarea name="categories" rows="5" class="w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand">${cms.categories.join("\n")}</textarea> <button class="w-full bg-gray-900 text-white rounded-xl py-3 font-bold">ذخیره دستهها</button> </form> <form action="/api/admin/save" method="post" class="bg-white rounded-2xl shadow-sm p-5 space-y-3"> <input type="hidden" name="action" value="settings"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <h2 class="font-bold text-lg">صفحه اول و آگهی</h2> <label class="block text-sm font-bold">برچسب فوری<input name="breakingLabel"${addAttribute(cms.settings.breakingNews.label, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <label class="block text-sm font-bold">لینک فوری<input name="breakingHref"${addAttribute(cms.settings.breakingNews.href, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <label class="block text-sm font-bold">متنهای فوری<textarea name="breakingItems" rows="4" class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand">${cms.settings.breakingNews.items.join("\n")}</textarea></label> <label class="block text-sm font-bold">اسلاگ پستهای نوار فوری<textarea name="breakingPostSlugs" rows="3" class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand">${(cms.settings.breakingNews.postSlugs ?? []).join("\n")}</textarea></label> <label class="block text-sm font-bold">موضوعات داغ<textarea name="hotTopics" rows="4" class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand">${cms.settings.hotTopics.join("\n")}</textarea></label> <label class="block text-sm font-bold">خبر اصلی<select name="featuredSlug" class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand">${approvedPosts.map((post) => renderTemplate`<option${addAttribute(post.slug, "value")}${addAttribute(post.slug === cms.settings.homeLayout.featuredSlug, "selected")}>${post.title}</option>`)}</select></label> <label class="block text-sm font-bold">دو خبر کناری<textarea name="sideFeaturedSlugs" rows="3" class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand">${cms.settings.homeLayout.sideFeaturedSlugs.join("\n")}</textarea></label> <label class="block text-sm font-bold">تعداد آخرین اخبار<input name="latestCount" type="number" min="1"${addAttribute(cms.settings.homeLayout.latestCount, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <label class="flex items-center gap-2 text-sm font-bold"><input type="checkbox" name="showAd"${addAttribute(cms.settings.homeLayout.showAd, "checked")}> نمایش جایگاه آگهی</label> <label class="flex items-center gap-2 text-sm font-bold"><input type="checkbox" name="adEnabled"${addAttribute(cms.settings.ad.enabled, "checked")}> آگهی فعال</label> <label class="block text-sm font-bold">عنوان آگهی<input name="adLabel"${addAttribute(cms.settings.ad.label, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <label class="block text-sm font-bold">لینک آگهی<input name="adHref"${addAttribute(cms.settings.ad.href, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <label class="block text-sm font-bold">متن آگهی<input name="adText"${addAttribute(cms.settings.ad.text, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <button class="w-full bg-brand text-white rounded-xl py-3 font-bold">ذخیره تنظیمات</button> </form> <div class="bg-white rounded-2xl shadow-sm p-5 space-y-3"> <h2 class="font-bold text-lg">API انتشار برای n8n</h2> <p class="text-xs text-gray-500 leading-6">POST به \`/api/posts/publish\` با هدر \`Authorization: Bearer ADMIN_API_TOKEN\`.</p> <code class="block bg-gray-100 text-xs rounded-xl p-3 leading-6 overflow-auto">${JSON.stringify({ title: "\u0639\u0646\u0648\u0627\u0646", category: "\u0628\u06CC\u0646\u200C\u0627\u0644\u0645\u0644\u0644", body: ["\u067E\u0627\u0631\u0627\u06AF\u0631\u0627\u0641 \u0627\u0648\u0644"], imageUrl: "https://..." })}</code> </div> </aside> </div> </main> ` })} `;
|
||
}, "/Users/drfelfel/ruseemrooz/src/pages/admin/index.astro", void 0);
|
||
|
||
const $$file = "/Users/drfelfel/ruseemrooz/src/pages/admin/index.astro";
|
||
const $$url = "/admin";
|
||
|
||
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||
__proto__: null,
|
||
default: $$Index,
|
||
file: $$file,
|
||
url: $$url
|
||
}, Symbol.toStringTag, { value: 'Module' }));
|
||
|
||
const page = () => _page;
|
||
|
||
export { page };
|