diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d7ef452..d1ea471 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -27,4 +27,4 @@ auto-deploy: services: - docker:dind script: - - curl --user admin:$JENKINS_PWD http://38.47.185.86:8080/job/auto-deploy-berita-bumn/build?token=autodeploymedols + - curl --user admin:$JENKINS_PWD http:// /job/auto-deploy-berita-bumn/build?token=autodeploymedols diff --git a/components/details/details-content.tsx b/components/details/details-content.tsx index d9e7b33..fb62c20 100644 --- a/components/details/details-content.tsx +++ b/components/details/details-content.tsx @@ -5,6 +5,7 @@ import Link from "next/link"; import { getArticleById, getArticleBySlug, + getArticleFiles, getListArticle, } from "@/service/article"; import { close, error, loading } from "@/config/swal"; @@ -74,7 +75,7 @@ export default function DetailContent() { startDate: null, endDate: null, }); - const [detailfiles, setDetailFiles] = useState([]); + const [detailFiles, setDetailFiles] = useState([]); const [mainImage, setMainImage] = useState(0); const [thumbnail, setThumbnail] = useState("-"); const [diseId, setDiseId] = useState(0); @@ -300,16 +301,38 @@ export default function DetailContent() { initStateData(); }, [listCategory]); + useEffect(() => { + setSelectedIndex(0); + }, [detailFiles]); + async function initStateData() { loading(); - const res = await getArticleBySlug(slug); - const data = res.data?.data; + try { + // 1️⃣ Ambil artikel by slug + const res = await getArticleBySlug(slug); + const data = res?.data?.data; - setThumbnail(data?.thumbnailUrl); - setDiseId(data?.aiArticleId); - setDetailFiles(data?.files); - setArticleDetail(data); - close(); + if (!data?.id) return; + + setArticleDetail(data); + setThumbnail(data.thumbnailUrl); + setDiseId(data.aiArticleId); + + // 2️⃣ Ambil SEMUA article files + const filesRes = await getArticleFiles(); + const allFiles = filesRes?.data?.data ?? []; + + // 3️⃣ FILTER sesuai articleId + const filteredFiles = allFiles.filter( + (file: any) => file.articleId === data.id + ); + + setDetailFiles(filteredFiles); + } catch (error) { + console.error("Init state detail error:", error); + } finally { + close(); + } } if (!articleDetail?.files || articleDetail.files.length === 0) { @@ -320,6 +343,23 @@ export default function DetailContent() { ); } + function decodeHtmlString(raw: string = "") { + if (!raw) return ""; + + // 1️⃣ Hapus newline escape, backslash, dsb + let decoded = raw + .replace(/\\n/g, "\n") + .replace(/\\"/g, '"') // ubah \" jadi " + .replace(/\\'/g, "'") // ubah \' jadi ' + .replace(/\\\\/g, "\\") // ubah \\ jadi \ + .trim(); + + // 2️⃣ Decode entity HTML (misal ") + const el = document.createElement("textarea"); + el.innerHTML = decoded; + return el.value; + } + return ( <>
@@ -370,38 +410,43 @@ export default function DetailContent() {
{/* Gambar utama */} -
- {articleDetail.files[selectedIndex].fileAlt -
+ {detailFiles.length > 0 ? ( + <> + {detailFiles[selectedIndex]?.fileAlt - {/* Thumbnail */} -
- {articleDetail.files.map((file: any, index: number) => ( - - ))} -
+
+ {detailFiles.map((file, index) => ( + + ))} +
+ + ) : ( +
+

Gambar tidak tersedia

+
+ )} {/* Slug */}

@@ -475,10 +520,12 @@ export default function DetailContent() {

-
+
diff --git a/components/form/article/create-article-form.tsx b/components/form/article/create-article-form.tsx index d920ed7..2df8011 100644 --- a/components/form/article/create-article-form.tsx +++ b/components/form/article/create-article-form.tsx @@ -514,7 +514,7 @@ export default function CreateArticleForm() { id="title" type="text" placeholder="Masukkan judul artikel" - className="w-full border rounded-lg dark:border-gray-400" + className="h-16 px-4 text-2xl leading-tight" {...field} /> )} diff --git a/components/form/article/edit-article-form.tsx b/components/form/article/edit-article-form.tsx index b28e391..7e1c271 100644 --- a/components/form/article/edit-article-form.tsx +++ b/components/form/article/edit-article-form.tsx @@ -23,6 +23,7 @@ import { deleteArticleFiles, getArticleByCategory, getArticleById, + getArticleFiles, submitApproval, unPublishArticle, updateArticle, @@ -196,27 +197,49 @@ export default function EditArticleForm(props: { isDetail: boolean }) { async function initState() { loading(); - const res = await getArticleById(id); - const data = res.data?.data; - setDetailData(data); - setValue("title", data?.title); - setValue("customCreatorName", data?.customCreatorName); - setValue("slug", data?.slug); - setValue("source", data?.source); - const cleanDescription = data?.htmlDescription - ? data.htmlDescription - .replace(/\\"/g, '"') - .replace(/\\n/g, "\n", "\\") - .trim() - : ""; - setValue("description", cleanDescription); - setValue("tags", data?.tags ? data.tags.split(",") : []); - setThumbnail(data?.thumbnailUrl); - setDiseId(data?.aiArticleId); - setDetailFiles(data?.files); + try { + // 1️⃣ Ambil ARTICLE + const articleRes = await getArticleById(id); + const articleData = articleRes.data?.data; - setupInitCategory(data?.categories); - close(); + if (!articleData) return; + + // ===== ARTICLE DATA ===== + setDetailData(articleData); + setValue("title", articleData.title); + setValue("customCreatorName", articleData.customCreatorName); + setValue("slug", articleData.slug); + setValue("source", articleData.source); + + const cleanDescription = articleData.htmlDescription + ? articleData.htmlDescription + .replace(/\\"/g, '"') + .replace(/\\n/g, "\n") + .trim() + : ""; + + setValue("description", cleanDescription); + setValue("tags", articleData.tags ? articleData.tags.split(",") : []); + + setThumbnail(articleData.thumbnailUrl); + setDiseId(articleData.aiArticleId); + setupInitCategory(articleData.categories); + + // 2️⃣ Ambil SEMUA article files + const filesRes = await getArticleFiles(); + const allFiles = filesRes.data?.data ?? []; + + // 3️⃣ FILTER berdasarkan ARTICLE ID yang sedang dibuka + const filteredFiles = allFiles.filter( + (file: any) => file.articleId === articleData.id + ); + + setDetailFiles(filteredFiles); + } catch (error) { + console.error("Init state error:", error); + } finally { + close(); + } } const setupInitCategory = (data: any) => { @@ -667,9 +690,10 @@ export default function EditArticleForm(props: { isDetail: boolean }) { name="title" render={({ field: { onChange, value } }) => (
-
)} diff --git a/service/article.ts b/service/article.ts index 4f338cd..8cb3509 100644 --- a/service/article.ts +++ b/service/article.ts @@ -143,6 +143,13 @@ export async function uploadArticleThumbnail(id: string, data: any) { return await httpPostInterceptor(`/articles/thumbnail/${id}`, data, headers); } +export async function getArticleFiles() { + const headers = { + "content-type": "application/json", + }; + return await httpGet(`/article-files`, headers); +} + export async function deleteArticleFiles(id: number) { const headers = { "content-type": "multipart/form-data",