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 / quick-setup / quickbuilder / QuickBuild.jsx

QuickBuild.jsx in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 4.9.5, at react-src/admin/quick-setup/quickbuilder/QuickBuild.jsx

108 lines 3.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { FormBuilder, useBuilderContext } from "quickbuilder";
2 import React, { useCallback, useEffect, useRef } from "react";
3 import "react-toastify/dist/ReactToastify.css";
4 import { proAlert } from "../../utils";
5 import toastAlert from "../../utils/toastAlert";
6
7 const getCookie = (name) => {
8 const match = document.cookie.match(
9 "(^|;)\\s*" + name + "\\s*=\\s*([^;]+)"
10 );
11 return match ? match.pop() : "";
12 };
13
14 const QuickBuild = (props) => {
15 const builder = useBuilderContext();
16 const wrapperRef = useRef(null);
17 // Furthest step the user has actually reached (via Proceed / Next), by DOM
18 // index. Steps beyond this stay locked so the wizard is a real stepper.
19 const maxReachedRef = useRef(0);
20
21 useEffect(() => {
22 builder.registerAlert("pro_alert", proAlert);
23 builder.registerAlert("toast", toastAlert);
24 }, []);
25
26 builder.submit.onSubmit = useCallback((event, context) => {
27 return 0;
28 }, []);
29
30 // Step gating. quickbuilder's Menu only has a global `clickable` flag, so we
31 // enforce stepper rules on the tab <li>s directly:
32 // - a tab is clickable only once it has been reached (Proceed / Next);
33 // - "Getting Started" locks once the user consents (Proceed to Next Step),
34 // so there's no going back to the consent screen — matching the prior
35 // footer Back-disable behaviour, now that tabs are clickable too.
36 const isStartClicked = builder?.values?.isStartClicked;
37 useEffect(() => {
38 const wrapper = wrapperRef.current;
39 if (!wrapper) {
40 return;
41 }
42
43 const applyGate = () => {
44 const items = Array.from(
45 wrapper.querySelectorAll(".wprf-tab-nav .wprf-tab-nav-item")
46 );
47 if (!items.length) {
48 return;
49 }
50
51 const activeIndex = items.findIndex((el) =>
52 el.classList.contains("wprf-active-nav")
53 );
54 if (activeIndex < 0) {
55 return;
56 }
57 if (activeIndex > maxReachedRef.current) {
58 maxReachedRef.current = activeIndex;
59 }
60
61 const consented =
62 getCookie("betterdocs_insights_allowed") === "1" ||
63 !!builder?.values?.isStartClicked;
64
65 items.forEach((el, index) => {
66 const isActive = index === activeIndex;
67 const isGettingStarted =
68 el.classList.contains("getting-started");
69
70 // Not yet reached → locked.
71 let disabled = index > maxReachedRef.current;
72 // Consent already given → the intro step is a dead end.
73 if (isGettingStarted && consented) {
74 disabled = true;
75 }
76
77 el.classList.toggle("wprf-tab-disabled", disabled && !isActive);
78 });
79 };
80
81 applyGate();
82
83 const nav = wrapper.querySelector(".wprf-tab-nav");
84 if (!nav) {
85 return;
86 }
87 // Re-gate whenever the active tab changes (from tabs or footer buttons).
88 const observer = new MutationObserver(applyGate);
89 observer.observe(nav, {
90 attributes: true,
91 subtree: true,
92 attributeFilter: ["class"],
93 });
94 return () => observer.disconnect();
95 }, [isStartClicked]);
96
97 return (
98 <div
99 className="betterdocs-quick-setup-builder-wrapper"
100 ref={wrapperRef}
101 >
102 <FormBuilder {...builder} />
103 </div>
104 );
105 };
106
107 export default QuickBuild;
108