PluginProbe ʕ •ᴥ•ʔ
Flex Import / 2.2
Flex Import v2.2
2.9 trunk 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8
flex-import / assets / js / template-admin.js
flex-import / assets / js Last commit date
admin-script.js 11 months ago dashboard-posts.js 11 months ago front-script.js 11 months ago jquery.notify.min.js 11 months ago license_script.js 11 months ago plugin-admin.js 11 months ago template-admin.js 11 months ago
template-admin.js
508 lines
1 document.addEventListener('DOMContentLoaded', function () {
2 const templatesApiEndpoint = fleximp_template_ajax_object.apiEndpoint;
3 let isFetchingTemplates = false;
4 let isFetchingCategories = false;
5
6 // Fetch Templates
7 function fetchTemplates() {
8 if (isFetchingTemplates) return;
9 isFetchingTemplates = true;
10
11 fetch(templatesApiEndpoint, {
12 method: 'POST',
13 headers: {
14 'Content-Type': 'application/json'
15 },
16 body: JSON.stringify({
17 action: 'getTemplates'
18 })
19 })
20 .then(response => response.json())
21 .then(data => {
22 if (data.success && data.data && Array.isArray(data.data.data.posts)) {
23 displayTemplates(data.data.data.posts);
24 } else {
25 console.error('Error fetching templates:', data);
26 }
27 })
28 .catch(error => {
29 console.error('Error:', error);
30 })
31 .finally(() => {
32 isFetchingTemplates = false;
33 });
34 }
35
36 // Fetch Categories
37 function fetchCategories() {
38 if (isFetchingCategories) return;
39 isFetchingCategories = true;
40
41 fetch(templatesApiEndpoint, {
42 method: 'POST',
43 headers: {
44 'Content-Type': 'application/json'
45 },
46 body: JSON.stringify({
47 action: 'getCategories'
48 })
49 })
50 .then(response => response.json())
51 .then(data => {
52 if (data.success && Array.isArray(data.data
53 .data)) {
54 displayCategories(data.data.data);
55 } else {
56 console.error('Error fetching categories:', data);
57 }
58 })
59 .catch(error => {
60 console.error('Error:', error);
61 })
62 .finally(() => {
63 isFetchingCategories = false;
64 });
65 }
66
67 // Display Templates
68 function displayTemplates(templates) {
69 const templatesListContainer = document.getElementById('templates-list');
70 templatesListContainer.innerHTML = '';
71
72 templates.forEach(template => {
73 const templateSlug = template.title.toLowerCase().replace(/ /g, '-');
74 const demoUrl = template.metafields?.demo_url || '#';
75 const selectedPlugins = template.metafields?.selected_plugins || [];
76 const jsonPath = template.metafields?.json_path || '';
77 const templateMainImage = template.metafields?.template_main_image || '';
78 const templateMobileImage = template.metafields?.template_mobile_image || '';
79 const templateResponsiveImage = template.metafields?.template_responsive_image || '';
80 const contentPath = template.metafields?.content_path || '';
81 const textDomain = template.template_domain || '';
82 const templateCss = template.metafields?.template_css_path || '';
83 const templateJs = template.metafields?.template_js_path || '';
84 const templatePhp = template.metafields?.template_php_path || '';
85 const isPremium = template.metafields?.free_pro === 'Pro';
86 // const isUserPremium = fleximp_template_ajax_object.isPremiumUser === true || fleximp_template_ajax_object.isPremiumUser === '1';
87 const isUserPremium = fleximp_template_ajax_object.isPremiumUser;
88 const isImported = fleximp_template_ajax_object.imported_template;
89 const fleximpCurrentTextDomain = fleximp_template_ajax_object.fleximp_current_text_domain;
90 let buttonHTML = '';
91 // new add
92 if (isPremium && !isUserPremium) {
93 buttonHTML = `
94 <a href="https://www.flextheme.net/products/flex-pro-wordpress-theme" target="_blank" class="btn flex-template-buttons get-pro-btn">
95 <svg viewBox="0 0 64 64" width="512" xmlns="http://www.w3.org/2000/svg" id="fi_3777733"><g id="Icon"><path d="m59.45 19.31a1 1 0 0 0 -1.15.18l-12.08 11.89-13.35-23.17a1.06 1.06 0 0 0 -1.74 0l-13.35 23.17-12.08-11.89a1 1 0 0 0 -1.7.86l4 26.8a1 1 0 0 0 1 .85h46a1 1 0 0 0 1-.85l4-26.8a1 1 0 0 0 -.55-1.04z"></path></g></svg>
96 Get Pro
97 </a>`;
98 } else {
99 if (isImported === textDomain) {
100 // Show Uninstall Button
101 buttonHTML = `
102 <button
103 class="btn flex-template-buttons uninstall-btn"
104 data-template="${templateSlug}" data-title="${template.title}"
105 data-plugins='${JSON.stringify(selectedPlugins)}'
106 data-json-path="${jsonPath}"
107 data-template-main-image="${templateMainImage}"
108 data-template-mobile-image="${templateMobileImage}"
109 data-template-responsive-image="${templateResponsiveImage}"
110 data-content-path="${contentPath}"
111 data-text-domain="${textDomain}"
112 data-template-css="${templateCss}"
113 data-template-js="${templateJs}"
114 data-template-php="${templatePhp}">
115 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="15" height="15"><path d="M135.2 17.7C140.4 7.1 150.9 0 162.7 0h186.7c11.8 0 22.3 7.1 27.5 17.7L416 64h80c17.7 0 32 14.3 32 32s-14.3 32-32 32h-16v304c0 44.2-35.8 80-80 80H160c-44.2 0-80-35.8-80-80V128H64c-17.7 0-32-14.3-32-32s14.3-32 32-32h80l23.2-46.3zM160 128v304h192V128H160z"/></svg>
116 Uninstall
117 </button>
118 `;
119 } else if (fleximp_template_ajax_object.isElementorActive === '1') {
120 let isDisabled = fleximpCurrentTextDomain != textDomain && fleximpCurrentTextDomain != '' ? 'disabled title="first uninstall imported template"' : '';
121 buttonHTML = `
122 <button
123 class="btn flex-unique-import-button flex-template-buttons import-btn"
124 ${isDisabled}
125 data-template="${templateSlug}"
126 data-title="${template.title}"
127 data-plugins='${JSON.stringify(selectedPlugins)}'
128 data-json-path="${jsonPath}"
129 data-template-main-image="${templateMainImage}"
130 data-template-mobile-image="${templateMobileImage}"
131 data-template-responsive-image="${templateResponsiveImage}"
132 data-content-path="${contentPath}"
133 data-text-domain="${textDomain}"
134 data-template-css="${templateCss}"
135 data-template-js="${templateJs}"
136 data-template-php="${templatePhp}">
137 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M128 64c0-35.3 28.7-64 64-64L352 0l0 128c0 17.7 14.3 32 32 32l128 0 0 288c0 35.3-28.7 64-64 64l-256 0c-35.3 0-64-28.7-64-64l0-112 174.1 0-39 39c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l80-80c9.4-9.4 9.4-24.6 0-33.9l-80-80c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l39 39L128 288l0-224zm0 224l0 48L24 336c-13.3 0-24-10.7-24-24s10.7-24 24-24l104 0zM512 128l-128 0L384 0 512 128z"/></svg>
138 Import
139 </button>
140 `;
141 } else {
142 // Elementor is NOT active, show disabled message
143 buttonHTML = `
144 <button class="btn flex-template-buttons btn-disabled" disabled title="Please install and activate Elementor to import templates.">
145 Elementor Required
146 </button>
147 `;
148 }
149 }
150
151 // end
152 const templateHTML = `
153 <div class="template-item grid-item" style="position: relative;">
154 <div class="flex-imp-temp-inner-box"><img src="${templateMainImage}" alt="${template.title}" style=""></div>
155
156 ${isPremium ? `
157 <div class="premium-badge" style="
158 position: absolute;
159 top: 10px;
160 left: 10px;
161 background-color: rgba(0, 0, 0, 0.6);
162 color: #fff;
163 padding: 4px 8px;
164 font-size: 12px;
165 border-radius: 4px;
166 display: flex;
167 align-items: center;
168 gap: 5px;">
169 <svg xmlns="http://www.w3.org/2000/svg" height="14" width="12" viewBox="0 0 448 512" fill="currentColor">
170 <path d="..."/>
171 </svg> Premium
172 </div>` : ''
173 }
174 <div class="fleximp-temp-buttons widgets-btn">
175 <div class="buttons widgets-btn">
176 <div class="btn-title">
177 <p class="template-title">${template.title}</p>
178 </div>
179 <div class="d-flex flex-gap-div">
180 <a href="${demoUrl}" target="_blank" class="btn flex-template-buttons">
181 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"> <path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM144 256a144 144 0 1 1 288 0 144 144 0 1 1 -288 0zm144-64c0 35.3-28.7 64-64 64c-7.1 0-13.9-1.2-20.3-3.3c-5.5-1.8-11.9 1.6-11.7 7.4c.3 6.9 1.3 13.8 3.2 20.7c13.7 51.2 66.4 81.6 117.6 67.9s81.6-66.4 67.9-117.6c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3z"></path> </svg>Demo</a>
182 </a>
183 ${buttonHTML}
184 </div>
185 </div>
186 </div>
187 </div>
188 `;
189
190 templatesListContainer.innerHTML += templateHTML;
191 });
192
193
194
195 }
196
197 // Display Categories
198 function displayCategories(categories) {
199 const categoriesListContainer = document.querySelector('#categories-list ul');
200 categoriesListContainer.innerHTML = '';
201 categories.forEach(category => {
202 const categoryHTML = `<li>${category.name}</li>`;
203 categoriesListContainer.innerHTML += categoryHTML;
204 });
205 }
206
207 // for loader
208 function updateProgress(percent, message) {
209 const progressBar = document.getElementById('import-progress-bar');
210 const progressText = document.getElementById('import-progress-text');
211 if (progressBar && progressText) {
212 progressBar.style.width = percent + '%';
213 progressText.textContent = `${message} (${percent}%)`;
214 }
215 }
216 //end
217
218 document.addEventListener('click', function (event) {
219 if (event.target.classList.contains('flex-unique-import-button')) {
220
221 const templateTitle = event.target.getAttribute('data-title');
222 const templateMobileImage = event.target.getAttribute('data-template-mobile-image');
223
224
225 const textDomain = event.target.getAttribute('data-text-domain');
226 const jsonPath = event.target.getAttribute('data-json-path');
227 const contentPath = event.target.getAttribute('data-content-path');
228 const templateCss = event.target.getAttribute('data-template-css');
229 const templateJs = event.target.getAttribute('data-template-js');
230 const templatePhp = event.target.getAttribute('data-template-php');
231 const plugins = event.target.getAttribute('data-plugins');
232 const templateResponsiveImage = event.target.getAttribute('data-template-responsive-image');
233
234 // Check if modal elements exist
235 const modal = document.getElementById('import-modal');
236 const modalTitle = document.getElementById('modal-template-title');
237 // For Step 2
238 const modalMobileTitle = document.getElementById('modal-template-mobile-title'); // Mobile title in Step 2
239 const modalMobileImage = document.getElementById('modal-template-mobile-image'); // Mobile image in Step 2
240 //new one
241 const modalTemplateImage = document.getElementById('modal-template-responsive-image'); // last one img
242 if (modal && modalTitle && modalMobileTitle && modalMobileImage && modalTemplateImage) {
243 // Set Step 1 Data
244 modalTitle.textContent = `${templateTitle}`;
245 // Set Step 2 Data (Mobile Image and Title)
246 modalMobileTitle.textContent = `${templateTitle}`; // Set title
247 modalMobileImage.src = templateMobileImage; // Set mobile img
248 //new
249 modalTemplateImage.src = templateResponsiveImage;
250 modal.style.display = 'block';
251 } else {
252 console.error('Modal or modal title/image element is missing in the DOM.');
253 }
254 // Now set up confirm import button click
255 const confirmBtn = document.getElementById('flex-confirm-import');
256 if (confirmBtn) {
257 // Remove existing listener if needed, or use once:true
258 confirmBtn.addEventListener('click', function () {
259 const data = {
260 textDomain: textDomain,
261 jsonPath: jsonPath,
262 contentPath: contentPath,
263 templateCss: templateCss,
264 templateJs: templateJs,
265 templatePhp: templatePhp,
266 plugins: plugins,
267 templateResponsiveImage: templateResponsiveImage,
268 };
269
270 sessionStorage.setItem('fleximp_import_data', JSON.stringify(data));
271
272 if (!textDomain) {
273 alert('Text domain not found.');
274 return;
275 }
276
277 // // Save text domain
278 fetch(fleximp_ajax_object.ajax_url, {
279 method: 'POST',
280 headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
281 body: new URLSearchParams({
282 action: 'fleximp_set_text_domain',
283 text_domain: textDomain,
284 template_php: templatePhp
285 })
286 })
287 .then(res => res.json())
288 .then(response => {
289 if (response.success) {
290 sessionStorage.setItem('fleximp_auto_continue', '1');
291 location.reload();
292 } else {
293 alert('Failed to update text domain.');
294 }
295 });
296 }, { once: true });
297 }
298 }
299 });
300
301 fetchCategories();
302 fetchTemplates();
303
304 // for uninstall
305 jQuery(document).on('click', '.uninstall-btn', function () {
306 const button = jQuery(this);
307 const templateSlug = button.data('template');
308 const textDomain = button.data('text-domain');
309 if (!confirm('Are you sure you want to uninstall this template and remove all related data?')) {
310 return;
311 }
312
313 jQuery.ajax({
314 url: ajaxurl,
315 type: 'POST',
316 data: {
317 action: 'fleximp_uninstall_template',
318 template_slug: templateSlug,
319 text_domain: textDomain,
320 },
321 success: function (response) {
322 if (response.success) {
323 alert(response.data.message);
324 location.reload();
325 } else {
326 alert('Error: ' + response.data.message);
327 }
328 },
329 });
330 });
331 });
332
333
334 window.addEventListener('DOMContentLoaded', function () {
335
336 if (sessionStorage.getItem('fleximp_auto_continue') === '1') {
337 const templatesTab = document.querySelector('.nav-link[href="#templates"]');
338 if (templatesTab) templatesTab.classList.add('active');
339 const templatesPane = document.querySelector('#templates');
340 if (templatesPane) templatesPane.classList.add('active', 'show');
341 const templatesTab1 = document.querySelector('.nav-link[href="#dashboard"]');
342 if (templatesTab1) templatesTab1.classList.remove('active');
343 const templatesPane1 = document.querySelector('#dashboard');
344 if (templatesPane1) templatesPane1.classList.remove('active', 'show');
345
346 sessionStorage.removeItem('fleximp_auto_continue');
347 const importData = sessionStorage.getItem('fleximp_import_data');
348 if (!importData) return;
349
350 const {
351 textDomain,
352 jsonPath,
353 contentPath,
354 templateCss,
355 templateJs,
356 templatePhp,
357 plugins,
358 templateResponsiveImage
359 } = JSON.parse(importData);
360
361 const modalTemplateImage = document.getElementById('modal-template-responsive-image');
362 modalTemplateImage.src = templateResponsiveImage;
363
364 const flexgetattributebutton = document.createElement('button');
365 flexgetattributebutton.classList.add('flex-unique-import-button');
366 flexgetattributebutton.setAttribute('data-text-domain', textDomain);
367 flexgetattributebutton.setAttribute('data-json-path', jsonPath);
368 flexgetattributebutton.setAttribute('data-content-path', contentPath);
369 flexgetattributebutton.setAttribute('data-template-css', templateCss);
370 flexgetattributebutton.setAttribute('data-template-js', templateJs);
371 flexgetattributebutton.setAttribute('data-template-php', templatePhp);
372 flexgetattributebutton.setAttribute('data-plugins', plugins);
373
374 document.body.appendChild(flexgetattributebutton);
375 runImportProcess(); // continue import
376 }
377 });
378
379 function updateProgress(percent, message) {
380 const progressBar = document.getElementById('import-progress-bar');
381 const progressText = document.getElementById('import-progress-text');
382 if (progressBar && progressText) {
383 progressBar.style.width = percent + '%';
384 progressText.textContent = `${message} (${percent}%)`;
385 }
386 }
387
388 async function runImportProcess() {
389 document.getElementById('step-confirm-import').style.display = 'none';
390 document.getElementById('step-plugins').style.display = 'block';
391 document.getElementById('import-modal').style.display = 'block';
392
393 const pluginLoader = document.getElementById('plugin-loader');
394 const contentLoader = document.getElementById('content-loader');
395 if (pluginLoader) pluginLoader.style.display = 'inline-block';
396 if (contentLoader) contentLoader.style.display = 'none';
397
398 const importBtn = document.querySelector('.flex-unique-import-button');
399 const selectedPlugins = JSON.parse(importBtn.getAttribute('data-plugins'));
400 const jsonPath = importBtn.getAttribute('data-json-path');
401 const contentPath = importBtn.getAttribute('data-content-path');
402 const textDomain = importBtn.getAttribute('data-text-domain');
403 const templateCss = importBtn.getAttribute('data-template-css');
404 const templateJs = importBtn.getAttribute('data-template-js');
405 const templatePhp = importBtn.getAttribute('data-template-php');
406
407 const installPlugin = (plugin) => {
408 return new Promise((resolve) => {
409 jQuery.ajax({
410 url: fleximp_ajax_object.ajax_url,
411 method: 'POST',
412 data: {
413 action: 'fleximp_checked_install_plugin',
414 plugin_slug: plugin.text_domain,
415 plugin_name: plugin.name,
416 plugin_main_file: plugin.main_file
417 },
418 success: function () {
419 console.log(`Plugin ${plugin.name} installed successfully.`);
420 updateProgress(33, `Installed plugin: ${plugin.name}`);
421 },
422 error: function (xhr, status, error) {
423 console.error(`Error installing plugin ${plugin.name}: ${error}`);
424 },
425 complete: function () {
426 resolve();
427 }
428 });
429 });
430 };
431
432 const selectedPluginsObj = Object.values(selectedPlugins);
433
434 // Install plugins one by one
435 for (let i = 0; i < selectedPluginsObj.length; i++) {
436 await installPlugin(selectedPluginsObj[i]);
437 }
438
439 if (pluginLoader) pluginLoader.classList.add('loader-success');
440
441 const innerPagesLoader = document.getElementById('inner-pages-loader');
442 if (innerPagesLoader) innerPagesLoader.style.display = 'inline-block';
443
444 // Step 2: Import Inner Pages
445 await new Promise((resolve) => {
446 jQuery.ajax({
447 url: fleximp_ajax_object.ajax_url,
448 method: 'POST',
449 data: {
450 action: 'fleximp_import_inner_pages_data',
451 nonce: fleximp_ajax_object.nonce,
452 content_path: contentPath,
453 text_domain: textDomain,
454 template_css: templateCss,
455 template_js: templateJs,
456 template_php: templatePhp
457 },
458 success: function () {
459 console.log('Inner pages data imported successfully.');
460 if (innerPagesLoader) innerPagesLoader.classList.add('loader-success');
461 updateProgress(75, 'Importing inner pages success');
462 },
463 error: function (xhr, status, error) {
464 console.error(`Error importing inner pages data: ${error}`);
465 if (innerPagesLoader) innerPagesLoader.classList.add('loader-error');
466 },
467 complete: resolve
468 });
469 });
470
471 // Step 3: Import Demo Content
472 if (contentLoader) contentLoader.style.display = 'inline-block';
473 contentLoader.classList.add('loader-active');
474
475 await new Promise((resolve) => {
476 jQuery.ajax({
477 url: fleximp_ajax_object.ajax_url,
478 method: 'POST',
479 data: {
480 action: 'fleximp_import_demo_content',
481 text_domain: textDomain,
482 json_path: jsonPath
483 },
484 success: function () {
485 console.log('Content imported successfully.');
486 updateProgress(100, 'Import success');
487 },
488 error: function (xhr, status, error) {
489 console.error(`Error importing content: ${error}`);
490 },
491 complete: resolve
492 });
493 });
494
495 if (contentLoader) {
496 contentLoader.classList.remove('loader-active');
497 contentLoader.classList.add('loader-success');
498 }
499
500 const continueButton = document.getElementById('flex-continue-install');
501 if (continueButton) continueButton.style.display = 'inline-block';
502
503 document.getElementById('step-plugins').style.display = 'none';
504 document.getElementById('step-done').style.display = 'block';
505
506 setTimeout(() => location.reload(), 8000);
507 }
508