HEX
Server: Apache
System: Linux ecngx285.inmotionhosting.com 4.18.0-553.79.1.lve.el8.x86_64 #1 SMP Wed Oct 15 17:59:35 UTC 2025 x86_64
User: zeusxp5 (3862)
PHP: 8.3.30
Disabled: NONE
Upload Files
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>  
}