diff --git a/components/details/details-content.tsx b/components/details/details-content.tsx
index 49e3617..dd6a790 100644
--- a/components/details/details-content.tsx
+++ b/components/details/details-content.tsx
@@ -21,6 +21,7 @@ import {
import { saveActivity } from "@/service/activity-log";
import { useForm } from "react-hook-form";
import { Badge } from "../ui/badge";
+import { formatTextToHtmlTag } from "@/utils/global";
type TabKey = "trending" | "comments" | "latest";
@@ -320,6 +321,16 @@ export default function DetailContent() {
);
}
+ function removeImgTags(htmlString?: { __html: string }) {
+ const parser = new DOMParser();
+ const doc = parser.parseFromString(String(htmlString?.__html), "text/html");
+
+ const images = doc.querySelectorAll("img");
+ images.forEach((img) => img.remove());
+
+ return { __html: doc.body.innerHTML };
+ }
+
function decodeHtmlString(raw: string = "") {
if (!raw) return "";
@@ -497,11 +508,10 @@ export default function DetailContent() {
{/*
*/}
diff --git a/components/editor/custom-editor.js b/components/editor/custom-editor.js
index 95886a7..cee120f 100644
--- a/components/editor/custom-editor.js
+++ b/components/editor/custom-editor.js
@@ -1,7 +1,7 @@
-// components/custom-editor.js
-
-import React from "react";
+import React, { useCallback, useEffect, useRef, useState } from "react";
import { CKEditor } from "@ckeditor/ckeditor5-react";
+
+import "@/styles/custom-editor.css";
import Editor from "@/vendor/ckeditor5/build/ckeditor";
function CustomEditor(props) {
@@ -47,7 +47,7 @@ function CustomEditor(props) {
padding: 1rem;
}
p {
- margin: 0.5em 0;
+ margin: 0.5em 0 !important;
}
h1, h2, h3, h4, h5, h6 {
margin: 1em 0 0.5em 0;
@@ -72,98 +72,6 @@ function CustomEditor(props) {
},
}}
/>
-
);
}
diff --git a/components/editor/view-editor.js b/components/editor/view-editor.js
index 31e7db9..1e579b0 100644
--- a/components/editor/view-editor.js
+++ b/components/editor/view-editor.js
@@ -48,7 +48,8 @@ function ViewEditor(props) {
.ckeditor-view-wrapper {
border-radius: 6px;
overflow: hidden;
- box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1),
+ box-shadow:
+ 0 1px 3px 0 rgba(0, 0, 0, 0.1),
0 1px 2px 0 rgba(0, 0, 0, 0.06);
}
diff --git a/components/table/article-table.tsx b/components/table/article-table.tsx
index 3a50853..919c99d 100644
--- a/components/table/article-table.tsx
+++ b/components/table/article-table.tsx
@@ -316,7 +316,7 @@ export default function ArticleTable() {
return cellValue;
}
},
- [article, page]
+ [article, page],
);
let typingTimer: NodeJS.Timeout;
@@ -445,8 +445,8 @@ export default function ArticleTable() {
-
-
+
+
{(username === "admin-mabes"
@@ -455,7 +455,18 @@ export default function ArticleTable() {
).map((column) => (
{column.name}
@@ -472,7 +483,17 @@ export default function ArticleTable() {
).map((column) => (
{renderCell(item, column.uid)}
diff --git a/package-lock.json b/package-lock.json
index 0db3818..2101675 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -42,7 +42,7 @@
"react-apexcharts": "^1.7.0",
"react-datepicker": "^8.4.0",
"react-day-picker": "^9.7.0",
- "react-dom": "^19.0.0",
+ "react-dom": "^19.2.4",
"react-dropzone": "^14.3.8",
"react-hook-form": "^7.59.0",
"react-password-checklist": "^1.8.1",
@@ -1521,111 +1521,6 @@
"fast-glob": "3.3.1"
}
},
- "node_modules/@next/swc-darwin-arm64": {
- "version": "15.3.4",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.4.tgz",
- "integrity": "sha512-z0qIYTONmPRbwHWvpyrFXJd5F9YWLCsw3Sjrzj2ZvMYy9NPQMPZ1NjOJh4ojr4oQzcGYwgJKfidzehaNa1BpEg==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-darwin-x64": {
- "version": "15.3.4",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.4.tgz",
- "integrity": "sha512-Z0FYJM8lritw5Wq+vpHYuCIzIlEMjewG2aRkc3Hi2rcbULknYL/xqfpBL23jQnCSrDUGAo/AEv0Z+s2bff9Zkw==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-linux-arm64-gnu": {
- "version": "15.3.4",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.4.tgz",
- "integrity": "sha512-l8ZQOCCg7adwmsnFm8m5q9eIPAHdaB2F3cxhufYtVo84pymwKuWfpYTKcUiFcutJdp9xGHC+F1Uq3xnFU1B/7g==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-linux-arm64-musl": {
- "version": "15.3.4",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.4.tgz",
- "integrity": "sha512-wFyZ7X470YJQtpKot4xCY3gpdn8lE9nTlldG07/kJYexCUpX1piX+MBfZdvulo+t1yADFVEuzFfVHfklfEx8kw==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-linux-x64-gnu": {
- "version": "15.3.4",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.4.tgz",
- "integrity": "sha512-gEbH9rv9o7I12qPyvZNVTyP/PWKqOp8clvnoYZQiX800KkqsaJZuOXkWgMa7ANCCh/oEN2ZQheh3yH8/kWPSEg==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-linux-x64-musl": {
- "version": "15.3.4",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.4.tgz",
- "integrity": "sha512-Cf8sr0ufuC/nu/yQ76AnarbSAXcwG/wj+1xFPNbyNo8ltA6kw5d5YqO8kQuwVIxk13SBdtgXrNyom3ZosHAy4A==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-win32-arm64-msvc": {
- "version": "15.3.4",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.4.tgz",
- "integrity": "sha512-ay5+qADDN3rwRbRpEhTOreOn1OyJIXS60tg9WMYTWCy3fB6rGoyjLVxc4dR9PYjEdR2iDYsaF5h03NA+XuYPQQ==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
"node_modules/@next/swc-win32-x64-msvc": {
"version": "15.3.4",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.4.tgz",
@@ -6375,9 +6270,9 @@
]
},
"node_modules/react": {
- "version": "19.2.3",
- "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
- "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
+ "version": "19.2.4",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
+ "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
"engines": {
"node": ">=0.10.0"
}
@@ -6429,14 +6324,14 @@
}
},
"node_modules/react-dom": {
- "version": "19.1.0",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
- "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
+ "version": "19.2.4",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
+ "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
"dependencies": {
- "scheduler": "^0.26.0"
+ "scheduler": "^0.27.0"
},
"peerDependencies": {
- "react": "^19.1.0"
+ "react": "^19.2.4"
}
},
"node_modules/react-dropzone": {
@@ -6748,9 +6643,9 @@
}
},
"node_modules/scheduler": {
- "version": "0.26.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
- "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
+ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="
},
"node_modules/semver": {
"version": "7.7.2",
diff --git a/package.json b/package.json
index 57a2716..15769bc 100644
--- a/package.json
+++ b/package.json
@@ -43,7 +43,7 @@
"react-apexcharts": "^1.7.0",
"react-datepicker": "^8.4.0",
"react-day-picker": "^9.7.0",
- "react-dom": "^19.0.0",
+ "react-dom": "^19.2.4",
"react-dropzone": "^14.3.8",
"react-hook-form": "^7.59.0",
"react-password-checklist": "^1.8.1",
diff --git a/styles/custom-editor.css b/styles/custom-editor.css
new file mode 100644
index 0000000..d203c3d
--- /dev/null
+++ b/styles/custom-editor.css
@@ -0,0 +1,121 @@
+/* ========== CKEditor Wrapper ========== */
+.ckeditor-wrapper {
+ border-radius: 6px;
+ overflow: hidden;
+ box-shadow:
+ 0 1px 3px 0 rgba(0, 0, 0, 0.1),
+ 0 1px 2px 0 rgba(0, 0, 0, 0.06);
+}
+
+/* ========== Main Editor Container ========== */
+.ckeditor-wrapper .ck.ck-editor__main {
+ min-height: var(--editor-min-height, 400px);
+ max-height: var(--editor-max-height, 600px);
+}
+
+/* ========== Editable Content Area (ClassicEditor) ========== */
+.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline {
+ min-height: calc(var(--editor-min-height, 400px) - 50px);
+ max-height: calc(var(--editor-max-height, 600px) - 50px);
+ overflow-y: auto !important;
+ scrollbar-width: thin;
+ scrollbar-color: #cbd5e1 #f1f5f9;
+ background: #fff !important;
+ color: #111 !important;
+ font-family:
+ -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
+ font-size: 14px;
+ line-height: 1.6;
+ padding: 1rem;
+ border: none !important;
+}
+
+/* ========== Headings and Text Formatting ========== */
+.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h1,
+.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h2,
+.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h3,
+.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h4,
+.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h5,
+.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h6 {
+ margin: 1em 0 0.5em 0;
+ color: inherit !important;
+}
+
+.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline p {
+ margin: 0.5em 0 !important;
+}
+
+.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline ul,
+.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline ol {
+ margin: 0.5em 0;
+ padding-left: 2em;
+}
+
+.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline blockquote {
+ margin: 1em 0;
+ padding: 0.5em 1em;
+ border-left: 4px solid #d1d5db;
+ background-color: #f9fafb;
+ color: inherit !important;
+}
+
+/* ========== Dark Mode Support ========== */
+.dark .ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline {
+ background: #111 !important;
+ color: #f9fafb !important;
+}
+
+.dark .ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h1,
+.dark .ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h2,
+.dark .ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h3,
+.dark .ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h4,
+.dark .ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h5,
+.dark .ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h6 {
+ color: #f9fafb !important;
+}
+
+.dark .ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline blockquote {
+ background-color: #1f2937 !important;
+ border-left-color: #374151 !important;
+ color: #f3f4f6 !important;
+}
+
+/* ========== Custom Scrollbars (Light & Dark) ========== */
+.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline::-webkit-scrollbar {
+ width: 8px;
+}
+
+.ckeditor-wrapper
+ .ck.ck-content.ck-editor__editable_inline::-webkit-scrollbar-track {
+ background: #f1f5f9;
+ border-radius: 4px;
+}
+
+.ckeditor-wrapper
+ .ck.ck-content.ck-editor__editable_inline::-webkit-scrollbar-thumb {
+ background: #cbd5e1;
+ border-radius: 4px;
+}
+
+.ckeditor-wrapper
+ .ck.ck-content.ck-editor__editable_inline::-webkit-scrollbar-thumb:hover {
+ background: #94a3b8;
+}
+
+.dark
+ .ckeditor-wrapper
+ .ck.ck-content.ck-editor__editable_inline::-webkit-scrollbar-track {
+ background: #1f2937;
+}
+
+.dark
+ .ckeditor-wrapper
+ .ck.ck-content.ck-editor__editable_inline::-webkit-scrollbar-thumb {
+ background: #4b5563;
+}
+
+.dark
+ .ckeditor-wrapper
+ .ck.ck-content.ck-editor__editable_inline::-webkit-scrollbar-thumb:hover {
+ background: #6b7280;
+}