PluginProbe
Page Builder: Pagelayer – Drag and Drop website builder / 2.1.9
Page Builder: Pagelayer – Drag and Drop website builder v2.1.9
2.2.1 2.2.0 2.1.9 2.1.8 2.1.7 2.1.6 2.1.5 2.1.4 2.1.3 trunk 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5 0.9.6 0.9.7 0.9.8 0.9.9 1.0.0 1.0.2 1.0.3 1.0.4 1.0.5 All 129 releases
pagelayer / js / pagelayer-abilities.js

pagelayer-abilities.js in Page Builder: Pagelayer – Drag and Drop website builder 2.1.9, at js/pagelayer-abilities.js

354 lines 11.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 jQuery(document).ready(function($){
2
3 var dataEl = document.getElementById('pagelayer-abilities-json-data');
4 var data = dataEl ? JSON.parse(dataEl.textContent) : {};
5
6 var configData = {
7 siteUrl: data.siteUrl || '',
8 mcpServerUrl: data.mcpServerUrl || '',
9 username: data.username || '',
10 password: ''
11 };
12
13 var filePaths = {
14 claude: 'macOS: ~/Library/Application Support/Claude/claude_desktop_config.json\nWindows: %APPDATA%\\Claude\\claude_desktop_config.json',
15 claude_code: 'Terminal (Claude Code CLI)',
16 cursor: '.cursor/mcp.json in your project root',
17 grok_cli: 'Terminal (Grok CLI)',
18 vscode: '.vscode/mcp.json in your project root',
19 antigravity: '.antigravity/mcp.json in your project root',
20 opencode: 'opencode.json in your project root (or ~/.config/opencode/opencode.json for global)',
21 gemini_cli: '.gemini/settings.json in your project root'
22 };
23
24 var snippetTitles = {
25 claude: 'JSON Configuration',
26 claude_code: 'Terminal Command',
27 cursor: 'JSON Configuration',
28 grok_cli: 'Terminal Command',
29 vscode: 'JSON Configuration',
30 antigravity: 'JSON Configuration',
31 opencode: 'JSON Configuration',
32 gemini_cli: 'JSON Configuration'
33 };
34
35 var instructions = {
36 claude: [
37 'Open the file for your OS shown above (create it if it doesn\'t exist). On Linux, use the Claude Code CLI tab instead.',
38 'Paste the snippet above into the file.',
39 'Restart Claude Desktop to load the Pagelayer abilities.'
40 ],
41 claude_code: [
42 'Open a terminal in your project directory.',
43 'Run the command displayed above.',
44 'Verify the connection in your Claude Code CLI.'
45 ],
46 cursor: [
47 'Open your project in Cursor.',
48 'Create a file at `.cursor/mcp.json` in your project root if it doesn\'t exist.',
49 'Paste the configuration snippet into the file and save.'
50 ],
51 grok_cli: [
52 'Open a terminal in your project directory.',
53 'Run the command displayed above.',
54 'Verify the connection in your Grok CLI.'
55 ],
56 vscode: [
57 'Open your project in VS Code.',
58 'Create a file at `.vscode/mcp.json` in your project root if it doesn\'t exist.',
59 'Paste the configuration snippet into the file and save.'
60 ],
61 antigravity: [
62 'Open your project in your workspace.',
63 'Create a file at `.antigravity/mcp.json` in your project root if it doesn\'t exist.',
64 'Paste the configuration snippet into the file and save.'
65 ],
66 opencode: [
67 'Open your project.',
68 'Create a file at `opencode.json` in your project root (or `~/.config/opencode/opencode.json` for a global config) if it doesn\'t exist.',
69 'Paste the configuration snippet into the file and save.',
70 'Restart OpenCode to load the Pagelayer abilities.'
71 ],
72 gemini_cli: [
73 'Open your project.',
74 'Create a file at `.gemini/settings.json` in your project root if it doesn\'t exist.',
75 'Paste the configuration snippet into the file and save.'
76 ]
77 };
78
79 var activeClient = 'claude';
80
81 function updateSnippet() {
82 var snippet = '';
83 var serverName = 'pagelayer-mcp';
84 var password = configData.password || '<YOUR_APP_PASSWORD>';
85 var username = configData.username || '<your-username>';
86
87 var jsonConfig = {
88 mcpServers: {}
89 };
90 jsonConfig.mcpServers[serverName] = {
91 command: 'npx',
92 args: [
93 '-y',
94 '@automattic/mcp-wordpress-remote'
95 ],
96 env: {
97 WP_API_URL: configData.mcpServerUrl,
98 WP_API_USERNAME: username,
99 WP_API_PASSWORD: password
100 }
101 };
102
103 // For Antigravity and VS Code, let's output basic auth header and direct SSE connection.
104 if (activeClient === 'antigravity') {
105 var basic = '<base64-of-username:application-password>';
106 if (configData.password) {
107 try {
108 basic = window.btoa(username + ':' + configData.password);
109 } catch (e) {}
110 }
111 var agy = {
112 mcpServers: {}
113 };
114 agy.mcpServers[serverName] = {
115 serverUrl: configData.mcpServerUrl,
116 headers: { 'Authorization': 'Basic ' + basic }
117 };
118 snippet = JSON.stringify(agy, null, 2);
119 } else if (activeClient === 'claude_code') {
120 snippet = 'claude mcp add ' + serverName + ' -e WP_API_URL="' + configData.mcpServerUrl + '" -e WP_API_USERNAME="' + username + '" -e WP_API_PASSWORD="' + password + '" -- npx -y @automattic/mcp-wordpress-remote';
121 } else if (activeClient === 'grok_cli') {
122 snippet = 'grok mcp add ' + serverName + ' -e WP_API_URL="' + configData.mcpServerUrl + '" -e WP_API_USERNAME="' + username + '" -e WP_API_PASSWORD="' + password + '" -- npx -y @automattic/mcp-wordpress-remote';
123 } else if (activeClient === 'opencode') {
124 var basicOc = '<base64-of-username:application-password>';
125 if (configData.password) {
126 try {
127 basicOc = window.btoa(username + ':' + configData.password);
128 } catch (e) {}
129 }
130 var oc = {
131 '$schema': 'https://opencode.ai/config.json',
132 mcp: {}
133 };
134 oc.mcp[serverName] = {
135 type: 'remote',
136 url: configData.mcpServerUrl,
137 enabled: true,
138 headers: { 'Authorization': 'Basic ' + basicOc }
139 };
140 snippet = JSON.stringify(oc, null, 2);
141 } else {
142 snippet = JSON.stringify(jsonConfig, null, 2);
143 }
144
145 $('#pagelayer-ai-filepath').text(filePaths[activeClient] || '');
146 $('#pagelayer-ai-snippet-title').text(snippetTitles[activeClient] || 'Configuration Snippet');
147 $('#pagelayer-ai-snippet').text(snippet);
148
149 // Render instructions
150 var $inst = $('#pagelayer-ai-instructions-list').empty();
151 var steps = instructions[activeClient] || [];
152 $.each(steps, function(i, step){
153 $inst.append('<li>' + step + '</li>');
154 });
155 }
156
157 // Tab switching
158 $(document).on('click', '.pagelayer-ai-segmented-btn', function(){
159 $('.pagelayer-ai-segmented-btn').removeClass('active').attr('aria-selected', 'false');
160 $(this).addClass('active').attr('aria-selected', 'true');
161 activeClient = $(this).data('client');
162 updateSnippet();
163 });
164
165 // Accordion toggle
166 $(document).on('click', '.pagelayer-ai-row-toggle', function(){
167 var $row = $(this).closest('.pagelayer-ai-row');
168 var $body = $row.find('.pagelayer-ai-row-body');
169 var expanded = $(this).attr('aria-expanded') === 'true';
170
171 $(this).attr('aria-expanded', expanded ? 'false' : 'true');
172 if(expanded){
173 $body.slideUp(150);
174 } else {
175 $body.slideDown(150);
176 }
177 });
178
179 // Copy Snippet
180 $('#pagelayer-ai-copy-snippet-btn').on('click', function(){
181 var text = $('#pagelayer-ai-snippet').text();
182 navigator.clipboard.writeText(text).then(function() {
183 var $label = $('#pagelayer-ai-copy-snippet-btn-label');
184 var original = $label.text();
185 $('#pagelayer-ai-copy-snippet-btn').addClass('is-copied');
186 $label.text('Copied!');
187 setTimeout(function(){
188 $('#pagelayer-ai-copy-snippet-btn').removeClass('is-copied');
189 $label.text(original);
190 }, 2000);
191 });
192 });
193
194 // Generate App Password
195 $('#pagelayer-ai-pass-btn').on('click', function(){
196 var $btn = $(this);
197 if($btn.prop('disabled')) return;
198
199 $btn.text('Generating...').prop('disabled', true);
200 $.post(ajaxurl, {
201 action: 'pagelayer_mcp_generate_app_password',
202 nonce: data.nonce
203 }, function(res) {
204 if (res.success && res.data.password) {
205 configData.password = res.data.password;
206 configData.username = res.data.username || configData.username;
207
208 $('#pagelayer-ai-pass-container').slideDown(150);
209 $('.pagelayer-ai-username').val(configData.username);
210 $('#pagelayer-ai-pass-input').val(configData.password);
211
212 updateSnippet();
213 $btn.text('Generate a new Application Password').prop('disabled', false);
214
215 // Update row done style
216 $btn.closest('.pagelayer-ai-row').addClass('pagelayer-ai-row-done');
217 } else {
218 alert('Error generating password.');
219 $btn.text('Generate Application Password').prop('disabled', false);
220 }
221 });
222 });
223
224 // Activate/Install MCP Adapter
225 $('#pagelayer-ai-adapter-btn').on('click', function(){
226 var $btn = $(this);
227 var actionType = $btn.data('action');
228 if($btn.prop('disabled')) return;
229
230 $btn.text(actionType === 'install' ? 'Installing...' : 'Activating...').prop('disabled', true);
231 $('#pagelayer-ai-adapter-msg').text('').css('color', 'inherit');
232
233 $.post(ajaxurl, {
234 action: 'pagelayer_mcp_adapter_action',
235 type: actionType,
236 nonce: data.nonce
237 }, function(res) {
238 if (res.success) {
239 $('#pagelayer-ai-adapter-msg').text('Success! Reloading...').css('color', 'green');
240 setTimeout(function(){
241 location.reload();
242 }, 1200);
243 } else {
244 $('#pagelayer-ai-adapter-msg').text('Error: ' + (res.data || 'Failed')).css('color', 'red');
245 $btn.text(actionType === 'install' ? 'Install Adapter' : 'Activate Adapter').prop('disabled', false);
246 }
247 });
248 });
249
250 // Test connection
251 $('#pagelayer-ai-test-btn').on('click', function(){
252 var $btn = $(this);
253 var $result = $('#pagelayer-ai-test-result');
254 var $status = $('#pagelayer-ai-test-status');
255
256 if($btn.prop('disabled')) return;
257
258 var password = configData.password;
259 if(!password){
260 $result.show().css('color', '#ef4444').text('Please generate an Application Password first.');
261 return;
262 }
263
264 $btn.prop('disabled', true).text('Testing...');
265 $status.text('Testing...');
266 $result.hide().empty();
267
268 serverTestConnection();
269
270 function showTestResult(ok, message){
271 $result.show()
272 .removeClass('pagelayer-ai-test-result-ok pagelayer-ai-test-result-error')
273 .addClass(ok ? 'pagelayer-ai-test-result-ok' : 'pagelayer-ai-test-result-error')
274 .html((ok ? 'Success: ' : 'Failed: ') + message);
275
276 $status.text(ok ? 'Verified' : 'Failed');
277 $btn.closest('.pagelayer-ai-row').toggleClass('pagelayer-ai-row-done', !!ok);
278 $btn.closest('.pagelayer-ai-row').toggleClass('pagelayer-ai-row-progress', !ok);
279
280 persistTestStatus(ok, message);
281 }
282
283 function persistTestStatus(ok, message){
284 $.post(ajaxurl, {
285 action: 'pagelayer_mcp_save_test_status',
286 ok: ok ? 1 : 0,
287 message: message,
288 nonce: data.nonce
289 });
290 }
291
292 function serverTestConnection(){
293 $.post(ajaxurl, {
294 action: 'pagelayer_mcp_test_connection',
295 username: configData.username,
296 password: password,
297 nonce: data.nonce
298 }, function(res){
299 var msg = (res && res.data && res.data.message) ? res.data.message : res.data;
300 if(res.success){
301 showTestResult(true, msg || 'Connected successfully.');
302 } else {
303 showTestResult(false, msg || 'Connection test failed.');
304 }
305 }).fail(function(){
306 showTestResult(false, 'Could not reach the abilities endpoint. Check the site is reachable and try again.');
307 }).always(function(){
308 $btn.prop('disabled', false).text('Test connection');
309 });
310 }
311 });
312
313 // Save/update Pexels image search API key
314 $('#pagelayer-ai-pexels-save-btn').on('click', function(){
315 var $btn = $(this);
316 var $msg = $('#pagelayer-ai-pexels-msg');
317 var $status = $('#pagelayer-ai-pexels-status');
318 var key = $('#pagelayer-ai-pexels-key').val().trim();
319
320 if(!key){
321 $msg.css('color', '#ef4444').text('Enter an API key first.');
322 return;
323 }
324
325 $btn.prop('disabled', true).text('Saving...');
326 $msg.css('color', 'inherit').text('');
327
328 $.post(ajaxurl, {
329 action: 'pagelayer_mcp_save_image_api_key',
330 provider: 'pexels',
331 api_key: key,
332 nonce: data.nonce
333 }, function(res){
334 if(res.success){
335 $msg.css('color', 'green').text('Saved.');
336 $status.removeClass('pagelayer-ai-pill-neutral').addClass('pagelayer-ai-pill-success').text('Configured');
337 $btn.text('Update Key');
338 $('#pagelayer-ai-pexels-key').val('').attr('placeholder', '••••••••' + key.slice(-4));
339 } else {
340 $msg.css('color', '#ef4444').text((res.data && res.data.message) || 'Could not save key.');
341 $btn.text('Save Key');
342 }
343 }).fail(function(){
344 $msg.css('color', '#ef4444').text('Request failed. Please try again.');
345 $btn.text('Save Key');
346 }).always(function(){
347 $btn.prop('disabled', false);
348 });
349 });
350
351 // Initialize snippet
352 updateSnippet();
353 });
354