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 = {