From afdac766505bf4c90738c4d41c32eff89b6b936a Mon Sep 17 00:00:00 2001 From: Nirbhay Singh <121793120+nirbhayel@users.noreply.github.com> Date: Thu, 7 Nov 2024 13:02:12 +0530 Subject: [PATCH] Setup base (#110) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial refactor commit * ✅ Added build and tests CI/CD * update: add src for admin settings * update: incorrect constant names * update: namespace * add: accessibility settings * update: webpack to output files inside a folder * update: build output folders * update: removed commented code * update: npm scripts * add: webpack config * add: hooks * update: move admin setting to the module folder * update: assets loading logic * update: settings variable * update: removed duplicate css import * Update modules/settings/assets/js/api/index.js Co-authored-by: VasylD --------- Co-authored-by: Ohad Co-authored-by: VasylD --- classes/utils/assets.php | 10 +- includes/manager.php | 1 + modules/settings/assets/css/style.css | 37 +++++ modules/settings/assets/js/admin.js | 26 ++++ .../assets/js/api/exceptions/APIError.js | 9 ++ modules/settings/assets/js/api/index.js | 132 ++++++++++++++++++ modules/settings/assets/js/app.js | 14 ++ .../js/components/admin-top-bar/index.js | 35 +++++ modules/settings/assets/js/constants/index.js | 2 + modules/settings/assets/js/hooks/index.js | 0 modules/settings/assets/js/hooks/use-auth.js | 33 +++++ modules/settings/assets/js/hooks/use-modal.js | 22 +++ .../assets/js/icons/elementor-logo.js | 21 +++ modules/settings/module.php | 97 +++++++++++++ webpack.config.js | 10 +- 15 files changed, 439 insertions(+), 10 deletions(-) create mode 100644 modules/settings/assets/css/style.css create mode 100644 modules/settings/assets/js/admin.js create mode 100644 modules/settings/assets/js/api/exceptions/APIError.js create mode 100644 modules/settings/assets/js/api/index.js create mode 100644 modules/settings/assets/js/app.js create mode 100644 modules/settings/assets/js/components/admin-top-bar/index.js create mode 100644 modules/settings/assets/js/constants/index.js create mode 100644 modules/settings/assets/js/hooks/index.js create mode 100644 modules/settings/assets/js/hooks/use-auth.js create mode 100644 modules/settings/assets/js/hooks/use-modal.js create mode 100644 modules/settings/assets/js/icons/elementor-logo.js create mode 100644 modules/settings/module.php diff --git a/classes/utils/assets.php b/classes/utils/assets.php index db3ac8ed..aa2e2cf5 100644 --- a/classes/utils/assets.php +++ b/classes/utils/assets.php @@ -60,7 +60,7 @@ public static function enqueue_styles( string $handle, string $style_name, array * @return string */ private static function get_assets_version( string $version = '' ) : string { - return empty( $version ) ? EA11Y_VERSION : $version; + return empty( $version ) ? \EA11Y_VERSION : $version; } /** @@ -95,7 +95,7 @@ private static function get_asset_version_and_suffix( string $version = '' ) : a * @return string */ private static function get_assets_path( string $asset_name, string $asset_type, string $suffix = '' ) : string { - return EA11Y_ASSETS_URL . '/build/' . $asset_name . $suffix . '.' . $asset_type; + return \EA11Y_ASSETS_URL . '/build/' . $asset_name . $suffix . '.' . $asset_type; } /** @@ -105,8 +105,8 @@ private static function get_assets_path( string $asset_name, string $asset_type, * @param bool $with_css */ public static function enqueue_app_assets( string $handle = '', bool $with_css = true ) : void { - $dir = EA11Y_ASSETS_PATH . 'build/'; - $url = EA11Y_ASSETS_URL . 'build/'; + $dir = \EA11Y_ASSETS_PATH . 'build/'; + $url = \EA11Y_ASSETS_URL . 'build/'; $script_asset_path = $dir . $handle . '.asset.php'; if ( ! file_exists( $script_asset_path ) ) { @@ -133,7 +133,7 @@ public static function enqueue_app_assets( string $handle = '', bool $with_css = } // enqueue css $css_file_name = 'style-' . $handle . '.css'; - $css_version = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? filemtime( $dir . $css_file_name ) : EA11Y_VERSION; + $css_version = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? filemtime( $dir . $css_file_name ) : \EA11Y_VERSION; wp_enqueue_style( $handle, $url . $css_file_name, diff --git a/includes/manager.php b/includes/manager.php index a8b29d6b..b8517576 100644 --- a/includes/manager.php +++ b/includes/manager.php @@ -17,6 +17,7 @@ final class Manager { public static function get_module_list(): array { return [ 'Legacy', + 'Settings' ]; } diff --git a/modules/settings/assets/css/style.css b/modules/settings/assets/css/style.css new file mode 100644 index 00000000..72965c8e --- /dev/null +++ b/modules/settings/assets/css/style.css @@ -0,0 +1,37 @@ +body { + background: #fff; +} +.wrap { + margin-top: 0; +} + +html:not([dir='rtl']) #ea11y-app { + margin-left: -20px; + background: white; +} + +html[dir='rtl'] #ea11y-app { + margin-right: -20px; + background: white; +} + +html:not([dir='rtl']) #ea11y-app-top-bar { + margin-left: -20px; + margin-bottom: 20px; +} + +html[dir='rtl'] #ea11y-app-top-bar { + margin-right: -20px; + margin-bottom: 20px; +} + +#ea11y-app * { + box-sizing: border-box; +} + +.ea11y-textfield .MuiInputBase-input { + height: 40px; + padding: 8px 12px; + box-shadow: none; + border-color: rgba(12, 13, 14, 0.23); +} \ No newline at end of file diff --git a/modules/settings/assets/js/admin.js b/modules/settings/assets/js/admin.js new file mode 100644 index 00000000..4e51e3ad --- /dev/null +++ b/modules/settings/assets/js/admin.js @@ -0,0 +1,26 @@ +import { ThemeProvider } from '@elementor/ui/styles'; +import { StrictMode, Fragment, createRoot } from '@wordpress/element'; +import App from './app'; +import AdminTopBar from './components/admin-top-bar'; + +const rootNode = document.getElementById( 'ea11y-app' ); +const topBarNode = document.getElementById( 'ea11y-app-top-bar' ); + +// Can't use the settings hook in the global scope so accessing directly +const isDevelopment = window?.ea11ySettingsData?.isDevelopment; +const AppWrapper = Boolean( isDevelopment ) ? StrictMode : Fragment; + +const root = createRoot( rootNode ); +const topBar = createRoot( topBarNode ); + +topBar.render( + + + , +); + +root.render( + + + , +); diff --git a/modules/settings/assets/js/api/exceptions/APIError.js b/modules/settings/assets/js/api/exceptions/APIError.js new file mode 100644 index 00000000..f13a1f1f --- /dev/null +++ b/modules/settings/assets/js/api/exceptions/APIError.js @@ -0,0 +1,9 @@ +class APIError extends Error { + constructor( message ) { + super( message ); + + this.name = 'APIError'; + } +} + +export default APIError; diff --git a/modules/settings/assets/js/api/index.js b/modules/settings/assets/js/api/index.js new file mode 100644 index 00000000..2648f103 --- /dev/null +++ b/modules/settings/assets/js/api/index.js @@ -0,0 +1,132 @@ +import apiFetch from '@wordpress/api-fetch'; +import { addQueryArgs } from '@wordpress/url'; +import APIError from './exceptions/APIError'; + +const wpV2Prefix = '/wp/v2'; +const v1Prefix = '/ea11y/v1'; + +class API { + static async request( { path, data, method = 'POST' } ) { + try { + if ( 'GET' === method && ! path.startsWith( wpV2Prefix ) ) { + path = addQueryArgs( path, { sb_time: new Date().getTime() } ); + } + + const response = await apiFetch( { + path, + method, + data, + } ); + + if ( path.startsWith( wpV2Prefix ) ) { + return response; + } + + if ( ! response.success ) { + throw new APIError( response.data.message ); + } + + return response.data; + } catch ( e ) { + if ( e instanceof APIError ) { + throw e; + } else { + throw new APIError( e.message ); + } + } + } + + static async initConnect( context = 'new' ) { + const data = { + wp_rest: window?.ea11ySettingsData?.wpRestNonce, + }; + + if ( 'update' === context ) { + data.update_redirect_uri = true; + } + + return API.request( { + method: 'POST', + path: `${ v1Prefix }/connect/authorize`, + data, + } ); + } + + static async clearSession() { + return API.request( { + method: 'POST', + path: `${ v1Prefix }/connect/deactivate_and_disconnect`, + data: { + wp_rest: window?.ea11ySettingsData?.wpRestNonce, + clear_session: true, + }, + } ); + } + + static async deactivateAndDisconnect() { + return API.request( { + method: 'POST', + path: `${ v1Prefix }/connect/deactivate_and_disconnect`, + data: { + wp_rest: window?.ea11ySettingsData?.wpRestNonce, + }, + } ); + } + + static async deactivate() { + return API.request( { + method: 'POST', + path: `${ v1Prefix }/connect/deactivate`, + data: { + wp_rest: window?.ea11ySettingsData?.wpRestNonce, + }, + } ); + } + + static async disconnect() { + return API.request( { + method: 'POST', + path: `${ v1Prefix }/connect/disconnect`, + data: { + wp_rest: window?.ea11ySettingsData?.wpRestNonce, + }, + } ); + } + + static async reconnect() { + return API.request( { + method: 'POST', + path: `${ v1Prefix }/connect/reconnect`, + data: { + wp_rest: window?.ea11ySettingsData?.wpRestNonce, + }, + } ); + } + + static async getSettings() { + return API.request( { + method: 'GET', + path: `${ wpV2Prefix }/settings`, + } ); + } + + static async updateSettings( data ) { + return API.request( { + method: 'PUT', + path: `${ wpV2Prefix }/settings`, + data, + } ); + } + + /** + * @return {Promise} {} + */ + static async getPluginSettings() { + return API.request( { + method: 'GET', + path: `${ v1Prefix }/settings/get-settings`, + } ); + } +} + +export default API; diff --git a/modules/settings/assets/js/app.js b/modules/settings/assets/js/app.js new file mode 100644 index 00000000..35d5bfb3 --- /dev/null +++ b/modules/settings/assets/js/app.js @@ -0,0 +1,14 @@ +import '../css/style.css'; +import DirectionProvider from '@elementor/ui/DirectionProvider'; +import { ThemeProvider } from '@elementor/ui/styles'; + +const App = () => { + return ( + + + + + ); +}; + +export default App; diff --git a/modules/settings/assets/js/components/admin-top-bar/index.js b/modules/settings/assets/js/components/admin-top-bar/index.js new file mode 100644 index 00000000..b789079b --- /dev/null +++ b/modules/settings/assets/js/components/admin-top-bar/index.js @@ -0,0 +1,35 @@ +import HelpIcon from '@elementor/icons/HelpIcon'; +import AppBar from '@elementor/ui/AppBar'; +import Grid from '@elementor/ui/Grid'; +import Link from '@elementor/ui/Link'; +import Toolbar from '@elementor/ui/Toolbar'; +import Typography from '@elementor/ui/Typography'; +import { __ } from '@wordpress/i18n'; +import { HELP_LINK } from '../../constants'; +import ElementorLogo from '../../icons/elementor-logo'; + +const AdminTopBar = () => { + return ( + + + + + + { __( 'Accessibility', 'pojo-accessibility' ) } + + + + + + + + + ); +}; + +export default AdminTopBar; diff --git a/modules/settings/assets/js/constants/index.js b/modules/settings/assets/js/constants/index.js new file mode 100644 index 00000000..c4169b45 --- /dev/null +++ b/modules/settings/assets/js/constants/index.js @@ -0,0 +1,2 @@ +export const HELP_LINK = 'https://go.elementor.com/'; +export const UPGRADE_LINK = 'https://go.elementor.com/'; diff --git a/modules/settings/assets/js/hooks/index.js b/modules/settings/assets/js/hooks/index.js new file mode 100644 index 00000000..e69de29b diff --git a/modules/settings/assets/js/hooks/use-auth.js b/modules/settings/assets/js/hooks/use-auth.js new file mode 100644 index 00000000..22ae0650 --- /dev/null +++ b/modules/settings/assets/js/hooks/use-auth.js @@ -0,0 +1,33 @@ +import API from '../api'; +import { UPGRADE_LINK } from '../constants'; +import { usePluginSettingsContext } from '../context/plugin-settings-context'; + +const useAuth = () => { + const { subscriptionId } = 123; + + const redirectToConnect = async () => { + const link = await getConnectLink(); + + window.open( link, '_self' ).focus(); + }; + + const getConnectLink = async () => { + return API.initConnect(); + }; + + const getUpgradeLink = () => { + const url = new URL( UPGRADE_LINK ); + + url.searchParams.append( 'subscription_id', subscriptionId ); + + return url.toString(); + }; + + return { + redirectToConnect, + getConnectLink, + getUpgradeLink, + }; +}; + +export default useAuth; diff --git a/modules/settings/assets/js/hooks/use-modal.js b/modules/settings/assets/js/hooks/use-modal.js new file mode 100644 index 00000000..6ae362b5 --- /dev/null +++ b/modules/settings/assets/js/hooks/use-modal.js @@ -0,0 +1,22 @@ +import { useState } from '@wordpress/element'; + +const useModal = ( defaultIsOpen = true ) => { + const [ isOpen, setIsOpen ] = useState( defaultIsOpen ); + + const open = () => { + setIsOpen( true ); + }; + + const close = () => { + setIsOpen( false ); + }; + + return { + isOpen, + setIsOpen, + open, + close, + }; +}; + +export default useModal; diff --git a/modules/settings/assets/js/icons/elementor-logo.js b/modules/settings/assets/js/icons/elementor-logo.js new file mode 100644 index 00000000..cc62ff43 --- /dev/null +++ b/modules/settings/assets/js/icons/elementor-logo.js @@ -0,0 +1,21 @@ +import SvgIcon from '@elementor/ui/SvgIcon'; + +const ElementorLogo = ( { size } ) => { + return ( + + + + + + + + + + + + ); +}; + +export default ElementorLogo; diff --git a/modules/settings/module.php b/modules/settings/module.php new file mode 100644 index 00000000..4cbd68f0 --- /dev/null +++ b/modules/settings/module.php @@ -0,0 +1,97 @@ +id ) { + return; + } + + ?> +
+ + +
+

+
+ +
+ wp_create_nonce( 'wp_rest' ) ] + ); + } + + /** + * Module constructor. + */ + public function __construct() { + $this->register_components(); + add_action( 'admin_menu', [ $this, 'register_page' ] ); + add_action( 'in_admin_header', [ $this, 'render_top_bar' ] ); + add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts' ] ); + } +} diff --git a/webpack.config.js b/webpack.config.js index 7216c1cf..b40d4aae 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -3,11 +3,11 @@ const defaultConfig = require( '@wordpress/scripts/config/webpack.config' ); // add your entry points here const entryPoints = { - // admin: path.resolve( - // process.cwd(), - // 'assets/dev/js', - // 'admin.js', - // ), + admin: path.resolve( + process.cwd(), + 'modules/settings/assets/js', + 'admin.js', + ), }; module.exports = {