PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.9.5
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.9.5
4.9.5 4.9.4 4.9.3 4.9.2 4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 All 203 releases
betterdocs / react-src / admin / dashboard-overview / components / RecentDocs.js

RecentDocs.js in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 4.9.5, at react-src/admin/dashboard-overview/components/RecentDocs.js

134 lines 4.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import React, { useState, useEffect } from "react";
2 import { __ } from "@wordpress/i18n";
3 import apiFetch from "@wordpress/api-fetch";
4 import PostsLoader from './PostsLoader';
5
6 const RecentDocs = () => {
7 const [posts, setPosts] = useState([]);
8 const [loading, setLoading] = useState(true);
9 const [error, setError] = useState(null);
10
11 useEffect(() => {
12 const fetchRecentDocs = async () => {
13 try {
14 const response = await apiFetch({
15 path: "/wp/v2/docs?status=publish,draft,pending,future,private&per_page=5&orderby=date&order=desc"
16 });
17 setPosts(response);
18 setLoading(false);
19 } catch (err) {
20 setError(err.message);
21 setLoading(false);
22 }
23 };
24
25 fetchRecentDocs();
26 }, []);
27
28 const getStatusLabel = (status) => {
29 const statusMap = {
30 publish: { label: __('Published', 'betterdocs'), class: 'published' },
31 future: { label: __('Scheduled', 'betterdocs'), class: 'scheduled' },
32 draft: { label: __('Drafted', 'betterdocs'), class: 'drafted' },
33 pending: { label: __('Pending', 'betterdocs'), class: 'pending' },
34 private: { label: __('Private', 'betterdocs'), class: 'private' }
35 };
36 return statusMap[status] || { label: status, class: status };
37 };
38
39 const truncateTitle = (title) => {
40 // Check if FAQ component is also displayed
41 const hasFaqs = betterdocs_admin?.count_all_faq > 0;
42
43 // Decode HTML entities (like ‘ to ')
44 const decodedTitle = document.createElement('textarea');
45 decodedTitle.innerHTML = title;
46 const cleanTitle = decodedTitle.value;
47
48 // If no FAQs, display full title without truncation
49 if (!hasFaqs) {
50 return cleanTitle;
51 }
52
53 // Otherwise, truncate to 35 characters when both components are displayed
54 const maxLength = 35;
55
56 return cleanTitle.length > maxLength ?
57 cleanTitle.substring(0, maxLength) + '..' :
58 cleanTitle;
59 };
60
61 // Don’t render the wrapper if not loading and there are no posts
62 if (!loading && posts.length === 0) {
63 return null;
64 }
65
66 return (
67 <div className="betterdocs-overview-col betterdocs-recent-col">
68 <div className="betterdocs-recent-wrapper">
69 <div className="betterdocs-recent-header">
70 <div className="betterdocs-flex justify-content-space-between align-items-center">
71 <div className="betterdocs-content-left">
72 <h3 className="betterdocs-recent-title">
73 {__('Recent Docs', 'betterdocs')}
74 </h3>
75 </div>
76 <div className="betterdocs-content-right">
77 <a
78 href={betterdocs_admin.admin_url + `admin.php?page=betterdocs-admin`}
79 className="betterdocs-view-all"
80 >
81 <span>{__('View All', 'betterdocs')}</span>
82 <span>
83 <svg width="18" height="18" viewBox="0 0 18 18" fill="none">
84 <g clipPath="url(#clip0_11456_29418)">
85 <path d="M12.7539 5.25L5.25391 12.75" stroke="#718096" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
86 <path d="M5.99609 5.25H12.7461V12" stroke="#718096" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
87 </g>
88 <defs>
89 <clipPath id="clip0_11456_29418">
90 <rect width="18" height="18" fill="white" />
91 </clipPath>
92 </defs>
93 </svg>
94 </span>
95 </a>
96 </div>
97 </div>
98 </div>
99
100 {loading ? (
101 <PostsLoader />
102 ) : error ? (
103 <div className="betterdocs-error">
104 {__('Error:', 'betterdocs')} {error}
105 </div>
106 ) : (
107 <ul className="betterdocs-recent-docs-list">
108 {posts.map(post => {
109 const status = getStatusLabel(post.status);
110 return (
111 <li
112 key={post.id}
113 className="betterdocs-recent-docs-list-items"
114 >
115 <a href={betterdocs_admin.admin_url + `post.php?post=${post.id}&action=edit`}>
116 <span className="recent-docs-title">
117 {truncateTitle(post.title.rendered)}
118 </span>
119 <span className={`recent-docs-tag tag-${status.class}`}>
120 {status.label}
121 </span>
122 </a>
123 </li>
124 );
125 })}
126 </ul>
127 )}
128 </div>
129 </div>
130 );
131 };
132
133 export default RecentDocs;
134