From 4a5c4b592fb0869f6eb00a011531e66818abd569 Mon Sep 17 00:00:00 2001 From: sabdayagra Date: Wed, 8 Jan 2025 02:36:40 +0700 Subject: [PATCH] feat: add rewrite content --- .../content-management/galery/page.tsx | 111 +- .../rewrite/create/[id]/page.tsx | 495 +- .../rewrite/detail/[id]/page.tsx | 2 - app/[locale]/auth/page.tsx | 39 +- package-lock.json | 13055 +--------------- service/detail/detail.ts | 6 + service/landing/landing.ts | 5 + vendor/ckeditor5/node_modules/.bin/tsc | 17 +- vendor/ckeditor5/node_modules/.bin/tsc.cmd | 17 - vendor/ckeditor5/node_modules/.bin/tsc.ps1 | 28 - vendor/ckeditor5/node_modules/.bin/tsserver | 17 +- .../ckeditor5/node_modules/.bin/tsserver.cmd | 17 - .../ckeditor5/node_modules/.bin/tsserver.ps1 | 28 - .../node_modules/typescript/LICENSE.txt | 110 +- .../node_modules/typescript/README.md | 98 +- .../typescript/ThirdPartyNoticeText.txt | 386 +- .../ckeditor5/node_modules/typescript/bin/tsc | 0 .../node_modules/typescript/bin/tsserver | 0 .../node_modules/typescript/lib/typesMap.json | 992 +- 19 files changed, 1431 insertions(+), 13992 deletions(-) create mode 100644 service/detail/detail.ts mode change 100644 => 120000 vendor/ckeditor5/node_modules/.bin/tsc delete mode 100644 vendor/ckeditor5/node_modules/.bin/tsc.cmd delete mode 100644 vendor/ckeditor5/node_modules/.bin/tsc.ps1 mode change 100644 => 120000 vendor/ckeditor5/node_modules/.bin/tsserver delete mode 100644 vendor/ckeditor5/node_modules/.bin/tsserver.cmd delete mode 100644 vendor/ckeditor5/node_modules/.bin/tsserver.ps1 mode change 100644 => 100755 vendor/ckeditor5/node_modules/typescript/bin/tsc mode change 100644 => 100755 vendor/ckeditor5/node_modules/typescript/bin/tsserver diff --git a/app/[locale]/(public)/content-management/galery/page.tsx b/app/[locale]/(public)/content-management/galery/page.tsx index 18e2295e..cfecc7fa 100644 --- a/app/[locale]/(public)/content-management/galery/page.tsx +++ b/app/[locale]/(public)/content-management/galery/page.tsx @@ -293,7 +293,7 @@ const Galery = (props: any) => {
{video?.mediaUpload?.title}
- + @@ -334,11 +334,7 @@ const Galery = (props: any) => { contentAudio?.length > 0 ? (
{contentAudio?.map((audio: any) => ( - +
{ />
-
+
{audio?.mediaUpload?.title}
-
+
@@ -365,7 +361,36 @@ const Galery = (props: any) => {
- + + + + + + + + + + + + + +

Content Rewrite

+ +
+ +
+ +
+
+
+
+
))}
) : ( @@ -377,12 +402,41 @@ const Galery = (props: any) => { contentImage?.length > 0 ? (
{contentImage?.map((image: any) => ( - +
{image?.mediaUpload?.title}
+ + + + + + + + + + + + + +

Content Rewrite

+ +
+ +
+ +
+
+
+
))} @@ -395,7 +449,7 @@ const Galery = (props: any) => { ) : contentDocument.length > 0 ? (
{contentDocument?.map((document: any) => ( - +
{
-
{document?.mediaUpload?.title}
+ + {document?.mediaUpload?.title} +
@@ -414,7 +470,36 @@ const Galery = (props: any) => { Download Dokumen
- + + + + + + + + + + + + + +

Content Rewrite

+ +
+ +
+ +
+
+
+
+
))}
) : ( diff --git a/app/[locale]/(public)/content-management/rewrite/create/[id]/page.tsx b/app/[locale]/(public)/content-management/rewrite/create/[id]/page.tsx index 0237434c..e2c3f8c5 100644 --- a/app/[locale]/(public)/content-management/rewrite/create/[id]/page.tsx +++ b/app/[locale]/(public)/content-management/rewrite/create/[id]/page.tsx @@ -3,30 +3,51 @@ import HeaderManagement from "@/components/landing-page/header-management"; import SidebarManagement from "@/components/landing-page/sidebar-management"; import { useRouter } from "@/i18n/routing"; -import { getCookiesDecrypt } from "@/lib/utils"; +import { getCookiesDecrypt, setCookiesEncrypt } from "@/lib/utils"; import { useSearchParams } from "next/navigation"; -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import Swal from "sweetalert2"; import withReactContent from "sweetalert2-react-content"; import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@/components/ui/select"; +import { Controller, useForm } from "react-hook-form"; +import * as z from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import CustomEditor from "@/components/editor/custom-editor"; +import { generateDataArticle, getDetailArticle } from "@/service/content/ai"; +import { Button } from "@/components/ui/button"; +import { error, loading } from "@/config/swal"; +import { saveContentRewrite } from "@/service/content/content"; +import { getPublicSuggestionList } from "@/service/landing/landing"; +import { getDetail } from "@/service/detail/detail"; +import { yupResolver } from "@hookform/resolvers/yup"; +import * as Yup from "yup"; +import { htmlToString } from "@/utils/globals"; +import Cookies from "js-cookie"; -const page = () => { - // const { states } = props; +const imageSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + description: z.string().min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }), + creatorName: z.string().min(1, { message: "Creator diperlukan" }), + // tags: z.string().min(1, { message: "Judul diperlukan" }), +}); + +const page = (props: { states?: any }) => { + const { states } = props; const [profile, setProfile] = useState(); const MySwal = withReactContent(Swal); const router = useRouter(); const [, setLoadingState] = useState(false); const searchParams = useSearchParams(); const id: any = searchParams?.get("title"); - const [content, setContent] = useState([]); + const [content, setContent] = useState([]); const [isFromSPIT, setIsFromSPIT] = useState(false); const [listSuggestion, setListSuggestion] = useState(); - const [main, setMain] = useState(); + const [main, setMain] = useState(); const userId = getCookiesDecrypt("uie"); const userRoleId = getCookiesDecrypt("urie"); - const [articleIds, setArticleIds] = useState([]); + const [articleIds, setArticleIds] = useState([]); const [isGeneratedArticle, setIsGeneratedArticle] = useState(false); - const [selectedArticleId, setSelectedArticleId] = useState(null); + const [selectedArticleId, setSelectedArticleId] = useState(null); const [articleBody, setArticleBody] = useState(""); const [selectedAdvConfig, setSelectedAdvConfig] = useState(""); const [selectedWritingStyle, setSelectedWritingStyle] = useState(""); @@ -36,11 +57,235 @@ const page = () => { const [selectedMainKeyword, setSelectedMainKeyword] = useState(""); const [selectedSEO, setSelectedSEO] = useState(""); const [selectedSize, setSelectedSize] = useState(""); - const [detailArticle, setDetailArticle] = useState(null); + const [detailArticle, setDetailArticle] = useState(null); const [contentType, setContentType] = useState("all"); + const [isLoadingData, setIsLoadingData] = useState(false); + const [detailData, setDetailData] = useState(null); + const [articleImages, setArticleImages] = useState([]); const userLevelId = getCookiesDecrypt("ulie"); const roleId = getCookiesDecrypt("urie"); + type ImageSchema = z.infer; + + const validationSchema = Yup.object().shape({ + title: Yup.string().required("Judul tidak boleh kosong"), + }); + + let componentMounted = true; + + const { control } = useForm({ + resolver: zodResolver(imageSchema), + }); + + const formOptions = { + resolver: yupResolver(validationSchema), + }; + + const { + register, + handleSubmit, + reset, + formState: { errors }, + setValue, + } = useForm(formOptions); + + const handleArticleIdClick = async (id: string) => { + setIsLoadingData(true); + let retryCount = 0; + const maxRetries = 20; + + try { + const waitForStatusUpdate = async () => { + while (retryCount < maxRetries) { + const res = await getDetailArticle(id); + const articleData = res?.data?.data; + + if (articleData?.status === 2) { + return articleData; + } + + retryCount++; + await new Promise((resolve) => setTimeout(resolve, 5000)); + } + + throw new Error("Timeout: Artikel belum selesai diproses."); + }; + const articleData = await waitForStatusUpdate(); + const cleanArticleBody = articleData?.articleBody?.replace(/]*>/g, ""); + const articleImagesData = articleData?.imagesUrl?.split(","); + setArticleBody(cleanArticleBody || ""); + setDetailData(articleData); + setSelectedArticleId(id); + setArticleImages(articleImagesData || []); + } catch (error) { + console.error("Error fetching article details:", error); + } finally { + setIsLoadingData(false); + } + }; + + const save = async (data: any) => { + const request = { + title: data.title, + articleId: detailArticle?.id, + mediaUploadId: id.split("-")?.[0], + articleBody: detailArticle?.articleBody, + metaTitle: detailArticle?.metaTitle, + metaDescription: detailArticle?.metaDescription, + mainKeyword: detailArticle?.mainKeyword, + additionalKeyword: detailArticle?.additionalKeyword, + articleSize: detailArticle?.articleSize, + style: detailArticle?.style, + website: detailArticle?.website, + imageUrl: detailArticle?.imageUrl, + }; + loading(); + const res = await saveContentRewrite(request); + if (res?.error) { + error(res?.message); + return false; + } + successSubmit(); + }; + + function successSubmit() { + MySwal.fire({ + title: "Sukses", + icon: "success", + confirmButtonColor: "#3085d6", + confirmButtonText: "OK", + }).then((result) => { + if (result.isConfirmed) { + router.push("/content-management/rewrite"); + } + }); + } + + function onSubmit(data: any) { + MySwal.fire({ + title: "Simpan Data", + text: "", + icon: "warning", + showCancelButton: true, + cancelButtonColor: "#d33", + confirmButtonColor: "#3085d6", + confirmButtonText: "Simpan", + }).then((result) => { + if (result.isConfirmed) { + save(data); + } + }); + } + useEffect(() => { + async function initState() { + setLoadingState(true); + const response = await getDetail(id, states == "polda" ? "polda" : "mabes"); + console.log("Detail dataaaa ::", response); + if (response?.data?.data?.isActive == false) { + window.location.replace("/"); + } + const responseGet = await getPublicSuggestionList(id?.split("-")?.[0]); + + // close(); + if (componentMounted) { + setContent(response?.data.data); + setIsFromSPIT(response?.data.data?.isFromSPIT); + setListSuggestion(responseGet?.data?.data); + console.log("data list file", response?.data.data?.files); + // const mainUrl = response?.data.data?.files[0]?.url; + // const ticket = response?.data.data?.files[0]?.ticket; + // const urlBlob = await getBlobContent(mainUrl, ticket); + setMain({ + id: response?.data.data?.files[0]?.id, + type: response?.data.data?.fileType.name, + url: Number(response?.data.data?.fileType?.id) == 4 ? response?.data.data?.files[0]?.secondaryUrl : response?.data.data?.files[0]?.url, + thumbnailFileUrl: response?.data.data?.files[0]?.thumbnailFileUrl, + names: response?.data.data?.files[0]?.fileName, + format: response?.data.data?.files[0]?.format, + widthPixel: response?.data.data?.files[0]?.widthPixel, + heightPixel: response?.data.data?.files[0]?.heightPixel, + size: response?.data.data?.files[0]?.size, + caption: response?.data.data?.files[0]?.caption, + }); + + // Send Meta Data + const metaData = { + title: response?.data.data?.title, + image: response?.data.data?.thumbnailLink, + }; + + setCookiesEncrypt("meta_data", metaData); + setLoadingState(false); // (2) write some value to state + // await new Promise(resolve => setTimeout(resolve, 1000)); // 2 sec + // setIdm(); + } + + return () => { + // This code runs when component is unmounted + componentMounted = false; // (4) set it to false if we leave the page + }; + } + + initState(); + }, [id]); + + const handleGenerateArtikel = async () => { + loading(); + const request = { + advConfig: selectedAdvConfig, + style: selectedWritingStyle, + website: "None", + connectToWeb: true, + lang: selectedLanguage, + pointOfView: "None", + title: content?.title, + imageSource: "Web", + mainKeyword: content?.title, + additionalKeywords: content?.htmlDescription, + targetCountry: null, + articleSize: selectedSize, + projectId: 2, + createdBy: roleId, + clientId: "ngDLPPiorplznw2jTqVe3YFCz5xqKfUJ", + }; + + const res = await generateDataArticle(request); + close(); + + if (res.error) { + console.error(res.message); + return false; + } + + const newArticleId = res?.data?.data?.id; + setIsGeneratedArticle(true); + + setArticleIds((prevIds: any) => { + if (prevIds.length < 5) { + return [...prevIds, newArticleId]; + } else { + const updatedIds = [...prevIds]; + updatedIds[4] = newArticleId; + return updatedIds; + } + }); + + Cookies.set("nulisAIArticleIdTemp", articleIds); + }; + + const handleArticleClick = async (id: any) => { + const res = await getDetailArticle(id); + const articleData = res?.data?.data; + const cleanArticleBody = articleData?.articleBody?.replace(/]*>/g, ""); + + const articleImagesData = articleData?.imagesUrl?.split(","); // Split URLs into an array + + setArticleBody(cleanArticleBody || ""); // Set articleBody for CKEditor + setDetailArticle(articleData); + setSelectedArticleId(id); + // setArticleImages(articleImagesData || []); // Set images array in state + }; + return ( <> @@ -51,88 +296,166 @@ const page = () => {
Content Rewrite
-
-
-
-

Bahasa

- + + {/* {content && ( */} +
+
+
+

Bahasa

+ +
+
+

Context Type

+ +
+
+

Writing Style

+ +
+
+

Article Size

+ +
-
-

Context Type

- + +
+

Judul

+ setSelectedTitle(e.target.value)} + />
-
-

Writing Style

- +
+

Main Keyword

+ + // setSelectedMainKeyword(e.target.value) + // } + placeholder="Masukan Main Keyword disini!" + defaultValue={content?.title} + />
-
-

Article Size

- +
+

SEO

+