feat(blog): add admin endpoint for blog details and cache invalidation
- Implemented `adminDetail()` method in `BlogController` to retrieve blog posts of any status for admin editing. - Introduced `BlogCacheInvalidator` service to handle cache invalidation after blog create/update/delete actions. - Updated existing methods in `BlogController` and `RepresentationBlogController` to call cache invalidation on blog modifications. - Enhanced `BlogFormPage` and `RepresentationBlogFormPage` to utilize the new admin endpoint for fetching blog data. - Added tests for `BlogCacheInvalidator` to ensure proper functionality and error handling. - Updated documentation to reflect new API endpoint and cache invalidation behavior.
This commit is contained in:
@@ -17,46 +17,46 @@ export default function BlogSeoFields({ control, register }: Props) {
|
||||
<h3 className="section-title">سئو و زمانبندی</h3>
|
||||
|
||||
<div>
|
||||
<label>عنوان متا (Meta Title)</label>
|
||||
<label className="cp-label">عنوان متا (Meta Title)</label>
|
||||
<input {...register('meta_title')} className="cp-input h-11" placeholder="عنوان برای موتور جستجو" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>توضیح متا (Meta Description)</label>
|
||||
<textarea {...register('meta_description')} rows={2} className="input resize-none"
|
||||
<label className="cp-label">توضیح متا (Meta Description)</label>
|
||||
<textarea {...register('meta_description')} rows={2} className="cp-textarea resize-none"
|
||||
placeholder="حداکثر ۱۵۵ کاراکتر" />
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label>کلیدواژهٔ اصلی</label>
|
||||
<label className="cp-label">کلیدواژهٔ اصلی</label>
|
||||
<input {...register('primary_keyword')} className="cp-input h-11" />
|
||||
</div>
|
||||
<div>
|
||||
<label>کلیدواژههای فرعی (با ویرگول)</label>
|
||||
<label className="cp-label">کلیدواژههای فرعی (با ویرگول)</label>
|
||||
<input {...register('secondary_keywords')} className="cp-input h-11" placeholder="کلمه۱، کلمه۲" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label>لینکهای داخلی (URL با ویرگول)</label>
|
||||
<label className="cp-label">لینکهای داخلی (URL با ویرگول)</label>
|
||||
<input {...register('internal_links')} dir="ltr" className="cp-input h-11" placeholder="/a, /b" />
|
||||
</div>
|
||||
<div>
|
||||
<label>لینکهای خارجی (URL با ویرگول)</label>
|
||||
<label className="cp-label">لینکهای خارجی (URL با ویرگول)</label>
|
||||
<input {...register('external_links')} dir="ltr" className="cp-input h-11" placeholder="https://..." />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label>زمان مطالعه (دقیقه)</label>
|
||||
<label className="cp-label">زمان مطالعه (دقیقه)</label>
|
||||
<input type="number" {...register('reading_time', { setValueAs: (v) => (v === '' || v == null ? null : Number(v)) })}
|
||||
className="cp-input h-11" min={1} />
|
||||
</div>
|
||||
<div>
|
||||
<label>زمانبندی انتشار</label>
|
||||
<label className="cp-label">زمانبندی انتشار</label>
|
||||
<Controller
|
||||
control={control}
|
||||
name="scheduled_at"
|
||||
@@ -79,7 +79,7 @@ export default function BlogSeoFields({ control, register }: Props) {
|
||||
{fields.map((f, i) => (
|
||||
<div key={f.id} className="card card-pad" style={{ padding: 12 }}>
|
||||
<input {...register(`faq.${i}.q` as const)} className="cp-input h-10 mb-2" placeholder="سوال" />
|
||||
<textarea {...register(`faq.${i}.a` as const)} rows={2} className="input resize-none" placeholder="پاسخ" />
|
||||
<textarea {...register(`faq.${i}.a` as const)} rows={2} className="cp-textarea resize-none" placeholder="پاسخ" />
|
||||
<button type="button" className="mini-btn danger mt-2" onClick={() => remove(i)}>حذف</button>
|
||||
</div>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user