Skip to content

Commit 7346431

Browse files
committed
Add dashboard button to the design studio
1 parent 1f01600 commit 7346431

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/* global MutationObserver */
2+
import { createPortal, useEffect, useState } from '@wordpress/element';
3+
import { Button } from '@wordpress/components';
4+
import { __ } from '@wordpress/i18n';
5+
import { wordpress } from '@wordpress/icons';
6+
7+
/**
8+
* A button to exit the user to the plugin dashboard.
9+
* The button is injected before the save button of the site editor.
10+
* @return {React.ReactNode} Dashboard button component portal.
11+
*/
12+
const DashboardButton = () => {
13+
const [ dashboardButtonContainer, setDashboardButtonContainer ] = useState( null );
14+
15+
useEffect( () => {
16+
/**
17+
* Create and inject the dashboard button container into the site editor header actions.
18+
* @return {void}
19+
*/
20+
const createDashboardButtonContainer = () => {
21+
const siteEditor = document.querySelector( '#site-editor' );
22+
if ( ! siteEditor ) {
23+
return;
24+
}
25+
26+
const siteEditorHeaderActions = siteEditor.querySelector( '.editor-header .editor-header__settings' );
27+
if ( ! siteEditorHeaderActions ) {
28+
return;
29+
}
30+
31+
// Prevent duplicates if the container already exists.
32+
const existingContainer = siteEditorHeaderActions.querySelector( '.nfd-design-studio-dashboard-button' );
33+
if ( existingContainer ) {
34+
setDashboardButtonContainer( existingContainer );
35+
return;
36+
}
37+
38+
// Create the container element.
39+
const dashboardButtonContainerElement = document.createElement( 'div' );
40+
dashboardButtonContainerElement.className = 'nfd-design-studio-dashboard-button';
41+
// Insert before the save button
42+
const siteEditorSaveButton = siteEditorHeaderActions.querySelector( '.editor-post-publish-button__button' );
43+
if ( siteEditorSaveButton && siteEditorSaveButton.parentNode ) {
44+
siteEditorSaveButton.parentNode.insertBefore( dashboardButtonContainerElement, siteEditorSaveButton );
45+
} else {
46+
siteEditorHeaderActions.appendChild( dashboardButtonContainerElement );
47+
}
48+
49+
setDashboardButtonContainer( dashboardButtonContainerElement );
50+
};
51+
createDashboardButtonContainer();
52+
53+
// Observer: watch for DOM changes and ensure dashboard button presence.
54+
const observer = new MutationObserver( () => {
55+
// Use a timeout to debounce rapid DOM changes.
56+
setTimeout( () => {
57+
if ( ! dashboardButtonContainer ) {
58+
createDashboardButtonContainer();
59+
}
60+
}, 100 );
61+
} );
62+
observer.observe( document.body, {
63+
childList: true,
64+
subtree: true,
65+
} );
66+
67+
// On unmount: remove the container and disconnect the observer.
68+
return () => {
69+
observer.disconnect();
70+
if ( dashboardButtonContainer && dashboardButtonContainer.parentNode ) {
71+
dashboardButtonContainer.parentNode.removeChild( dashboardButtonContainer );
72+
}
73+
};
74+
// eslint-disable-next-line react-hooks/exhaustive-deps
75+
}, [] );
76+
77+
const getPluginDashboardPageUrl = () => {
78+
// Get the admin URL from the NewfoldRuntime.
79+
const adminUrl = window.NewfoldRuntime?.admin_url;
80+
if ( adminUrl ) {
81+
const brand = window.NewfoldRuntime?.context?.brand?.name;
82+
if ( brand ) {
83+
return `${ adminUrl }admin.php?page=${ brand }&referrer=nfd-design-studio`;
84+
}
85+
86+
return adminUrl;
87+
}
88+
89+
// Fallback to the default WordPress admin URL.
90+
return '/wp-admin/';
91+
};
92+
93+
const dashboardButtonComponent = (
94+
<Button
95+
variant="secondary"
96+
size="compact"
97+
icon={ wordpress }
98+
disabled={ false }
99+
href={ getPluginDashboardPageUrl() }
100+
className="nfd-design-studio-dashboard-button"
101+
>
102+
{ __( 'Dashboard' ) }
103+
</Button>
104+
);
105+
106+
return dashboardButtonContainer ? createPortal( dashboardButtonComponent, dashboardButtonContainer ) : null;
107+
};
108+
109+
export default DashboardButton;

src/DesignStudio/components/DesignStudio.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import ScreenColors from './Screens/ScreenColors';
2020
import ScreenLogo from './Screens/ScreenLogo';
2121
import ScreenRoot from './Screens/ScreenRoot';
2222
import ScreenTypography from './Screens/ScreenTypography';
23+
import DashboardButton from './DashboardButton/DashboardButton';
2324

2425
/**
2526
* Main component that applies all customizations
@@ -85,6 +86,8 @@ const OnboardingDesignStudio = () => {
8586
</Navigator>
8687
</div>
8788
</PluginSidebar>
89+
90+
<DashboardButton />
8891
</>
8992
);
9093
};

0 commit comments

Comments
 (0)