PluginProbe
AI Builder – Generate pages, blocks, images & translate with AI / 2.7.2
AI Builder – Generate pages, blocks, images & translate with AI v2.7.2
2.7.10 2.7.9 2.7.8 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.3.10 All 122 releases
ai-builder / assets / js / settings.js

settings.js in AI Builder – Generate pages, blocks, images & translate with AI 2.7.2, at assets/js/settings.js

183 lines 7.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 document.addEventListener("DOMContentLoaded", () => {
2 const form = document.getElementById("aibui-settings-form");
3 const toast = document.getElementById("aibui-settings-toast");
4
5 // Descriptions for Design Style options
6 const designStyleDescriptions = {
7 minimalist: "Priority on white space and readability. Few graphic elements, very airy and quiet design.",
8 "tech-modern": "A 'Startup' style with soft drop shadows, subtle gradients, and a very clean appearance.",
9 corporate: "A structured and reassuring design, ideal for B2B companies, firms, and consultants.",
10 brutalist: "Strong contrasts, bold typography, thick black borders. A style that dares and stands out.",
11 luxury: "Sophisticated, monochrome or gold palettes, often associated with serif fonts.",
12 organic: "Pastel colors, natural shapes, no pure black, for a wellness or nature ambiance.",
13 };
14
15 // Descriptions for Block Shapes options
16 const blockShapesDescriptions = {
17 sharp: "Right angles (0px). Gives a rigorous, solid, and technical look.",
18 soft: "Soft angles (4px - 8px). The current web standard, neutral and pleasant.",
19 rounded: "Pronounced curves (12px - 20px). Brings modernity and fluidity.",
20 pill: "Very rounded buttons and cards (Full radius). Friendly, young, and playful style.",
21 };
22
23 // Descriptions for Copywriting Tone options
24 const copywritingToneDescriptions = {
25 professional: "An expert tone, formal address, precise vocabulary. Inspires trust and authority.",
26 friendly: "A conversational, warm tone, close to the reader. Ideal for blogs or lifestyle brands.",
27 persuasive: "Short sentences, action-oriented (CTA), focused on customer benefits. For selling.",
28 educational: "A neutral, pedagogical, and detailed tone. Perfect for explaining complex services.",
29 enthusiastic: "Many positive adjectives, exclamation points, dynamic style to motivate.",
30 };
31
32 function showToast(message, isError = false) {
33 if (!toast) return;
34 toast.textContent = message;
35 toast.style.display = "block";
36 toast.style.background = isError ? "#b00020" : "#23272f";
37 toast.style.color = "#fff";
38 toast.style.padding = "10px 14px";
39 toast.style.borderRadius = "8px";
40 setTimeout(() => {
41 toast.style.display = "none";
42 }, 4000);
43 }
44
45 // Limite et compteur pour "Site description & context"
46 const SITE_DESCRIPTION_MAX = 1000;
47 const siteDescriptionTextarea = document.getElementById("siteDescription");
48 const siteDescriptionCounter = document.getElementById("siteDescription-counter");
49
50 function updateSiteDescriptionCounter() {
51 if (!siteDescriptionTextarea || !siteDescriptionCounter) return;
52 let value = siteDescriptionTextarea.value || "";
53 if (value.length > SITE_DESCRIPTION_MAX) {
54 value = value.slice(0, SITE_DESCRIPTION_MAX);
55 siteDescriptionTextarea.value = value;
56 }
57 siteDescriptionCounter.textContent = `${value.length}/${SITE_DESCRIPTION_MAX}`;
58 }
59
60 if (siteDescriptionTextarea && siteDescriptionCounter) {
61 siteDescriptionTextarea.addEventListener("input", updateSiteDescriptionCounter);
62 // Initialiser l'affichage au chargement
63 updateSiteDescriptionCounter();
64 }
65
66 // Update description when select changes
67 function updateDescription(selectId, descriptions) {
68 const select = document.getElementById(selectId);
69 const descriptionEl = document.getElementById(selectId + "-description");
70 if (!select || !descriptionEl) return;
71
72 select.addEventListener("change", () => {
73 const value = select.value;
74 descriptionEl.textContent = descriptions[value] || "";
75 });
76
77 // Set initial description
78 const initialValue = select.value;
79 descriptionEl.textContent = descriptions[initialValue] || "";
80 }
81
82 async function getJwtToken() {
83 const res = await fetch(aiBuilderVars.ajaxurl, {
84 method: "POST",
85 headers: { "Content-Type": "application/x-www-form-urlencoded" },
86 body: `action=aibui_get_token&nonce=${aiBuilderVars.nonce}`,
87 });
88 const data = await res.json();
89 if (data.success && data.data.token) return data.data.token;
90 throw new Error("Missing token");
91 }
92
93 async function loadSettings() {
94 try {
95 const jwt = await getJwtToken();
96 const res = await fetch(window.config.apiUrl + "/settings", {
97 method: "GET",
98 headers: { Authorization: `Bearer ${jwt}` },
99 });
100 if (!res.ok) throw new Error("Failed to load settings");
101 const data = await res.json();
102
103 // Expect shape: { primaryColor, secondaryColor, siteName, siteDescription, designStyle, blockShapes, copywritingTone }
104 const {
105 primaryColor = "#2f80ed",
106 secondaryColor = "#00b87c",
107 siteName = "",
108 siteDescription = "",
109 designStyle = "",
110 blockShapes = "",
111 copywritingTone = "",
112 } = data || {};
113
114 document.getElementById("primaryColor").value = primaryColor;
115 document.getElementById("secondaryColor").value = secondaryColor;
116 document.getElementById("siteName").value = siteName;
117 const siteDescriptionEl = document.getElementById("siteDescription");
118 if (siteDescriptionEl) {
119 siteDescriptionEl.value = siteDescription;
120 // Mettre à jour le compteur si déjà chargé
121 if (typeof updateSiteDescriptionCounter === "function") {
122 updateSiteDescriptionCounter();
123 }
124 }
125
126 if (designStyle) {
127 document.getElementById("designStyle").value = designStyle;
128 }
129 if (blockShapes) {
130 document.getElementById("blockShapes").value = blockShapes;
131 }
132 if (copywritingTone) {
133 document.getElementById("copywritingTone").value = copywritingTone;
134 }
135
136 // Update descriptions for loaded values
137 updateDescription("designStyle", designStyleDescriptions);
138 updateDescription("blockShapes", blockShapesDescriptions);
139 updateDescription("copywritingTone", copywritingToneDescriptions);
140 } catch (e) {
141 // Silent load error; user can still save
142 console.warn("AI Builder Settings: load failed", e);
143 // Still initialize description handlers even if load fails
144 updateDescription("designStyle", designStyleDescriptions);
145 updateDescription("blockShapes", blockShapesDescriptions);
146 updateDescription("copywritingTone", copywritingToneDescriptions);
147 }
148 }
149
150 form?.addEventListener("submit", async (e) => {
151 e.preventDefault();
152 try {
153 const jwt = await getJwtToken();
154 const body = {
155 primaryColor: document.getElementById("primaryColor").value,
156 secondaryColor: document.getElementById("secondaryColor").value,
157 siteName: document.getElementById("siteName").value.trim(),
158 siteDescription: document
159 .getElementById("siteDescription")
160 .value.trim(),
161 designStyle: document.getElementById("designStyle").value,
162 blockShapes: document.getElementById("blockShapes").value,
163 copywritingTone: document.getElementById("copywritingTone").value,
164 };
165
166 const res = await fetch(window.config.apiUrl + "/settings", {
167 method: "POST",
168 headers: {
169 "Content-Type": "application/json",
170 Authorization: `Bearer ${jwt}`,
171 },
172 body: JSON.stringify(body),
173 });
174 if (!res.ok) throw new Error("Save failed");
175 showToast("Settings saved");
176 } catch (err) {
177 showToast("Error saving settings", true);
178 }
179 });
180
181 loadSettings();
182 });
183