File: /home/zeusxp5/chuair.org/wp-content/themes/lifttruck/inc/panel/src/panel/components/main/popup.jsx
import Popup from 'reactjs-popup'
import { __ , _x, _n } from '@wordpress/i18n'
import { Spinner } from "@wordpress/components"
// import doneimport from '../images/OK_result.png'
// import errorimport from '../images/NOK_result.png'
import { useState, useEffect } from "@wordpress/element"
export const PopupImport = ({ demo }) => {
const [isLoading, setIsLoading] = useState(false)
const [attachments, setAttachments] = useState(0)
const [importOption, setImportOption] = useState('complete_content')
const [messages, setMessages] = useState([])
const [responseMessages, setResponseMessages] = useState([])
const [err, setErr] = useState('')
// State variable to store the progress value
const [progressValue, setProgressValue] = useState(0)
const [plugins, setPlugins] = useState(Object.values(demo.plugins))
useEffect(() => {
setResponseMessages(prevMessages => [...prevMessages, ...messages])
const lastChild = document.querySelector('.response-messages > div:last-child')
if(lastChild) {
lastChild.scrollIntoView({ behavior: 'smooth', block: 'end' });
}
}, [messages])
useEffect(() => {
const lastChild = document.querySelector('.response-messages > div:last-child')
if(lastChild) {
lastChild.scrollIntoView({ behavior: 'smooth', block: 'end' });
}
}, [responseMessages])
// Render response messages
const renderResponseMessages = () => (
responseMessages.map((message, index) => <div key={index}>✔️ {message} </div> )
)
const handleClick = async () => {
setIsLoading(true)
setMessages([])
setErr('')
setProgressValue(0)
await installPlugins()
setProgressValue(prevProg => prevProg + 15)
setMessages(['Plugins has been installed successfully'])
switch(importOption) {
case 'complete_content':
await demoContent(1, 75)
await demoSliders(5)
await demoOptions(5)
break
case 'content':
await demoContent(1, 85)
break
case 'options':
await demoOptions(85)
break
case 'sliders':
await demoSliders(85)
break
case 'plugins':
setProgressValue(100)
setMessages(['Plugins has been installed successfully'])
break
}
setIsLoading(false)
}
const handleImportOption = e => {
setImportOption(e.target.value)
}
const demoContent = async (currentIndex, maxProgress) => {
let requestCount = 10
if (currentIndex > requestCount) {
// All requests are processed
return currentIndex
}
const xmlFile = (currentIndex >= 10 ) ? 'demo-file-' + currentIndex + '.xml' : 'demo-file-0' + currentIndex + '.xml'
let details = {
action: 'wd_data_import',
xml: xmlFile,
example: demo.slug,
import_attachments: attachments
}
const res = await sendAjaxRequests(details)
// set progress value
if(res.success) {
setProgressValue( prevProg => prevProg + Math.ceil(maxProgress/10) )
setMessages([`Content file ${currentIndex}/${requestCount} loaded`])
await demoContent(currentIndex + 1, maxProgress)
} else {
await demoContent(currentIndex, maxProgress)
//setErr(res.message)
}
}
const demoOptions = async (maxProgress) => {
let details = {
action: 'wd_import_options',
example: demo.slug
}
const res = await sendAjaxRequests(details)
if(res.success) {
const newMessages = maxProgress == 100 ? res.message : [...messages, `\n${res.message}`]
setMessages([newMessages])
setProgressValue(prevProg => prevProg + maxProgress)
} else {
setErr(res.message)
}
}
const demoSliders = async (maxProgress) => {
let details = {
action: 'wd_import_sliders',
example: demo.slug
}
const res = await sendAjaxRequests(details)
if(res.success) {
const newMessages = maxProgress == 100 ? res.message : [...messages, res.message]
setMessages([newMessages])
setProgressValue(prevProg => prevProg + maxProgress)
} else {
setErr(res.message)
}
}
const sendAjaxRequests = async (details) => {
var formBody = []
for (var property in details) {
var encodedKey = encodeURIComponent(property)
var encodedValue = encodeURIComponent(details[property])
formBody.push(encodedKey + "=" + encodedValue)
}
formBody = formBody.join("&")
const response = await fetch(ajaxurl, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: formBody
})
const result = await response.json()
return result
}
const installPlugins = async () => {
try {
for (const plugin of plugins) {
if (plugin.status !== 1) {
setPlugins((prevPlugins) =>
prevPlugins.map((p) => ({
...p,
status: p.slug === plugin.slug ? -1 : p.status,
}))
)
await installAndActivate(plugin)
setPlugins((prevPlugins) =>
prevPlugins.map((p) => ({
...p,
status: p.slug === plugin.slug ? 1 : p.status,
}))
)
}
}
// Check if all plugins are activated successfully
await checkAllPluginsActivated()
} catch (e) {
setErr(e.message)
console.error(e)
}
}
const installAndActivate = async (plugin) => {
if (plugin.status === 0) {
await installPlugin(plugin)
}
if (plugin.status !== 1) {
await activatePlugin(plugin)
await waitPluginActivation(plugin.mainClass) // Wait for plugin activation
}
}
const installPlugin = async (plugin) => {
const installRes = await fetch(
`${devia_options.rest_url}wd/v2/install-plugin`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-NONCE': devia_options.nonce,
},
body: JSON.stringify({
plugin_url: plugin.url,
}),
}
)
if (!installRes.ok) {
throw new Error('Failed to install plugin')
}
}
const activatePlugin = async (plugin) => {
const activateRes = await fetch(
`${devia_options.rest_url}wd/v2/activate-plugin`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-NONCE': devia_options.nonce,
},
body: JSON.stringify({
slug: plugin.slug,
}),
}
)
if (!activateRes.ok) {
throw new Error('Failed to activate plugin')
}
}
const waitPluginActivation = async (mainClass) => {
let maxAttempts = 10 // Number of attempts to check plugin activation
let attempt = 0
while (attempt < maxAttempts) {
const isPluginActive = await checkPluginStatus(mainClass)
if (isPluginActive) {
return // Plugin activated, exit the loop
}
await new Promise((resolve) => setTimeout(resolve, 1000)) // Wait 1 second before next attempt
attempt++
}
throw new Error('Failed to activate plugin within the specified time.')
}
const checkPluginStatus = async (mainClass) => {
const response = await fetch(
`${devia_options.rest_url}wd/v2/is-plugin-active`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': devia_options.nonce,
},
body: JSON.stringify({
mainClass,
}),
}
)
const data = await response.json()
return data.active
}
const Plugin = ({plugin}) => {
let status
switch (plugin.status) {
case 0:
status = __( 'Not Installed', devia_options.text_domain )
break
case 1:
status = __( '✔️ Active', devia_options.text_domain )
break
case 2:
status = __( 'Inactive', devia_options.text_domain )
break
case 3:
status = __( 'Update Available', devia_options.text_domain )
break
default:
status = __( '⟳ Installing...', devia_options.text_domain )
break
}
return <li id={`${plugin.slug}-plugin`}>
{plugin.name}
{<span className={plugin.status === -1 ? 'plugin-installing' : ''}>{status}</span>}
</li>
}
const checkAllPluginsActivated = async () => {
for (const plugin of plugins) {
const isActive = await checkPluginStatus(plugin.mainClass)
if (!isActive) {
setErr(`Plugin ${plugin.name} failed to activate. Retrying...`)
await activatePlugin(plugin) // Attempt to activate again
const retryActive = await checkPluginStatus(plugin.mainClass) // Check again
if (!retryActive) {
setErr(`Plugin ${plugin.name} failed to activate after retry.`)
} else {
setMessages(prevMessages => [...prevMessages, `Plugin ${plugin.name} activated successfully on retry.`])
}
}
}
// If all plugins are activated successfully
const allActive = plugins.every(plugin => checkPluginStatus(plugin.mainClass));
if (allActive) {
setMessages(prevMessages => [...prevMessages, 'All plugins activated successfully.'])
}
}
return <Popup trigger={<button> Import Demo </button>} modal nested >
{close => (
<div className="modal" style={{minWidth: "600px", minHeight: '400px', padding: '30px'}}>
<button className="close" onClick={close}>
<svg width="20" height="20" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 24L23.9006 2.0989" stroke="currentColor" stroke-width="3" stroke-linecap="round"/>
<path d="M2.09912 2L23.9998 23.9011" stroke="currentColor" stroke-width="3" stroke-linecap="round"/>
</svg>
</button>
<div className="content">
<div style={{display: 'flex', gap: '30px' }}>
<div>
<img src={demo.image} style={{boxShadow: '0px 0px 18px #00000017', borderRadius: '6px', maxWidth: '450px'}} />
</div>
<div style={{display: 'flex', flexDirection: 'column', minWidth: '376px', gap: '15px'}}>
<div>
<h3 style={{marginBlock: '0 0.5em'}}>{demo.title} Import </h3>
<hr style={{borderTop: '1px solid #ccc', margin: '0'}} />
</div>
<div className={'required-demo-plugins'}>
<h4> {__('These plugins are needed and will be installed.', devia_options.text_domain)}</h4>
<ul>
{ !!plugins && plugins.map( plugin => <Plugin plugin={plugin} /> ) }
</ul>
</div>
<div>
<label className="wd-field-description"> {__('Import Type :', devia_options.text_domain)} </label>
<select name="import_option" id="import_option" className="form-control wd-form-element" value={importOption} onChange={handleImportOption}>
<option disabled selected hidden > {__('Choose here ', devia_options.text_domain)} </option>
<option value="complete_content" > {__('All', devia_options.text_domain)} </option>
<option value="content"> {__('Content ', devia_options.text_domain)} </option>
<option value="plugins"> {__('Plugins ', devia_options.text_domain)} </option>
<option value="options"> {__('Options', devia_options.text_domain)} </option>
<option value="sliders"> {__('Sliders', devia_options.text_domain)} </option>
</select>
</div>
<div>
<input type="checkbox" value={attachments} className="wd-form-element" name="import_attachments" id="import_attachments" onClick={ e => setAttachments(attachments == 0 ? 1 : 0)} />
<label for="import_attachments" style={{paddingBottom: '4px', display: 'inline-block'}}> {__('Do you want to import media files?', devia_options.text_domain)}</label>
</div>
{progressValue < 100 && (
<>
<span style={{background: '#fffbc4bf', padding: '10px', borderBlock: '1px solid green'}}>
{__(' ⚠️ The import process may take some time. Please be patient.', devia_options.text_domain)}
</span>
<div>
<button onClick={handleClick} className="button button-primary" style={{padding: '2px 20px', background: '#1185e3'}}>Import</button>
</div>
</>
)}
<div>
<progress id="progressbar" value={progressValue} max={100} style={{width: '100%', height: '20px'}} />
<div className="progress-value">{progressValue > 100 ? 100 : progressValue}%</div>
</div>
{ !!messages.length && <div className="response-messages"> { renderResponseMessages() } </div> }
{ isLoading && <div id="loading_gif" style={{ display: 'flex', alignItems: 'center', justifyContent: 'start'}} >
<Spinner style={{ margin: '0 7px 0 0'}}/>
<h2 style={{ margin: '0'}}>Loading...</h2>
</div>}
{ err && <div className="error" style={{ margin: 0, maxWidth: `50ch` }}>
{err}
</div> }
{progressValue >= 100 && (
<div style={{ display: 'flex', alignItems: 'center', gap: '1em' }}>
<a href={ devia_options.home_link } target="_blank" class="button button-primary" style={{ padding: '2px 20px', background: '#1185e3' }}>View your website</a> or
<a href="#/theme-options">Go to theme options</a>
</div>
)}
</div>
</div>
</div>
</div>
)}
</Popup>
}