From 5da675ad76517c3d098600d8c1edd7ed52a02204 Mon Sep 17 00:00:00 2001 From: Allen Benny Date: Thu, 10 Oct 2024 16:50:29 +0530 Subject: [PATCH] Code --- package-lock.json | 10 +- package.json | 7 +- src/Installer/components/App/index.jsx | 45 ++++++- src/Installer/components/Modal/index.jsx | 114 ++++++++++++++++-- .../components/Modal/stylesheet.scss | 67 ++++++++-- src/Installer/styles/_wordpress.scss | 7 ++ src/Installer/styles/app.scss | 13 +- src/Scripts/dataAttrListener.js | 58 ++++----- 8 files changed, 256 insertions(+), 65 deletions(-) create mode 100644 src/Installer/styles/_wordpress.scss diff --git a/package-lock.json b/package-lock.json index 54e78b4..96d8a7a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,11 +9,12 @@ "version": "1.2.0-beta", "license": "GPL-2.0-or-later", "dependencies": { - "@wordpress/element": "^6.1.0" + "@wordpress/base-styles": "^4.49.0", + "@wordpress/element": "^6.9.0" }, "devDependencies": { - "@wordpress/scripts": "^26.10.0", - "webpack-merge": "^5.8.0" + "@wordpress/scripts": "^26.19.0", + "webpack-merge": "^5.10.0" } }, "node_modules/@ampproject/remapping": { @@ -4251,8 +4252,7 @@ "node_modules/@wordpress/base-styles": { "version": "4.49.0", "resolved": "https://registry.npmjs.org/@wordpress/base-styles/-/base-styles-4.49.0.tgz", - "integrity": "sha512-yFRYqNtd26ULZ0oAHhCu/IcaA0XHI3E7kRCKajZqUvyRQj7YprXnpD3o0/pnwvF6ZFTXzCX8pXHjUc2TIv97ig==", - "dev": true + "integrity": "sha512-yFRYqNtd26ULZ0oAHhCu/IcaA0XHI3E7kRCKajZqUvyRQj7YprXnpD3o0/pnwvF6ZFTXzCX8pXHjUc2TIv97ig==" }, "node_modules/@wordpress/browserslist-config": { "version": "5.41.0", diff --git a/package.json b/package.json index 960cdf0..999b736 100644 --- a/package.json +++ b/package.json @@ -9,11 +9,12 @@ "email": "micah.wood@newfold.com" }, "dependencies": { - "@wordpress/element": "^6.1.0" + "@wordpress/base-styles": "^4.49.0", + "@wordpress/element": "^6.9.0" }, "devDependencies": { - "@wordpress/scripts": "^26.10.0", - "webpack-merge": "^5.8.0" + "@wordpress/scripts": "^26.19.0", + "webpack-merge": "^5.10.0" }, "scripts": { "build": "wp-scripts build ./src/Installer/installer.js ./src/Scripts/dataAttrListener.js", diff --git a/src/Installer/components/App/index.jsx b/src/Installer/components/App/index.jsx index 64b0f7a..5b63a1e 100644 --- a/src/Installer/components/App/index.jsx +++ b/src/Installer/components/App/index.jsx @@ -1,9 +1,52 @@ +// External Imports +import { useState, useEffect } from '@wordpress/element'; + +// Internal Imports import Modal from '../Modal'; +import { INSTALLER_DIV } from '../../constants'; const App = () => { + const [ pluginName, setPluginName ] = useState(); + const [ pluginSlug, setPluginSlug ] = useState(); + const [ pluginURL, setPluginURL ] = useState(); + const [ pluginActivate, setPluginActivate ] = useState(); + + useEffect( () => { + // Add an event listener to get the changes + window.addEventListener( 'installerParamsSet', getData ); + + // Cleanup the event listener + return () => { + window.removeEventListener( 'installerParamsSet', getData ); + }; + }, [] ); + + const getData = () => { + const element = document.getElementById( INSTALLER_DIV ); + setPluginName( + element.getAttribute( 'nfd-installer-app__plugin--name' ) + ); + setPluginSlug( + element.getAttribute( 'nfd-installer-app__plugin--slug' ) + ); + setPluginURL( + element.getAttribute( 'nfd-installer-app__plugin--url' ) + ); + setPluginActivate( + element.getAttribute( 'nfd-installer-app__plugin--activate' ) + ); + }; + return (
- + { pluginSlug && ( + + ) }
); }; diff --git a/src/Installer/components/Modal/index.jsx b/src/Installer/components/Modal/index.jsx index b0311d6..a468c6d 100644 --- a/src/Installer/components/Modal/index.jsx +++ b/src/Installer/components/Modal/index.jsx @@ -1,10 +1,86 @@ -import { __ } from '@wordpress/i18n'; +// External Imports +import apiFetch from '@wordpress/api-fetch'; +import { __, sprintf } from '@wordpress/i18n'; +import { useRef, useState, useEffect } from '@wordpress/element'; + +// Internal Imports import { loadingInstaller } from '../../static/icons/index'; +import { + INSTALLER_DIV, + installerAPI, + pluginInstallHash, +} from '../../constants'; + +const Modal = ( { pluginName, pluginSlug, pluginURL, pluginActivate } ) => { + /** + * Represents the status of the plugin installation process. + * + * @typedef {('unknown'|'installing'|'failed'|'completed')} PluginStatus + * + * @property {'unknown'} unknown - The plugin installation has not started yet. + * @property {'installing'} installing - The plugin installation process has started. + * @property {'failed'} failed - The plugin installation process failed. + * @property {'completed'} completed - The plugin installation process is complete. + */ + const [ pluginStatus, setPluginStatus ] = useState( 'unknown' ); + const modalRef = useRef( null ); + + useEffect( () => { + installPremiumPlugin(); + const handleKeyDown = ( event ) => { + if ( event.key === 'Escape' ) { + closeModal(); + } + }; + + document.addEventListener( 'keydown', handleKeyDown ); + document.addEventListener( 'mousedown', handleClickOutside ); + + return () => { + document.removeEventListener( 'keydown', handleKeyDown ); + document.removeEventListener( 'mousedown', handleClickOutside ); + }; + }, [] ); + + const handleClickOutside = ( event ) => { + if ( modalRef.current && ! modalRef.current.contains( event.target ) ) { + closeModal(); + } + }; + + const closeModal = () => { + if ( 'failed' === pluginStatus || 'completed' === pluginStatus ) { + document.getElementById( INSTALLER_DIV ).style.display = 'none'; + } + }; + + const installPremiumPlugin = async () => { + setPluginStatus( 'installing' ); + try { + await apiFetch( { + url: installerAPI, + method: 'POST', + headers: { + 'X-NFD-INSTALLER': pluginInstallHash, + }, + data: { + activate: pluginActivate === 'true' ? true : false, + queue: false, + priority: 0, + premium: true, + plugin: pluginSlug, + }, + } ); + setPluginStatus( 'completed' ); + window.open( pluginURL, '_self' ); + } catch ( e ) { + setPluginStatus( 'failed' ); + } + }; -const Modal = ( {} ) => { return (
-
+
{ __( 'Hold on while we get things setup for you!', @@ -14,16 +90,32 @@ const Modal = ( {} ) => {
Man carrying items -
- { __( - 'Activating the plugin_name…', - 'wp-module-installer' - ) } -
-
+ { pluginStatus === 'installing' && ( + <> +
+ { sprintf( + /* translators: %s: Plugin Name */ + __( + 'Activating… %s', + 'wp-module-onboarding' + ), + pluginName + ) } +
+
+ + ) } + { pluginStatus === 'failed' && ( +
+ { __( + 'Sorry, there was an error installing and activating the plugin.', + 'wp-module-onboarding' + ) } +
+ ) }
diff --git a/src/Installer/components/Modal/stylesheet.scss b/src/Installer/components/Modal/stylesheet.scss index bfaf30c..e24e30a 100644 --- a/src/Installer/components/Modal/stylesheet.scss +++ b/src/Installer/components/Modal/stylesheet.scss @@ -8,21 +8,37 @@ position: fixed; align-items: center; justify-content: center; - background: rgba(0, 0, 0, 0.5); + background: rgba(255, 255, 255, 0.3); + + @media (max-width: #{ ($break-small) }) { + top: 30px; + } &__content { - width: 400px; - padding: 20px; + width: 40vw; + padding: 72px; position: relative; border-radius: 8px; text-align: center; background-color: #fff; - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.3); + + @media (max-width: #{ ($break-small) }) { + width: 80vw; + padding: 24px; + } &-heading { - font-size: 20px; - margin-bottom: 20px; color: #333; + font-size: 22px; + font-weight: 300; + margin-bottom: 60px; + letter-spacing: 1.1px; + + @media (max-width: #{ ($break-small) }) { + font-size: 18px; + margin-bottom: 20px; + } } &-section { @@ -32,24 +48,49 @@ } &-image { - width: 150px; - margin-bottom: 15px; + width: 200px; + margin-bottom: 30px; + + @media (max-width: #{ ($break-small) }) { + width: 100px; + } } &-subheading { - margin-bottom: 10px; - font-size: 16px; color: #333; + font-size: 16px; + margin-bottom: 30px; + + @media (max-width: #{ ($break-small) }) { + font-size: 14px; + margin-bottom: 10px; + } + } + + &-error { + color: red; + font-size: 16px; + + @media (max-width: #{ ($break-small) }) { + font-size: 14px; + } } } &__loader { + width: 30px; + height: 30px; + border-radius: 50%; border: 4px solid #f3f3f3; border-top: 4px solid #3498db; - border-radius: 50%; - width: 40px; - height: 40px; + border-right: 4px solid #3498db; + border-bottom: 4px solid #3498db; animation: spin 1s linear infinite; + + @media (max-width: #{ ($break-small) }) { + width: 20px; + height: 20px; + } } } diff --git a/src/Installer/styles/_wordpress.scss b/src/Installer/styles/_wordpress.scss new file mode 100644 index 0000000..e576c59 --- /dev/null +++ b/src/Installer/styles/_wordpress.scss @@ -0,0 +1,7 @@ +/** + * Initialize all WordPress Sass + * ----------------------------- + * @import @wordpress/base-styles + */ + +@import "@wordpress/base-styles/breakpoints"; diff --git a/src/Installer/styles/app.scss b/src/Installer/styles/app.scss index 8a6fd53..485cee7 100644 --- a/src/Installer/styles/app.scss +++ b/src/Installer/styles/app.scss @@ -1,3 +1,7 @@ +//Imports +@import "wordpress"; +@import "../components/Modal/stylesheet"; + * { margin: 0; padding: 0; @@ -5,9 +9,10 @@ } body { - font-family: Arial, sans-serif; - background-color: #f4f4f4; + font-family: "Open Sans", sans-serif; } -//Imports -@import "../components/Modal/stylesheet"; +#nfd-installer { + display: none; + transition: all 3s ease-in-out; +} diff --git a/src/Scripts/dataAttrListener.js b/src/Scripts/dataAttrListener.js index b190137..f527fef 100644 --- a/src/Scripts/dataAttrListener.js +++ b/src/Scripts/dataAttrListener.js @@ -1,27 +1,10 @@ +// External Imports import domReady from '@wordpress/dom-ready'; -import apiFetch from '@wordpress/api-fetch'; -import { pluginInstallHash, installerAPI } from '../Installer/constants'; +// Internal Imports +import { INSTALLER_DIV } from '../Installer/constants'; domReady( () => { - const installPremiumPlugin = async ( pluginSlug, activate ) => { - const data = await apiFetch( { - url: installerAPI, - method: 'POST', - headers: { - 'X-NFD-INSTALLER': pluginInstallHash, - }, - data: { - plugin: pluginSlug, - activate: activate === 'true' ? true : false, - queue: false, - priority: 0, - premium: true, - }, - } ); - return data; - }; - // function removeModal() { // // find the modal and remove if it exists // const modal = document.querySelector( '.nfd-installer' ); @@ -30,12 +13,26 @@ domReady( () => { // } // } - // function renderModal() { - // // create the installer div - // const modal = document.createElement( 'div' ); - // modal.classList.add( 'nfd-installer' ); - // document.body.appendChild( modal ); - // } + function renderModal( pluginName, pluginSlug, pluginURL, activate ) { + // create the installer div + document.getElementById( INSTALLER_DIV ).style.display = 'block'; + document + .getElementById( INSTALLER_DIV ) + .setAttribute( 'nfd-installer-app__plugin--name', pluginName ); + document + .getElementById( INSTALLER_DIV ) + .setAttribute( 'nfd-installer-app__plugin--slug', pluginSlug ); + document + .getElementById( INSTALLER_DIV ) + .setAttribute( 'nfd-installer-app__plugin--url', pluginURL ); + document + .getElementById( INSTALLER_DIV ) + .setAttribute( + 'nfd-installer-ap__plugin--activate', + activate === 'true' ? true : false + ); + window.dispatchEvent( new Event( 'installerParamsSet' ) ); + } const domObserver = new window.MutationObserver( ( mutationList ) => { for ( const mutation of mutationList ) { @@ -56,11 +53,16 @@ domReady( () => { 'data-nfd-installer-plugin-slug' ) !== null ) { - // renderModal(); - installPremiumPlugin( + renderModal( + this.getAttribute( + 'data-nfd-installer-plugin-name' + ), this.getAttribute( 'data-nfd-installer-plugin-slug' ), + this.getAttribute( + 'data-nfd-installer-plugin-url' + ), this.getAttribute( 'data-nfd-installer-plugin-activate' )