PluginProbe
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News / 4.0.8
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News v4.0.8
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 2.3.5 2.3.6 2.4.0 2.4.1 2.4.10 2.4.11 2.4.12 2.4.13 2.4.14 2.4.15 2.4.16 2.4.17 2.4.18 2.4.19 2.4.2 2.4.20 2.4.21 All 88 releases
post-carousel / src / admin / components / layout / Header.js

Header.js in Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News 4.0.8, at src/admin/components/layout/Header.js

397 lines 10.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { useEffect, useState, useRef } from "@wordpress/element";
2 import { __ } from "@wordpress/i18n";
3 import useGetChangeLogData from "../../hooks/getChangeLogData";
4 import { Arrow, ArrowRight } from "../icons/navigation";
5 import { Logo, OurPluginsIcon } from "../icons/brand";
6 import { LogNoticeIcon, Blog, Community, DocsStroked, FeatRequest, GetHelp, Roadmap, SetupWizard, TechSupport, Video, WhatsNew } from "../icons/ui";
7 import { CloseIcon } from "../../../prebuild-library/icons";
8
9 const GreenCheckIcon = () => (
10 <img
11 src={`${sp_pcp_block_settings?.pluginUrl}/assets/images/bell-icon.gif`}
12 width={18}
13 height={18}
14 alt=""
15 />
16 );
17
18 const GetHelpItems = [
19 {
20 title: __("Documentation", "post-carousel"),
21 Icon: DocsStroked,
22 link: "https://wpsmartpost.com/docs/",
23 },
24 {
25 title: __("Technical Support", "post-carousel"),
26 Icon: TechSupport,
27 link: "https://shapedplugin.com/create-new-ticket/",
28 },
29 {
30 title: __("Setup Wizard", "post-carousel"),
31 Icon: SetupWizard,
32 link: `${sp_pcp_block_settings?.homeUrl}wp-admin/admin.php?page=pcp_help#setupwizard`,
33 },
34 {
35 title: __("Public Roadmap", "post-carousel"),
36 Icon: Roadmap,
37 link: "https://community.shapedplugin.com/roadmap/smart-post/",
38 },
39 {
40 title: __("Request a Feature", "post-carousel"),
41 Icon: FeatRequest,
42 link: "https://community.shapedplugin.com/portal/space/smartpost/home",
43 },
44 {
45 title: __("Video Tutorials", "post-carousel"),
46 Icon: Video,
47 link: "https://youtu.be/vnveuaiPBdc?si=B-DH-foeAh9TwjE5",
48 },
49 {
50 title: __("What's New", "post-carousel"),
51 Icon: WhatsNew,
52 link: "https://wpsmartpost.com/changelog/",
53 },
54 {
55 title: __("Blog: Latest News", "post-carousel"),
56 Icon: Blog,
57 link: "https://wpsmartpost.com/blog/",
58 },
59 {
60 title: __("Join Community", "post-carousel"),
61 Icon: Community,
62 link: "https://community.shapedplugin.com/portal/",
63 },
64 {
65 title: __("About Us", "post-carousel"),
66 Icon: DocsStroked,
67 link: "#about-us",
68 value: "about-us",
69 internal: true,
70 },
71 ];
72
73 const Header = ({ page, setPage, modulesOptions }) => {
74 const [changeLogToggle, setChangeLogToggle] = useState(false);
75 const [changeLodData, setChangeLogData] = useState(null);
76 const [showUpgradeNotice, setShowUpgradeNotice] = useState(!!sp_pcp_block_settings?.upgradeNoticeVisible);
77 const [activeItemPosition, setActiveItemPosition] = useState({ left: 0, width: 0 });
78 const navRef = useRef();
79 const itemsRef = useRef({});
80 const getHelpRef = useRef();
81
82 const { getChangeLog } = useGetChangeLogData();
83
84 const changeLogControl = async () => {
85 if (!changeLodData) {
86 const changelog = await getChangeLog();
87 setChangeLogData(changelog);
88 }
89 setChangeLogToggle(!changeLogToggle);
90 if (!changeLogToggle) {
91 document.querySelector("body").classList.add("show-change-log");
92 } else {
93 document.querySelector("body").classList.remove("show-change-log");
94 }
95 };
96
97 useEffect(() => {
98 const closeChangeLog = (e) => {
99 if (changeLogToggle) {
100 const changelogEl = document.querySelector(".sp-pcp-change-log");
101 if (changelogEl && !changelogEl.contains(e.target)) {
102 setChangeLogToggle(false);
103 document.querySelector("body").classList.remove("show-change-log");
104 }
105 }
106 };
107 document.addEventListener("click", closeChangeLog);
108 return () => document.removeEventListener("click", closeChangeLog);
109 }, [changeLogToggle]);
110
111 const enabledSavedTemplate = modulesOptions?.some((item) => item.module_name === "saved-template" && item.show);
112
113 useEffect(() => {
114 const postMenu = document.getElementById("menu-posts-sp_post_carousel");
115 if (!postMenu) {
116 return;
117 }
118 const saveTemplateItem = postMenu?.querySelectorAll("li");
119
120 if (saveTemplateItem && saveTemplateItem.length > 3) {
121 if (!enabledSavedTemplate) {
122 saveTemplateItem[3].style.display = "none";
123 } else {
124 saveTemplateItem[3].style.display = "block";
125 }
126 }
127
128 // Initialize recommended plugins wrapper visibility on mount
129 const pluginsContainer = document.querySelector(".spspc-recommended-page");
130 if (pluginsContainer) {
131 if (page === "our-plugins") {
132 pluginsContainer.style.display = "block";
133 } else {
134 pluginsContainer.style.display = "none";
135 }
136 }
137 }, [enabledSavedTemplate, page]);
138
139 // Update sliding indicator position when current page changes
140 useEffect(() => {
141 if (page === "about-us") {
142 // Position indicator below Get Help button
143 const getHelpEl = getHelpRef.current;
144 const nav = navRef.current;
145 if (getHelpEl && nav) {
146 const navRect = nav.getBoundingClientRect();
147 const getHelpRect = getHelpEl.getBoundingClientRect();
148 setActiveItemPosition({
149 left: getHelpRect.left - navRect.left,
150 width: getHelpRect.width,
151 });
152 }
153 } else if (itemsRef.current[page]) {
154 // Position indicator below nav item
155 const item = itemsRef.current[page];
156 const nav = navRef.current;
157 if (item && nav) {
158 const navRect = nav.getBoundingClientRect();
159 const itemRect = item.getBoundingClientRect();
160 setActiveItemPosition({
161 left: itemRect.left - navRect.left,
162 width: itemRect.width,
163 });
164 }
165 }
166
167 // Show/hide recommended plugins wrapper based on active page
168 const pluginsContainer = document.querySelector(".spspc-recommended-page");
169 if (pluginsContainer) {
170 if (page === "our-plugins") {
171 pluginsContainer.style.display = "block";
172 } else {
173 pluginsContainer.style.display = "none";
174 }
175 }
176 }, [page]);
177
178 const tabChange = (e) => {
179 e.preventDefault();
180 const targetLink = e.currentTarget.closest("a");
181 const targetValue = targetLink.getAttribute("value");
182 setPage(targetValue);
183 window.location.hash = targetValue;
184 };
185
186 // Permanently dismiss the upgrade notice: hide it immediately and persist the
187 // choice via AJAX so it never shows again on subsequent page loads.
188 const dismissUpgradeNotice = () => {
189 setShowUpgradeNotice(false);
190
191 const formData = new FormData();
192 formData.append("action", "sp_pcp_dismiss_upgrade_notice");
193 formData.append("nonce", sp_pcp_block_settings?.nonce);
194 formData.append("dismissed", true);
195
196 fetch(ajaxurl, { method: "POST", body: formData }).catch(() => {});
197 };
198
199 const navigationItems = [
200 {
201 title: __("Dashboard", "post-carousel"),
202 value: "quick-start",
203 href: "#",
204 show: true,
205 },
206 {
207 title: __("Blocks", "post-carousel"),
208 value: "blocks",
209 href: "#blocks",
210 show: true,
211 badge: __("NEW!", "post-carousel"),
212 },
213 {
214 title: __("Modules", "post-carousel"),
215 value: "modules",
216 href: "#modules",
217 show: true,
218 },
219 {
220 title: __("Saved Templates", "post-carousel"),
221 value: "savedTemplate",
222 href: "#savedTemplate",
223 show: enabledSavedTemplate,
224 },
225 {
226 title: __("Integrations", "post-carousel"),
227 value: "integrations",
228 href: "#integrations",
229 show: true,
230 },
231 {
232 title: __("Settings", "post-carousel"),
233 value: "settings",
234 href: "#settings",
235 show: true,
236 },
237 {
238 title: __("Lite vs Pro", "post-carousel"),
239 value: "lite-vs-pro",
240 href: "#lite-vs-pro",
241 show: true,
242 },
243 {
244 title: __("Our Plugins", "post-carousel"),
245 value: "our-plugins",
246 href: "#our-plugins",
247 show: true,
248 icon: <OurPluginsIcon />,
249 },
250 ];
251
252 const getNavDividerClass = (value) => {
253 if (value === "lite-vs-pro") {
254 return "sp-pcp-nav-divider";
255 }
256 if (value === "our-plugins") {
257 return "sp-pcp-nav-item-with-icon";
258 }
259 return "";
260 };
261
262 return (
263 <>
264 <div className="sp-pcp-change-log">
265 <div className="sp-pcp-change-log-header">
266 <h4>Latest Updates - Changelog</h4>
267 <span onClick={() => changeLogControl()} className="sp-pcp-change-log-close">
268 <CloseIcon />
269 </span>
270 </div>
271 {changeLodData && (
272 <div
273 className="sp-smart-changelog-details"
274 dangerouslySetInnerHTML={{
275 __html: changeLodData?.changelog,
276 }}
277 />
278 )}
279 {!changeLodData && changeLogToggle && (
280 <div className="sp-smart-changelog-details">
281 <p>Loading....</p>
282 </div>
283 )}
284 </div>
285
286 {/* Upgrade Notice with Close Button */}
287 {showUpgradeNotice && (
288 <div className="sp-pcp-green-header-notice">
289 <div className="sp-pcp-green-header-notice-content">
290 <GreenCheckIcon />
291 <span className="sp-pcp-green-header-notice-text">
292 You're currently using <strong>Smart Post Lite</strong>. To access additional features, consider
293 </span>
294 <a
295 className="sp-pcp-green-header-notice-link"
296 href="https://wpsmartpost.com/pricing/?ref=1"
297 target="_blank"
298 rel="noopener noreferrer"
299 >
300 {__("Upgrade to Pro", "post-carousel")}
301 <ArrowRight />
302 </a>
303 <button
304 className="sp-pcp-green-header-notice-close"
305 onClick={dismissUpgradeNotice}
306 type="button"
307 >
308 <CloseIcon />
309 </button>
310 </div>
311 </div>
312 )}
313
314 {/* Header with Three-Column Layout */}
315 <div className="sp-pcp-blocks-settings-page-header">
316 <div className="sp-pcp-block-setting-header-wrapper">
317 {/* Left: Logo + Version */}
318 <div className="sp-pcp-blocks-settings-page-header-left">
319 <Logo />
320 <span onClick={() => changeLogControl()} className="sp-pcp-plugin-version">
321 <LogNoticeIcon /> {sp_pcp_block_settings.pluginVersion}
322 </span>
323 </div>
324
325 {/* Center: Navigation with Sliding Indicator */}
326 <div className="sp-pcp-admin-dashboard-nav" ref={navRef}>
327 <span
328 className="sp-pcp-nav-sliding-indicator"
329 style={{ left: `${activeItemPosition.left}px`, width: `${activeItemPosition.width}px` }}
330 ></span>
331 <ul>
332 {navigationItems?.map(
333 ({ title, value, href, show, badge, icon }, index) =>
334 show && (
335 <li
336 key={index}
337 className={getNavDividerClass(value)}
338 ref={(el) => (itemsRef.current[value] = el)}
339 >
340 <a
341 href={href}
342 className={page === value ? "active" : ""}
343 value={value}
344 onClick={tabChange}
345 >
346 {icon}
347 {title}
348 {badge && (
349 <span className="sp-pcp-nav-badge">{badge}</span>
350 )}
351 </a>
352 </li>
353 )
354 )}
355 </ul>
356 </div>
357
358 {/* Right: Get Help */}
359 <div
360 ref={getHelpRef}
361 className={`sp-pcp-blocks-settings-page-header-right${page === "about-us" ? " active" : ""}`}
362 >
363 <GetHelp />
364 <span className="get-help">{__("Get Help", "post-carousel")}</span>
365 <div className="sp-pcp-help-drop-down">
366 {GetHelpItems?.map(
367 ({ title, link, Icon, internal, value }, index) => (
368 <a
369 key={index}
370 href={link}
371 {...(!internal && { target: "_blank", rel: "noopener noreferrer" })}
372 {...(internal && {
373 onClick: (e) => {
374 e.preventDefault();
375 setPage(value);
376 window.location.hash = value;
377 }
378 })}
379 >
380 <Icon />
381 <span>{title}</span>
382 <span className="drop-down-arrow">
383 <Arrow />
384 </span>
385 </a>
386 )
387 )}
388 </div>
389 </div>
390 </div>
391 </div>
392 </>
393 );
394 };
395
396 export default Header;
397